pmacct-1.7.8/0000755000175000017500000000000014354105633012010 5ustar paolopaolopmacct-1.7.8/depcomp0000755000175000017500000005602014354105416013367 0ustar paolopaolo#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # 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 2, 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. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/install-sh0000755000175000017500000003577614354105415014034 0ustar paolopaolo#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # 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. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # 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_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly 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 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. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -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 By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " 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 *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi 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 if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi 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=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi 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. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # 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 # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # 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 oIFS=$IFS IFS=/ set -f set fnord $dstdir shift 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=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_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 && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $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` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # 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 "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$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 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/ltmain.sh0000755000175000017500000117716714354105411013651 0ustar paolopaolo#! /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 Debian-2.4.6-15" 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='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=2015-10-07.11; # 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 _G_rc_run_hooks=false 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 if eval $_G_hook '"$@"'; then # 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 _G_rc_run_hooks=: fi done $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, you may remove/edit # any options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. In this case you also must return $EXIT_SUCCESS to let the # hook's caller know that it should pay attention to # '_result'. Returning $EXIT_FAILURE signalizes that # arguments are left untouched by the hook and therefore caller will ignore the # result variable. # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). There is # # no need to do the equivalent (but slower) action: # # func_quote_for_eval ${1+"$@"} # # my_options_prep_result=$func_quote_for_eval_result # false # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # 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=: # args_changed=: # ;; # # 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 # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@", we could need that later # # if $args_changed is true. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # if $args_changed; then # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # fi # # $args_changed # } # 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." # # false # } # func_add_hook func_validate_options my_option_validation # # You'll also 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_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd _G_func_options_finish_exit=false if func_run_hooks func_options ${1+"$@"}; then func_options_finish_result=$func_run_hooks_result _G_func_options_finish_exit=: fi $_G_func_options_finish_exit } # 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 _G_rc_options=false for my_func in options_prep parse_options validate_options options_finish do if eval func_$my_func '${1+"$@"}'; then eval _G_res_var='$'"func_${my_func}_result" eval set dummy "$_G_res_var" ; shift _G_rc_options=: fi done # Save modified positional parameters for caller. As a top-level # options-parser function we always need to set the 'func_options_result' # variable (regardless the $_G_rc_options value). if $_G_rc_options; then func_options_result=$_G_res_var else func_quote_for_eval ${1+"$@"} func_options_result=$func_quote_for_eval_result fi $_G_rc_options } # 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 propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= _G_rc_options_prep=false if func_run_hooks func_options_prep ${1+"$@"}; then _G_rc_options_prep=: # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result fi $_G_rc_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= _G_rc_parse_options=false # 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. if func_run_hooks func_parse_options ${1+"$@"}; then eval set dummy "$func_run_hooks_result"; shift _G_rc_parse_options=: fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_match_parse_options=: _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) if test $# = 0 && func_missing_arg $_G_opt; then _G_rc_parse_options=: break fi 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 ;; --) _G_rc_parse_options=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac $_G_match_parse_options && _G_rc_parse_options=: done if $_G_rc_parse_options; then # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result fi $_G_rc_parse_options } # 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 _G_rc_validate_options=false # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" if func_run_hooks func_validate_options ${1+"$@"}; then # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result _G_rc_validate_options=: fi # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE $_G_rc_validate_options } ## ----------------- ## ## 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 $scriptversion Debian-2.4.6-15 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= _G_rc_lt_options_prep=: # 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 ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result fi $_G_rc_lt_options_prep } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _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 _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result fi $_G_rc_lt_parse_options } 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 # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC # -static-* direct GCC to link specific libraries statically # -fcilkplus Cilk Plus language extension features for C/C++ -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=*| \ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) 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%" test "X$link_all_deplibs" != Xno && libs="$libs $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" 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 elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi 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 ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; 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: pmacct-1.7.8/config.guess0000755000175000017500000012637314354105415014342 0ustar paolopaolo#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-24' # 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: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # 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. Options: -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-2018 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'`" # If ldd exists, use it to detect musl libc. if command -v ldd >/dev/null && \ ldd --version 2>&1 | grep -q ^musl then LIBC=musl fi ;; 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) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|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/[-_].*//' | cut -d. -f1,2` ;; 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 ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$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 ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 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 ;; 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:4.4BSD:*) 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` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac 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*: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 ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-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 "[:upper:]" "[:lower:]"``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 ;; k1om: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; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-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 ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-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:*:*) if objdump -f /bin/sh | grep -q elf32-x86-64; then echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 else echo "$UNAME_MACHINE"-pc-linux-"$LIBC" fi 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.*:*) 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 configure 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 ;; SX-ACE:SUPER-UX:*:*) echo sxace-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 # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc 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 ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-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 ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&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-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pmacct-1.7.8/UPGRADE0000644000175000017500000010313214354105275013024 0ustar paolopaoloUPGRAGE guidelines. pmacct is developed keeping an eye to backward compatibility: the upgrade to some newer version should be as smooth as possible from an user standpoint. However, sometimes the upgrade may require some operations aimed to support the changes done or break old assumptions no longer valid; while the effort is to keep these cases at a low, please read this file in preparation to upgrading your installation. TO: >= 1.7.8 FROM: <= 1.7.7 TOPIC: kafka_avro_schema_registry DESC: Until version 1.7.7 a custom "-value" string was forcingly appended to the schema name. This was non-standard practice and hence such practice has been terminated. TO: >= 1.7.8 FROM: <= 1.7.7 TOPIC: mpls_stack_depth primitive DESC: Support for the primitive has been removed. This has been coincidental with the introduction of the mpls_label_stack primitive, that exposes the full MPLS label stack, including its complex representation (on top of its stringy one), via the mpls_label_stack_encode_as_array configuration directive, in JSON and Apache Avro formats. TO: >= 1.7.8 FROM: <= 1.7.7 TOPIC: BGP, BMP message log / dumps & "label" field DESC: Until version 1.7.7, the output of BGP message logs / dumps would include MPLS labels, ie. as a result of a NLRI being part of a VPN, in the "label" field for both JSON and Avro encodings. In order to align naming convention with flow data plugins and to facilitate introduction of pre_tag_map support in BGP / BMP daemons (which output can be a "tag" or a "label" field), MPLS labels will now be encoded in the "mpls_label" field. TO: >= 1.7.7 FROM: <= 1.7.6 TOPIC: pmtelemetryd, JSON telemetry input and JSON daemon output DESC: Until version 1.7.6, JSON telemetry input data would be embedded as a 'telemetry_data' string part of the JSON daemon output along with some other meta-data. While this was useful, it was slightly not convenient as extracting actual content from 'telemetry_data' does require some (simple) scriptware in the middle; starting version 1.7.7, 'telemetry_data' is a JSON object (hence making the whole JSON daemon output nested) making it easier for consumers to parse the content. TO: >= 1.7.7 FROM: <= 1.7.6 TOPIC: Obsoleted features DESC: Following is the list of features, knobs and plugins that are being discontinued with release 1.7.7: * sql_history_since_epoch was removed from docs for a while; it is replaced by timestamps_since_epoch so that all timestamps-related config keys have the 'timestamps' suffix; * refresh_maps and pre_tag_map_entries were removed from docs for a while; they are replaced respectively by maps_refresh and maps_entries so that all maps-related config keys have the 'maps' suffix. * interface_wait and interface were removed from docs for a while; they are replaced respectively by pcap_interface_wait and pcap_interface so that all pmacctd / libpcap-related config keys have the 'pcap' suffix. TO: >= 1.7.6 FROM: <= 1.7.5 TOPIC: Obsoleted features DESC: Following is the list of features, knobs and plugins that are being discontinued with release 1.7.6: * Prefix labels, enabled with --enable-plabel configure switch, has been removed as now pre_tag_map supports a 'set_label' action to achieve the same. * sfacctd & timestamp_start aggregation primitive: sFlow does not include a timestamp as part of its header structure and a time is effectively created on arrival (timestamp_arrival). While this is still the case and timestamp_arrival is populated, timestamp_start will cease to be aliased over timestamp_arrival in order to avoid confusions. TO: >= 1.7.6 FROM: <= 1.7.5 TOPIC: Default nfprobe plugin protocol version DESC: Since its conception nfprobe plugin default export version has been 5. With IPFIX having been standardized back in 2013 with RFC7011 and being widely adopted by both exporters and collector, it is felt it is the right moment to switch the default version. On a sidenote, there are no plans to retire support for verdion 5. TO: >= 1.7.6 FROM: <= 1.7.5 TOPIC: BMP dump timestamps DESC: In order to align the namespace of timestamps to existing ones, ie. timestamp_start timestamp_end timestamp_arrival etc., the field 'event_timestamp' was renamed 'timestamp_event'. TO: >= 1.7.3 FROM: <= 1.7.2 TOPIC: BGP-related src primitives (ie. src_as_path) and JSON/Avro encoding DESC: Majority of these primitives were written in a 'src_' field, ie. src_as_path, contraddicting the prevailing name convention of other source/destination fields, ie. port_src, peer_ip_dst, etc.. These fields have now been aligned to the name convention - with src or dst qualifier at the end - and here is the full list of the fields modified: src_comms, src_ecomms, src_lcomms, src_med, src_as_path and src_local_pref; changed in: comms_src, ecomms_src, lcomms_src, med_src, as_path_src and local_pref_src respectively. TO: >= 1.7.3 FROM: <= 1.7.2 TOPIC: BGP attribute "origin" encoding change DESC: The "origin" attribute was encded as an integer, until 1.7.2. To make output more human-friendly, the encoding has been changed to string in 1.7.3, where three single-letter values are defined: IGP (i), EGP (e) and Incomplete (u). Only release 1.7 releases starting with 1.7.7 do feature a tmp_bgp_daemon_origin_type_int true/false configuration knob to revert to the old encoding in order to allow for smoother pre-1.7.3 upgrades. TO: >= 1.7.2 FROM: <= 1.7.1 TOPIC: Obsoleted features DESC: Following is the list of features, knobs and plugins that are being discontinued with release 1.7.2: * pre_tag_map: matching on 'sampling_rate' is not supported anymore since a sampling_rate primitive is available from version 0.14.2; the 'return' feature to return matched data before completing the map workflow has started the process of being obsolete (retired from docs but still available). * nfacctd: collection, processing and replication of NetFlow v1, v7 and v8 has been discontinued. The focus will remain on popular v5, v9 and IPFIX. * tee_plugin: tee_dissect_send_full_pkt was allowing to specify if, when dissecting replicated packets due to a complex pre_tag_map, to send (or not) the full packet. Now, in a simplification move, full packets are replicated only if no pre_tag_map is set or a simple pre_tag_map is defined. In the context of replication, in QUICKSTART is defined what is a simple and a complex pre_tag_map. * Kafka plugin: configuration directives kafka_avro_schema_topic and kafka_avro_schema_refresh_time allow to produce an Avro schema at regular time intervals to a topic; Confluent Platform supports an Avro schema registry which is the clean/preferred way to handle the distribution of schemas; as a result of this, the existing feature is made legacy and will be discontinued at the next major release and a new configuration directive kafka_avro_schema_registry is introduced. TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: nfprobe plugin, nfprobe_engine and NetFlow v9/IPFIX DESC: Until version 1.7.0 it was possible to (mistakenly) configure the NetFlow v9 SourceID field/IPFIX Observation Domain ID with the old NetFlow v5 jargon, ie. '1:1'. This is now threated as invalid and a positive 32-bit number, ie. '100000', is expected. If exporting NetFlow v5, nothing changed: the Engine ID/Engine Type input, ie. '1:1', is still valid and expected. TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: NetFlow/IPFIX/sFlow statistics via SIGUSR1 DESC: If using this feature, please note that there has been a change in the output format. Mainly: 1) agent stats are now one per line, 2) the stats format has been formalised a bit and 3) +++/--- separators are sent at the beginning and at the end of the output (not anymore one per agent). The new output looks as follows: NOTICE ( default/core ): +++ NOTICE ( default/core ): stats [0.0.0.0:2100] agent=X.X.X.X:0 time=1515772618 packets=1 bytes=496 seq_good=1 seq_jmp_fwd=0 seq_jmp_bck=0 NOTICE ( default/core ): stats [0.0.0.0:2100] agent=Y.Y.Y.Y:0 time=1515772618 packets=2 bytes=992 seq_good=2 seq_jmp_fwd=0 seq_jmp_bck=0 NOTICE ( default/core ): stats [0.0.0.0:2100] time=1515772618 discarded_packets=0 NOTICE ( default/core ): --- The old output was looking as follows: NOTICE ( default/core ): +++ NOTICE ( default/core ): NetFlow statistics collector=0.0.0.0:2100 agent=X.X.X.X:0 (1515772618): NOTICE ( default/core ): Datagrams: 1 NOTICE ( default/core ): Bytes: 496 NOTICE ( default/core ): Good datagrams: 1 NOTICE ( default/core ): Forward jumps: 0 NOTICE ( default/core ): Backward jumps: 0 NOTICE ( default/core ): --- NOTICE ( default/core ): +++ NOTICE ( default/core ): NetFlow statistics collector=0.0.0.0:2100 agent=Y.Y.Y.Y:0 (1515772618): NOTICE ( default/core ): Datagrams: 2 NOTICE ( default/core ): Bytes: 992 NOTICE ( default/core ): Good datagrams: 2 NOTICE ( default/core ): Forward jumps: 0 NOTICE ( default/core ): Backward jumps: 0 NOTICE ( default/core ): --- NOTICE ( default/core ): +++ NOTICE ( default/core ): Total bad NetFlow datagrams: 0 (1515772618) NOTICE ( default/core ): --- TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: Obsoleted features DESC: Following is the list of features, knobs and plugins that are being discontinued with release 1.7.1: * pkt_len_distrib primitive is discontinued due to apparent lack of interest; the primitive was meant to bucket packet/flow/sample lenghts in a distribution. Alternatively pre_tag_map can be used to achieve the same. Buckets could be defined as follows: set_tag=100 filter='ip[2:2] > 0 && ip[2:2] <= 512' set_tag=200 filter='ip[2:2] > 512 && ip[2:2] <= 1024' set_tag=300 filter='ip[2:2] > 1024 && ip[2:2] <= 9000' Then the 'tag' primiive will carry the defined packet size bucket. * BGP daemon offline code, ie. bgp_daemon_offline_* directives, has been deprecated in favor of alternative approaches, ie. BGP Looking Glass (bgp_daemon_lg_*) and BGP Xconnects (bgp_daemon_xconnect_*). * removed --enable-threads / --disable-threads configure switch to allow to compile pmacct even if no pthreads library is available. From this release support for threads is mandatory. TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: tag variables for dynamic Kafka topics and RabbitMQ routing keys. DESC: In an effort to harmonise variable names - and variable replacement functions - among the different plugins, $pre_tag has been renamed as $tag and $pre_tag2 as $tag2. TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: allow file, ie. nfacctd_allow_file and equivalents. DESC: Definition of IP prefixes is now supported and hence the 0.0.0.0/0 to allow all traffic in; whereas now an empty map rejects all input traffic. In previous releases an empty map would allow all traffic in instead and there was no way to simply reject all traffic. TO: >= 1.7.1 FROM: <= 1.7.0 TOPIC: pmacct IMT client and timestamps DESC: Timestamps (ie. timestamp_start, timestamp_end, timestamp_arrival primitives) are now formatted in a rfc3339 compliant way, ie. if UTC timezone yyyy-MM-ddTHH:mm:ss(.ss)Z. This break compatibility as in previous releases timestamps had a more liberal formatting. TO: >= 1.7.0 FROM: <= 1.6.2 TOPIC: Obsoleted features DESC: Following is the list of features, knobs and plugins that are being discontinued with release 1.7: * MongoDB plugin is being discontinued since the old Mongo API is not supported anymore and there has never been enough push from the community to transition to the new/current API (which would require a rewrite of most of the plugin) * Packet classification basing on the L7-filter project is being discontinued (ie. 'classifiers' directive). This is being replaced by an implementation basing on the nDPI project. As part of this also the sql_aggressive_classification knob has been discontinued. * tee_receiver was part of the original implementation of the tee plugin, allowing to forward to a single target and hence requiring multiple plugins instantiated, one per target. Since 0.14.3 this directive was effectively outdated by tee_receivers. * tmp_net_own_field knob was allowing to revert to backward compatible behaviour of IP prefixes (ie. src_net) being written in the same field as IP addresses (ie. src_host) * tmp_comms_same_field knob was allowing to revert to backward compatible behaviour of BGP communities (standard, extended) being writeen all in the same field. * plugin_pipe_amqp and plugin_pipe_kafka features were meant as an alternative to the homegrown queue solution for internal messaging, ie. passing data from the Core Process to Plugins, and are being discontinued. They are being replaced by a new implementation, plugin_pipe_zmq, basing on ZeroMQ. * plugin_pipe_backlog was allowing to keep an artificial backlog of data in the Core Process so for plugins to maximise bypass poll() syscalls in plugins. If home-grown queueing is found limiting, instead of falling back to such strategies, ZeroMQ queueing should be used. TO: >= 1.7.0 FROM: <= 1.6.2 TOPIC: change to sql_num_hosts DESC: When sql_num_hosts is enabled and pmacct is not compiled with --disable-ipv6, INET6_ATON() is now used for both IPv4 and IPv6 with MySQL and SQLite. Tables should be upgraded by changing columns from INT(4) to VARBINARY(16) and then converting data - for MySQL: ALTER TABLE table MODIFY COLUMN ip_src VARBINARY(16) NOT NULL; UPDATE table SET ip_src = INET6_ATON(INET_NTOA(ip_src)) WHERE INET_NTOA(ip_src) IS NOT NULL; This has performance implications which are mentioned in README.IPv6. TO: >= 1.6.2 FROM: <= 1.6.1 TOPIC: default plugin names DESC: Plugin names had to be unique per plugin type, meaning two plugins could be named "foobar" if they were of different type. Such behaviour has proven to lead to ambiguous scenarios and hence now plugin names must be globally unique. If not naming a plugin, its default name will now be "default_" instead of "default". Any piece of configuration that attaches directives to the "default" name, ie. relying on the assumption the plugin name defaults to "default", must be reviewed. TO: >= 1.6.2 FROM: <= 1.6.1 TOPIC: print_time_roundoff configuration directive suppressed DESC: The directive was renamed print_history_roundoff for consistency with other plugins. print_time_roundoff was already removed from documents for the past 3+ years. TO: >= 1.6.2 FROM: <= 1.6.1 TOPIC: sFlow probe (sfprobe plugin) and tags and class primitives DESC: Historically enterprise #8800 was squatted for the purpose of encoding pmacct-specific fields in sFlow, ie. tags and class. This never got changed when pmacct was assigned its own enterprise number (#43874) by IANA. In 1.6.2, these primitives are moved from #8800 to #43874 making older exports not compatible anymore. TO: >= 1.6.1 FROM: <= 1.6.0 TOPIC: BGP communities and AS-PATH DESC: In pmacct 1.6.1 BGP communities and AS-PATH primitives (ie. std_comm, ext_comm, as_path, etc.) were moved from being fixed length to the variable-length framework, allowing for very long lists of communities or paths to be integrally represented. The IMT plugin is excluded from this work and these primitives will still be fixed length. Also, these primitives are not going to be supported anymore in the formatted output (but they will be no problem in the CSV, JSON and Avro output formats) of the print plugin. Btw, the formatted output support for the print plugin will be eventually discontinued in future so it is good to move away from it. TO: >= 1.6.1 FROM: <= 1.6.0 TOPIC: BGP extended communities (ext_comm, src_ext_comm primitives) DESC: Some legacy decision (..) made BGP standard and extended communities be written to the same field, mutual excluding each other. This behaviour has now been changed with each community type being written to the own field. For backward compatibility purposes a temporary config directive has been introduced, tmp_comms_same_field, that - if set to true - does enable the old behaviour. The config directive will be removed at the next major release. TO: >= 1.6.1 FROM: <= 1.6.0 TOPIC: print_markers DESC: In the print plugin, start marker is now printed also in the case where print_output_file_append is set to true; also, markers are printed as a JSON object, if output is set to JSON. TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: uacctd switched from ULOG to NFLOG DESC: NFLOG supports both IPv4 and IPv6. While ULOG is still supported in recent kernels, NFLOG is supported since 2.6.14 and there is little point to support both - so a switch was made. The new daemon depends on the package libnetfilter-log-dev (in Debian/Ubuntu or equivalent in the prefered Linux distribution). For a quick test one can setup iptables to produce data in one of the following ways: * iptables -t mangle -I POSTROUTING -j NFLOG --nflog-group 4 * iptables -t raw -I PREROUTING -j NFLOG --nflog-group 4 And use the following command to collect data back: uacctd -c in_iface,out_iface,src_mac,dst_mac,src_host,dst_host,proto,src_port,dst_port -P print -g 4 TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: build system refreshed DESC: autoconf and automake from early 2000 were being used to compile the build system until 1.5.3. This was for the sake of simplicity and robustness and, of course, came with drawbacks: somebody wanting to touch the build system should know which version of the tools to use, no leverage of the latest and greatest advancements made in the last one and half decades. The switch for should be almost transparent, the only impact being how to supply information in case the build system is unable to determine location of libraries (ie. via pkg-config and checking "typical" locations like /usr/local/lib): taking as an example PostgreSQL, before --with-pgsql-libs and --with-pgsql-includes were to be used to supply path to library and headers respectively; now environment variables PGSQL_LIBS and PGSQL_CFLAGS should be used instead for the same purpose, ie.: PGSQL_LIBS="-L/usr/local/postgresql/lib -lpq" PGSQL_CFLAGS="-I/usr/local/postgresql/include" ./configure --enable-pgsql TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: nfacctd_disable_checks and sfacctd_disable_checks DESC: Default for this feature changed from false to true, ie. log warning messages for failing basic checks against incoming NetFlow/sFlow datagrams is disabled. For sequencing checks, the 'export_proto_seqno' primitive is recommended instead. TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: sql_recovery_logfile DESC: Feature removed from pmacct along with pmmyplay and pmpgplay logfile replay tools. TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: MongoDB C legagy driver releases <= 0.8 DESC: Support for MongoDB C legacy driver prior to 0.8 is dropped; in 0.8 release, the most current version of the legacy driver, there was an impacting change of API; unfortunately in mongo.h the version was not updated and it looks the legacy driver is not maintained anymore (so no chance to have the nit fixed). The only way out seemed to default to the 0.8 behaviour, as that is the one currently being downloaded from GitHub by users. TO: >= 1.6.0 FROM: <= 1.5.3 TOPIC: src_net and dst_net primitives DESC: Until 1.5.3 src_net and dst_net primitives value was written in the same field as src_host and dst_host - hence making the two sets mutual exclusive. This was found limiting by several users and, as a result of that, a separate field was added for storing networks (see "Increased memory usage by plugin caches" entry in this document). The use of such separate field had to be explicitely enabled by setting tmp_net_own_field configuration directive to true (by default set to false for backward compatibility); in version 1.6.0, tmp_net_own_field default value has now changed to true. tmp_net_own_field will be removed at the next major release. TO: >= 1.5.2 FROM: <= 1.5.1 TOPIC: --enable-ipv6 , IPv4-mapped IPv6 addresses & bindv6only DESC: Explicit support for IPv4-mapped IPv6 addresses was removed and now the bindv6only kind of behaviour is expected to be false (ie. both v4, via v4-mapped v6 addresses, and v6 addresses can connect to the v6 socket). On BSDs this is enforced in the code via a setsockopt() call; on Linux /proc/sys/net/ipv6/bindv6only is meant to enable/disable the feature. If binding to a "::" address (ie. no [sn]facctd_ip specified when pmacct is compiled with --enable-ipv6) no packets from IPv4 senders are not being received, then please check your bindv6only kernel setting. TO: >= 1.5.2 FROM: <= 1.5.1 TOPIC: sql_history_since_epoch DESC: The effect of configuration directive sql_history_since_epoch has been ported to encompass any timestamp in pmacct, ie. timestamp_start and timestamp_end primitives, nfacctd_stitching, sfacctd counters filename, etc. The directive has hence been renamed timestamps_since_epoch. The old name, sql_history_since_epoch, has been removed from documentation but it is still going to be accepted in the configuration until the next major release for the sake of backwards compatibility. TO: >= 1.5.1 FROM: <= 1.5.0 TOPIC: Increased memory usage by plugin caches DESC: Source and destination IP prefixes aggregaton primitives, src_net and dst_net, now feature a separate field so to not be mutually exclusive with aggregation over IP addresses, ie. src_host and dst_host. In 1.5 this can be optionally enabled by setting tmp_net_own_field to true; in later releases this behaviour will become default. The extra fields for IP prefixes do take additional memory in plugins cache - meaning values for pre-allocated cache enries, ie. print_cache_entries, if configured to tight to available resources might generate SEGV and have to be reviewed downward. TO: >= 1.5.0 FROM: <= 1.5.0rc3 TOPIC: nfprobe plugin, NetFlow v9 export and flow timestamps DESC: timestamps for nfprobe plugin NetFlow v9 export are now absolute and in msecs, using field types #152 and #153. timestamps_secs can be set to true in order to revert to timestamps relative and in secs, using fields types #21 and #22. TO: >= 1.5.0 FROM: <= 1.5.0rc3 TOPIC: nfprobe plugin, NetFlow/IPFIX exports and tag, tag2 primitives DESC: tag and tag2 primitives can now be exported by nfprobe plugin only using IPFIX transport (nfprobe_version: 10). This is because, being custom pmacct field types, they have moved inside pmacct PEN for a cleaner solution (PENs not being supported by NetFlow v9). TO: >= 1.5.0 FROM: <= 1.5.0rc3 TOPIC: NetFlow/IPFIX, print/AMQP/MongoDB plugins & time syncronization DESC: In 1.5.0 print/AMQP/MongoDB plugins are brought on par to SQL plugins by which flows/data with a future timestamp than the one currently being flushed is retained in the cache - to give further chances to in-memory data aggregation. This is intuitive, consistent behaviour but could happen time syncronization between collector and NetFlow/ IPFIX agents was not an issue and suddenly it appears pmacct is not writing to the backend anymore. Solution is simply to sync all via NTP and use same timezone (recommended UTC for all). TO: >= 1.5.0rc3 FROM: <= 1.5.0rc2 TOPIC: nfacctd, sfacctd & plugin_pipe_size DESC: nfacctd_pipe_size and sfacctd_pipe_size configuration directives are being introduced in order to set the socket size between the daemons and the kernel. Until 1.5.0rc2 the same was accomplished, the dirty way, via existing plugin_pipe_size config directive when assigned to the core process. If relying on this trick on 1.5.0rc2 and upgrading this can silently create packet loss on 1.5.0r3 and later (packet loss can be checked by veryfing that the counter showed by "netstat -s | grep Rcv" is not increasing). TO: >= 1.5.0rc3 FROM: <= 1.5.0rc2 TOPIC: MySQL plugin, additional libraries required when compiling DESC: MySQL 5.6 and later require linking against libstdc++ and librt. For this reason, when compiling MySQL plugin, it's now required that the development packages for these two libraries must be installed on the host system. Checks for this are introduced at configure script time. It is not checked which MySQL version is installed so the requirement for these libraries is made retroactive. TO: >= 1.5.0rc3 FROM: <= 1.5.0rc2 TOPIC: SQL plugins, agent_id2 field DESC: Over the years, agent_id, agent_id2 fields were found confusing to store tag, tag2 primitives respectively. agent_id is now renamed 'tag' and backwards compatibility is preserved by issuing schema version #9. agent_id2 is not defined in any sql_table_schema instead and hence its renaming will be disruptive for existing deployments. TO: >= 1.5.0rc2 FROM: <= 1.5.0rc1 TOPIC: print plugin, dynamic file names and pointer to latest file DESC: Until 1.5.0rc1 pointer to latest file available was built as "-latest". Possibility to build variable spool directory structure and introduction of primitives-related variables, ie. $peer_src_ip, do phase-out the simple way of producing pointers, jeopardizing backward compatibility aswell. From 1.5.0rc2 a print_latest_file configuration directive allows to explicitely define pointer(s) to latest file(s): please refer to CONFIG-KEYS for more details about the feature. When upgrading, it is recommended to delete existing symlinks. TO: >= 1.5.0rc2 FROM: <= 1.5.0rc1 TOPIC: print plugin, dynamic file names and time-related variables DESC: Time-related variables substitution is now based solely on the value of print_history. Previously, if print_history was not specified, this was based on the value of print_refresh_time. While this breaks backward- compatibility, it makes print plugin acting consistently to the rest of pmacct plugins. TO: >= 1.5.0rc1 FROM: <= 0.14.3 TOPIC: print plugin, no entries to print_output_file DESC: In line with SQL plugins, in case there are no entries to account for the last print_refresh_time period, the purge function will not be invoked. As a result of that, if print_output_file contains time-based variables and if required to, output files will not be created anymore in case of no traffic to account for. Until 0.14.3, under same conditions, an empty output file (title only in case of formatted, CSV output) would have been printed out. TO: >= 1.5.0rc1 FROM: <= 0.14.3 TOPIC: IPv6, peer_src_ip primitive, NetFlow exporter IP address DESC: Upon enabling IPv6 at compile time, via --enable-ipv6 switch, an IPv4 NetFlow exporter IP address, ie. 10.0.0.1, was being written as IPv4- mapped IPv6 address, ie. ::ffff:10.0.0.1. This was causing confusion when composing maps, ie. the 'ip' field would change depending on whether IPv6 was enabled or not. To make maps consistent and simplify transitions to IPv6 compiled pmacct executables, IPv4-mapped IPv6 addresses are now internally translated to plain IPv4 ones. TO: >= 0.14.3 FROM: <= 0.14.2 TOPIC: networks_file & host aggregation primitives DESC: In previous releases defining a networks_file in conjunction with host aggregation primitives would automatically work as a filter (ie. zero out hosts not included in the networks_file); whereas defining a networks_file in conjunction with net primitives would only work as a resolver. Now this behaviour has been streamlined by introducing a networks_file_filter true- false configuration directive to explicitely enable/disable the filtering feature (for both host and net primitives) on top of the resolver one. To summarize: if using a networks_file in conjunction with host aggregation primitives, and in order to keep the same behaviour while upgrading, a line should be added to the configuration: "networks_file_filter: true". TO: >= 0.14.3 FROM: <= 0.14.2 TOPIC: xlate_src and xlate_dst DESC: Feature has been obsoleted and replaced by proper aggregation primitives (nat_event, post_nat_*) to support NEL (NetFlow Event Logging) as currently implemented on Cisco ASR devices and to support CGNAT kind of scenarios. TO: >= 0.14.3 FROM: <= 0.14.2 TOPIC: nfacctd_sql_log DESC: Feature has been obsoleted and replaced by proper aggregation primitives (timestamp_start, timestamp_end) that effectively convert pmacct into a logger if enabled. TO: >= 0.14.0 FROM: <= 0.14.0rc3 TOPIC: peer_dst_ip DESC: The peer_dst_ip primitive is being attached to IP prefix resolution method (ie. as defined by nfacctd_net directive) from AS number resolution method in the past (ie. as defined by nfacctd_as_new directive). TO: >= 0.14.0 FROM: <= 0.14.0rc3 TOPIC: Fallback resolution of networks and ASNs (ie. nfacctd_net, nfacctd_as_new) DESC: Longest match wins has been introduced to select which route resolution method to use in fallback scenarios. For example up to 0.14.0rc3, a route advertised via BGP would have been winning over any more specific route learned via sFlow/NetFlow regardless. TO: >= 0.14.0rc3 FROM: <= 0.14.0rc2 TOPIC: is_symmetric DESC: Support for is_symmetric aggregation primitive has been ceased due to lack of interest from the general community. TO: >= 0.14.0rc3 FROM: <= 0.14.0rc2 TOPIC: peer_src_ip DESC: peer_src_ip primitive must represent a reference (IP address, Agent ID) of the NetFlow or sFlow emitter for a certain flow. Due to previous work, this primitive was connected to the [ns]facctd_as_new mechanism which, if set to 'bgp', was making it represent the IP address of a BGP peer instead. This is found not correct and hence peer_src_ip has now been disconnected from the [ns]facctd_as_new feature and always constitutes a reference to the NetFlow or sFlow emitter. TO: >= 0.14.0rc2 FROM: <= 0.14.0rc1 TOPIC: NetFlow v9 sampling DESC: Support for sampling in NetFlow v9 and IPFIX is elegant from an architecture point of view - but complex if compared to NetFlow v5 and sFlow for example. Such increased complexity lacking of proper framing by means of a supportive RFC exposes to bizzarre and creative implementations by vendors. 0.14.0rc2 introduces fixes and workarounds to its sampled NetFlow v9 support in an effort to tackle specific but popular platforms among operators - and which can result in breaking some backward compatibility in this sense. 0.14.0rc2 introduces a sampling_map feature, which although not rocket science from a concept point of view, it helps supporting sampled NetFlow v9 in heterogeneous network hardware environments at the cost of an extra static setting to care about; on the other hand it's also true sampling rates are often uniform and seldomly redefined in a production network. TO: >= 0.12.1 FROM <= 0.12.0 TOPIC: Data source for ASNs must be explicitely defined DESC: data source for 'src_as' and 'dst_as' primitives for nfprobe and sfprobe plugins is now expected to be explicitely defined via the [ pmacctd_as | uacctd_as ] directive. All other plugins were already working like that. In terms of backward compatibility the only case affected is getting ASN values out of a Networks File: up to 0.12.0, it was sufficient to define a networks_file to implicitely use it. TO: >= 0.12.0rc1 FROM: <= 0.11 TOPIC: agent_id size and SQL table schemas DESC: With release 0.12, the agent_id field becomes 4-bytes large (from 2-bytes previously). SQL table schemas have been updated accordingly. If running a previous release and upgrading, you might incur into the risk that both Pre/Post-tagging infrastructures will accept values up to ~4M while the underlying SQL table schema is configured with a 2-bytes field. Solution is to run an "ALTER TABLE" statement to increase the field size during a maintenance window. TO: >= 0.12.0rc1 FROM: <= 0.11 TOPIC: nfprobe plugin: NetFlow v9 and 32-bit ASNs DESC: Release 0.12 introduces support for 32-bit ASNs in pmacct; things do not change in NetFlow v5 as if a 32-bit ASN is encountered, it is written as AS23456. In NetFlow v9, though, the source and destination AS fields are specified as 4 bytes long in the template. Given the template nature of NetFlow v9, this shouldn't pose a problem with 3rd party implementations but it's better to pay some extra attention while upgrading an existing installation. TO: >= 0.10.0 FROM: <= 0.10.0rc3 TOPIC: Configuration directives and command-line options DESC: In all previous releases, commandline options ( ie. -D -c ) were mutually exclusive with respect to configuration directives; now, they can cohexist and, more specifically, commandline options will override the content of the configuration file. This exposes to more interesting usages: shell> pmacctd -I -f to launch pmacctd sharing an unique configuration file while reading data from different tcpdump/ethereal tracefiles among multiple runs. TO: >= 0.8.3 FROM: <= 0.8.2 TOPIC: Pre-Tagging, Post-Tagging DESC: In all previous releases, the 'pre_tag_map' and 'post_tag' directives were causing the captured traffic to be automatically tagged while forwarded to each active plugin; this behaviour can result in reduced flexibility; the 0.8.3 release makes the two forementioned directives just to evaluate the tag to be assigned to captured traffic; a new 'aggregate' directive keyword - tag - causes the traffic to be marked (basing on the previous evaluation). So, a configuration like the following: ... pre_tag_map: /usr/local/pmacct/pre_tag.map aggregate[dummy]: src_host,dst_host,src_port,dst_port ... Have to be rewritten the following way in order for the plugin 'dummy' to receive the tags: ... pre_tag_map: /usr/local/pmacct/pre_tag.map aggregate[dummy]: tag,src_host,dst_host,src_port,dst_port ... [EOF] pmacct-1.7.8/autogen.sh0000755000175000017500000000420414354105275014013 0ustar paolopaolo#!/bin/sh set -e case "$(uname)" in Darwin) LIBTOOLIZE=${LIBTOOLIZE:-glibtoolize} ;; *) LIBTOOLIZE=${LIBTOOLIZE:-libtoolize} ;; esac AUTORECONF=${AUTORECONF:-autoreconf} ACLOCAL=${ACLOCAL:-aclocal} AUTOCONF=${AUTOCONF:-autoconf} AUTOHEADER=${AUTOHEADER:-autoheader} AUTOMAKE=${AUTOMAKE:-automake} # Check we have all tools installed check_command() { command -v "${1}" > /dev/null 2>&1 || { >&2 echo "autogen.sh: could not find \`$1'. \`$1' is required to run autogen.sh." exit 1 } } check_command "$LIBTOOLIZE" check_command "$AUTORECONF" check_command "$ACLOCAL" check_command "$AUTOCONF" check_command "$AUTOHEADER" check_command "$AUTOMAKE" # Absence of pkg-config or misconfiguration can make some odd error # messages, we check if it is installed correctly. See: # https://blogs.oracle.com/mandy/entry/autoconf_weirdness # # We cannot just check for pkg-config command, we need to check for # PKG_* macros. The pkg-config command can be defined in ./configure, # we cannot tell anything when not present. check_pkg_config() { grep -q '^AC_DEFUN.*PKG_CHECK_MODULES' aclocal.m4 || { cat <&2 autogen.sh: could not find PKG_CHECK_MODULES macro. Either pkg-config is not installed on your system or \`pkg.m4' is missing or not found by aclocal. If \`pkg.m4' is installed at an unusual location, re-run \`autogen.sh' by setting \`ACLOCAL_FLAGS': ACLOCAL_FLAGS="-I /share/aclocal" ./autogen.sh EOF exit 1 } } echo "autogen.sh: reconfigure with autoreconf" ${AUTORECONF} -vif -I m4 || { echo "autogen.sh: autoreconf has failed ($?), let's do it manually" [ -f ./configure.ac ] || [ -f ./configure.in ] || continue echo "autogen.sh: configure `basename $PWD`" ${ACLOCAL} -I m4 ${ACLOCAL_FLAGS} check_pkg_config ${LIBTOOLIZE} --automake --copy --force ${ACLOCAL} -I m4 ${ACLOCAL_FLAGS} ${AUTOCONF} --force ${AUTOHEADER} ${AUTOMAKE} --add-missing --copy --force-missing } bin/configure-help-replace.sh echo "autogen.sh: for the next step, run './configure' [or './configure --help' to check available options]" exit 0 pmacct-1.7.8/config.sub0000755000175000017500000010645014354105415013777 0ustar paolopaolo#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-22' # 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: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # 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 or ALIAS Canonicalize a configuration name. Options: -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-2018 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* | cloudabi*-eabi* | \ 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/'` ;; -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 \ | ba \ | 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 | ia16 | 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 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]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 \ | wasm32 \ | 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) ;; 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]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | 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-* | ia16-* | 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-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | 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-* \ | wasm32-* \ | 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-pc 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 ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; 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*) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=$os"spe" ;; 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 ;; 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 ;; 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 ;; 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 ;; nsv-tandem) basic_machine=nsv-tandem ;; nsx-tandem) basic_machine=nsx-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) 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) 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 ;; sh5el) basic_machine=sh5le-unknown ;; 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 ;; x64) basic_machine=x86_64-pc ;; 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 ;; 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 ;; 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 ;; 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 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) -es1800*) os=-ose ;; # Now 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* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -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* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ | -midnightbsd*) # 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 | -xray | -os68k* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* \ | -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 ;; -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 ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. case $basic_machine in arm*) os=-eabi ;; *) os=-elf ;; esac ;; -nacl*) ;; -ios) ;; -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 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-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 ;; *-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-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pmacct-1.7.8/CONFIG-KEYS0000644000175000017500000057675614354105275013505 0ustar paolopaoloSUPPORTED CONFIGURATION KEYS Both configuration directives and commandline switches are listed below. A configuration consists of key/value pairs, separated by the ':' char. Starting a line with the '!' symbol, makes the whole line to be ignored by the interpreter, making it a comment. Please also refer to QUICKSTART document and the 'examples/' sub-tree for some examples. Directives are sometimes grouped, like sql_table and print_output_file: this is to stress if multiple plugins are running as part of the same daemon instance, such directives must be casted to the plugin they refer to - in order to prevent undesired inheritance effects. In other words, grouped directives share the same field in the configuration structure. LEGEND of flags: GLOBAL Can't be configured on individual plugins NO_GLOBAL Can't be configured globally NO_PMACCTD Does not apply to pmacctd NO_UACCTD Does not apply to uacctd NO_NFACCTD Does not apply to nfacctd NO_SFACCTD Does not apply to sfacctd NO_PMBGPD Does not apply to pmbgpd NO_PMBMPD Does not apply to pmbmpd ONLY_PMACCTD Applies only to pmacctd ONLY_UACCTD Applies only to uacctd ONLY_NFACCTD Applies only to nfacctd ONLY_SFACCTD Applies only to sfacctd ONLY_PMBGPD Applies only to pmbgpd ONLY_PMBMPD Applies only to pmbmpd MAP Indicates the input file is a map LIST OF DIRECTIVES: KEY: debug (-d) VALUES: [ true | false ] DESC: Enables debug (default: false). KEY: debug_internal_msg VALUES: [ true | false ] DESC: Extra flag to enable debug of internal messaging between Core process and plugins. It has to be enabled on top of 'debug' (default: false). KEY: daemonize (-D) [GLOBAL] VALUES: [ true | false ] DESC: Daemonizes the process (default: false). KEY: aggregate (-c) VALUES: [ src_mac, dst_mac, vlan, in_vlan, out_vlan, cos, etype, src_host, dst_host, src_net, dst_net, src_mask, dst_mask, src_as, dst_as, src_port, dst_port, tos, proto, none, sum_mac, sum_host, sum_net, sum_as, sum_port, flows, tag, tag2, label, class, tcpflags, in_iface, out_iface, std_comm, ext_comm, lrg_comm, as_path, peer_src_ip, peer_dst_ip, peer_src_as, peer_dst_as, local_pref, med, dst_roa, src_std_comm, src_ext_comm, src_lrg_comm, src_as_path, src_local_pref, src_med, src_roa, mpls_vpn_rd, mpls_pw_id, mpls_label_top, mpls_label_bottom, mpls_label_stack, sampling_rate, sampling_direction, src_host_country, dst_host_country, src_host_pocode, dst_host_pocode, src_host_coords, dst_host_coords, nat_event, fw_event, post_nat_src_host, post_nat_dst_host, post_nat_src_port, post_nat_dst_port, tunnel_src_mac, tunnel_dst_mac, tunnel_src_host, tunnel_dst_host, tunnel_proto, tunnel_tos, tunnel_src_port, tunnel_dst_port, tunnel_tcpflags, fwd_status, vxlan, timestamp_start, timestamp_end, timestamp_arrival, timestamp_export, export_proto_seqno, export_proto_version, export_proto_sysid ] FOREWORDS: Individual IP packets are uniquely identified by their header field values (a rather large set of primitives!). Same applies to uni-directional IP flows, as they have at least enough information to discriminate where packets are coming from and going to. Aggregates are instead used for the sole purpose of IP accounting and hence can be identified by an arbitrary set of primitives. The process to create an aggregate starting from IP packets or flows is: (a) select only the primitives of interest (generic aggregation), (b) optionally cast certain primitive values into broader logical entities, ie. IP addresses into network prefixes or Autonomous System Numbers (spatial aggregation) and (c) sum aggregate bytes/flows/packets counters when a new tributary IP packet or flow is captured (temporal aggregation). DESC: Aggregate captured traffic data by selecting the specified set of primitives. sum_ are compound primitives which sum ingress/egress traffic in a single aggregate; current limit of sum primitives: each sum primitive is mutual exclusive with any other, sum and non-sum, primitive. The 'none' primitive allows to make a single grand total aggregate for traffic flowing through. 'tag', 'tag2' and 'label' generates tags when tagging engines (pre_tag_map, post_tag) are in use. 'class' enables L7 traffic classification. NOTES: * List of the aggregation primitives available to each specific pmacct daemon, along with their description, is available via -a command-line option, ie. "pmacctd -a". * Some primitives (ie. tag2, timestamp_start, timestamp_end) are not part of any default SQL table schema shipped. Always check out documentation related to the RDBMS in use (ie. 'sql/README.mysql') which will point you to extra primitive-related documentation, if required. * peer_src_ip, peer_dst_ip: two primitives with an obscure name conceived to be as generic as possible due to the many different use-cases around them: peer_src_ip is the IP address of the node exporting NetFlow/IPFIX or sFlow; peer_dst_ip is the BGP next-hop or IP next-hop (if use_ip_next_hop is set to true). * sampling_rate: if counters renormalization (ie. sfacctd_renormalize) is enabled this field will report a value of one (1); otherwise it will report the rate that is passed by the protocol or sampling_map. A value of zero (0) means 'unknown' and hence no rate is applied to original counter values. * src_std_comm, src_ext_comm, src_lrg_comm, src_as_path are based on reverse BGP lookups; peer_src_as, src_local_pref and src_med are by default based on reverse BGP lookups but can be alternatively based on other methods, for example maps (ie. bgp_peer_src_as_type). Internet traffic is by nature asymmetric hence reverse BGP lookups must be used with caution (ie. against own prefixes). * mpls_label_top, mpls_label_bottom primitives only include the MPLS label value, stripped of EXP code-points (and BoS flag). Visibiliy in EXP values can be achieved by defining a custom primitive to extract the full 3 bytes, ie. 'name=mplsFullTopLabel field_type=70 len=3 semantics=raw' for NetFlow/ IPFIX. On the contrary mpls_label_stack does extract the full 3 bytes. * timestamp_start, timestamp_end and timestamp_arrival let pmacct act as a traffic logger up to the msec level (if reported by the capturing method). timestamp_start records NetFlow/IPFIX flow start time or observation; timestamp_end records NetFlow/IPFIX flow end time; timestamp_arrival records libpcap packet timestamp and sFlow/NetFlow/IPFIX packet arrival time at the collector. Historical accounting (enabled by the *_history config directives, ie. kafka_history) finest granularity for time-bins is 1 minute: timestamp_start can be used for finer greater granularitiies, ie. second (timestamps_secs set to true) or sub-second. * tcpflags: in pmacctd, uacctd and sfacctd daemons TCP flags are ORed until the aggregate is flushed - hence emulating the behaviour of NetFlow/IPFIX. If a flag analysis is needed, packets with different flags (combinations) should be isolated using a pre_tag_map/pre_tag_filter or aggregate_filter features (see examples in QUICKSTART and review libpcap filtering syntax via pcap-filter man page). * export_proto_seqno reports about export protocol (NetFlow, sFlow, IPFIX) sequence number and can be very relevant to detect packet loss. nfacctd and sfacctd do perform simple non-contextual sequencing checks but these are mainly limited to check out-of-order situations; proper contextual checking can be performed as part of post-processing. A specific plugin instance, separate from the main / accounting one, can be configured with 'aggregate: export_proto_seqno' for the task. An example of a simple check would be to find min/max sequence numbers, compute their difference and make sure it does match to the amount of entries in the interval; the check can be then windowed over time by using timestamps (ie. 'timestamp_export' primitive and/or *_history config directives). * timestamp_export is the observation time at the exporter. This is only relevant in export protocols involving caching, ie. NetFlow/IPFIX. In all other cases this would not be populated or be equal to timestamp_start. * In nfacctd, undocumented aggregation primitive class_frame allows to apply nDPI clssification to NFv9/IPFIX packets with IE 315 (dataLinkFrameSection). class primitive instead allows to leverage traditional classification using NetFlow v9/IPFIX IE 94, 95 and 96 (applicationDescription, applicationId and applicationName). * vlan / in_vlan / out_vlan: in NetFlow / IPFIX and sFlow, where there is indication (explicit or implicit, ie. expressing sample direction) of ingress / egress sampling, 'vlan' checks both cases reporting the VLAN ID of the first case checked reporting a non-zero ID (ingress > egress); more intuitively, in_vlan reports ingress VLAN ID if any and out_vlan reports egress VLAN ID if any. DEFAULT: src_host KEY: aggregate_primitives [GLOBAL, MAP] DESC: Expects full pathname to a file containing custom-defined primitives. Once defined in this file, primitives can be used in 'aggregate' statements. The feature is currently available only in nfacctd, for NetFlow v9/IPFIX, pmacctd and uacctd. Examples are available in 'examples/primitives.lst.example'. This map does not support reloading at runtime. DEFAULT: none KEY: aggregate_filter [NO_GLOBAL, NO_UACCTD] DESC: Per-plugin filtering applied against the original packet or flow. Aggregation is performed slightly afterwards, upon successful match of this filter. By binding a filter, in tcpdump syntax, to an active plugin, this directive allows to select which data has to be delivered to the plugin and aggregated as specified by the plugin 'aggregate' directive. See the following example: ... aggregate[inbound]: dst_host aggregate[outbound]: src_host aggregate_filter[inbound]: dst net 192.168.0.0/16 aggregate_filter[outbound]: src net 192.168.0.0/16 plugins: memory[inbound], memory[outbound] ... This directive can be used in conjunction with 'pre_tag_filter' (which, in turn, allows to filter tags). You will also need to force fragmentation handling in the specific case in which a) none of the 'aggregate' directives is including L4 primitives (ie. src_port, dst_port) but b) an 'aggregate_filter' runs a filter which requires dealing with L4 primitives. For further information, refer to the 'pmacctd_force_frag_handling' directive. DEFAULT: none KEY: aggregate_unknown_etype [GLOBAL] VALUES: [ true | false ] DESC: By default, Ethernet frames with unknown EtherTypes for which pmacct has not implemented decoding support are ignored by the aggregation engine. Enabling this option allows such frames to be aggregated by the available Ethernet L2 header fields ('src_mac', 'dst_mac', 'vlan', 'cos', 'etype'). DEFAULT: false KEY: dtls_path [GLOBAL] DESC: Full path to a directory containing files needed to establish a successful DTLS session (key, certificate and CA file); a key.pem file can be generated with the "certtool --generate-privkey --outfile key.pem" command-line; a self-signed cert.pem certificate, having previously created the key, can be generated with the "certtool --generate-self-signed --load-privkey key.pem --outfile cert.pem" command-line; the ca-certificates.crt CA file can be copied from (ie. on Debian or Ubuntu) "/etc/ssl/certs/ca-certificates.crt". DEFAULT: none KEY: writer_id_string DESC: A "writer_id" field is added when sending data onto a Kafka or RabbitMQ broker, this is meant to add contextual information about the collector producing data (ie. $proc_name) or the specific batch of data (ie. PID of the writer process, $writer_pid). Additional static information and separators can be supplied as part of the string. Some variables are supported: $proc_name The name of the process producing data. This maps to the plugin name in case of 'kafka' and 'amqp' plugins and core_proc_name when the write is made from the Core Process, ie. BGP, BMP and Streaming Telemetry cases $writer_pid The PID of the process producing data $pmacct_build The build version of the collector producing data Note: The '_' character is part of the variables alphabet not hence it isn't a valid separator between any two variables and between any variable and static text. It can only used as part of variables, like the ones defined above, or static text. DEFAULT: $proc_name/$writer_pid KEY: pcap_filter [GLOBAL, PMACCTD_ONLY, ONLY_PMBMPD] DESC: This filter is global and applied to all incoming packets. It's passed to libpcap and expects libpcap/tcpdump filter syntax. Being global it doesn't offer a great flexibility but it's the fastest way to drop unwanted traffic. DEFAULT: none KEY: pcap_protocol [GLOBAL, PMACCTD_ONLY] DESC: If set, specifies a specific packet socket protocol value to limit packet capture to (for example, 0x0800 = IPv4). This option is only supported if pmacct was built against a version of libpcap that supports pcap_set_protocol(). DEFAULT: none KEY: pcap_arista_trailer_offset [GLOBAL, PMACCTD_ONLY] DESC: Arista does set a trailer structure to convey extra info (ie. output interface, etc.) when mirroring packets. This knob sets the byte offset from the end of the packet to indicate where the trailer starts. DEFAULT: none KEY: pcap_arista_trailer_flag_value [GLOBAL, PMACCTD_ONLY] DESC: When 'pcap_arista_trailer_offset' is set, specify the expected value in the arista trailer flag field that indicates the output interface is present (this varies by chipset). DEFAULT: 1 KEY: snaplen (-L) [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Specifies the maximum number of bytes to capture for each packet. This directive has key importance to both classification and connection tracking engines. In fact, some protocols (mostly text-based eg.: RTSP, SIP, etc.) benefit of extra bytes because they give more chances to successfully track data streams spawned by control channel. But it must be also noted that capturing larger packet portion require more resources. The right value need to be traded-off. In case classification is enabled, values under 200 bytes are often meaningless. 500-750 bytes are enough even for text based protocols. Default snaplen value is OK if classification is disabled. DEFAULT: 128 bytes KEY: plugins (-P) [GLOBAL] VALUES: [ memory | print | mysql | pgsql | sqlite3 | nfprobe | sfprobe | tee | amqp | kafka ] DESC: Plugins to be enabled. memory, print, nfprobe, sfprobe and tee plugins are always compiled in pmacct executables as they do not have external dependencies. Database (ie. RDBMS, noSQL) and messaging ones (ie. amqp, kafka) do have external dependencies and hence are available only if explicitely configured and compiled (see QUICKSTART). 'memory' plugin uses a memory table as backend and a client tool, 'pmacct', can fetch the memory table content; the memory plugin is only good to prototype solutions, lab environment without mass traffic generation and small/home production environments. mysql, pgsql and sqlite3 plugins do output respectively to MySQL (or MariaDB via the MySQL-compatible C API), PostgreSQL and SQLite 3.x (or BerkeleyDB 5.x via the SQLite API compiled-in) databases to store data. 'print' plugin prints output data to flat- files or stdout in JSON, Apache Avro, CSV or tab-spaced encodings. 'amqp' and 'kafka' plugins allow to output data to RabbitMQ and Kafka brokers respectively. All these plugins - to output to stdout, files, RDBMS and messaging brokers - are suitable for production solutions and/or larger scenarios. 'nfprobe' plugin is a NetFlow/IPFIX agent and exports collected data via NetFlow v5/ v9 and IPFIX datagrams to a remote collector. 'sfprobe' plugin is a sFlow agent and exports collected data via sFlow v5 datagrams to a remote collector. Both 'nfprobe' and 'sfprobe' plugins can be run only via pmacctd and uacctd daemons (in other words no collect NetFlow v5 / re-export IPFIX and similar trans-codings are supported). The 'tee' plugin is a replicator of NetFlow/IPFIX/sFlow data (also transparent); it can be run only via nfacctd and sfacctd. Plugins can be either anonymous or named; configuration directives can be global or bound to a specific plugins when named. An anonymous plugin is declared as 'plugins: mysql' in the config whereas a named plugin is declared as 'plugins: mysql[name]'. Then directives can be bound to a specific named plugin as: 'directive[name]: value'. DEFAULT: memory KEY: [ nfacctd_pipe_size | sfacctd_pipe_size | pmacctd_pipe_size ] [GLOBAL, NO_UACCTD] DESC: Defines the size of the kernel socket to read traffic data. The socket is highlighted below with "XXXX": XXXX [network] ----> [kernel] ----> [core process] ----> [plugin] ----> [backend] [__________pmacct___________] On Linux systems, if this configuration directive is not specified default socket size awarded is defined in /proc/sys/net/core/[rw]mem_default ; the maximum configurable socket size is defined in /proc/sys/net/core/[rw]mem_max instead. Still on Linux, the "drops" field of /proc/net/udp or /proc/net/udp6 can be checked to ensure its value is not increasing. DEFAULT: Operating System default KEY: [ bgp_daemon_pipe_size | bmp_daemon_pipe_size ] [GLOBAL] DESC: Defines the size of the kernel socket used for BGP and BMP messaging. The socket is highlighted below with "XXXX": XXXX [network] ----> [kernel] ----> [core process] ----> [plugin] ----> [backend] [__________pmacct___________] On Linux systems, if this configuration directive is not specified default socket size awarded is defined in /proc/sys/net/core/rmem_default ; the maximum configurable socket size (which can be changed via sysctl) is defined in /proc/sys/net/core/rmem_max instead. DEFAULT: Operating System default KEY: plugin_pipe_size DESC: Core Process and each of the plugin instances are run into different processes. To exchange data, they set up a circular queue (home-grown implementation, referred to as 'pipe') and highlighted below with "XXXX": XXXX [network] ----> [kernel] ----> [core process] ----> [plugin] ----> [backend] [__________pmacct___________] This directive sets the total size, in bytes, of such queue. Its default size is set to 4MB. Whenever facing heavy traffic loads, this size can be adjusted to hold more data. In the following example, the queue between the Core process and the plugin 'test' is set to 10MB: ... plugins: memory[test] plugin_pipe_size[test]: 10240000 ... When enabling debug, log messages about obtained and target pipe sizes are printed. If obtained is less than target, it could mean the maximum socket size granted by the Operating System has to be increased. On Linux systems default socket size awarded is defined in /proc/sys/net/core/[rw]mem_default ; the maximum configurable socket size (which can be changed via sysctl) is defined in /proc/sys/net/core/[rw]mem_max instead. In case of data loss messages containing the "missing data detected" string will be logged - indicating the plugin affected and current settings. Alternatively see at plugin_pipe_zmq and plugin_pipe_zmq_profile. DEFAULT: 4MB KEY: plugin_buffer_size DESC: By defining the transfer buffer size, in bytes, this directive enables buffering of data transfers between core process and active plugins. Once a buffer is filled, it is delivered to the plugin. Setting a larger value may improve throughput (ie. amount of CPU cycles required to transfer data); setting a smaller value may improve latency, especially in scenarios with little data influx. It is disabled by default. If used with the home-grown circular queue implemetation, the value has to be minor/equal to the size defined by 'plugin_pipe_size' and keeping a ratio between 1:100 and 1:1000 among the two is considered good practice; the circular queue of plugin_pipe_size size is partitioned in chunks of plugin_buffer_size. Alternatively see at plugin_pipe_zmq and plugin_pipe_zmq_profile. DEFAULT: Set to the size of the smallest element to buffer KEY: plugin_pipe_zmq VALUES: [ true | false ] DESC: By defining this directive to 'true', a ZeroMQ queue is used for queueing and data exchange between the Core Process and the plugins. This is in alternative to the home-grown circular queue implementation (see plugin_pipe_size description). This directive, along with all other plugin_pipe_zmq_* directives, can be set globally or be applied on a per plugin basis (ie. it is a valid scenario, if multiple plugins are instantiated, that some make use of home-grown queueing, while others use ZeroMQ based queueing). For a quick comparison: while relying on a ZeroMQ queue introduces an external dependency, ie. libzmq, it reduces the bare minimum the need of settings of the home-grown circular queue implementation. See QUICKSTART for some examples. DEFAULT: false KEY: plugin_pipe_zmq_retry DESC: Defines the interval of time, in seconds, after which a connection to the ZeroMQ server (Core Process) should be retried by the client (Plugin) after a failure is detected. DEFAULT: 60 KEY: plugin_pipe_zmq_profile VALUES: [ micro | small | medium | large | xlarge ] DESC: Allows to select some standard buffering profiles. Following are the recommended buckets in flows/samples/packets per second (the configured buffer value is reported in brackets and is meant only to facilitate transitioning existing deployments from plugin_buffer_size): micro : up to 1K (0KB) small : from 1K to 10-15K (10KB) medium : from 10-10K to 100-125K (100KB) large : from 100-125K to 250K (1MB) xlarge : from 250K (10MB) A symptom that the selected profile may be undersized is the missing data warnings appearing in the logs; a symptom it is oversized instead is the latency in data being purged out: in fact the buffer has to fill up in order to be released to the plugin. The amount of flows/samples per second can be estimated as described in Q21 in the FAQS document; 'large' and 'xlarge' (and possibly also 'medium') profiles may be counter-productive in case of a 'tee' plugin: excessive burstiness may cause UDP drops due to small default kernel buffers. Should no profile fit the sizing, the buffering value can be customised using the plugin_buffer_size directive. DEFAULT: micro KEY: plugin_pipe_zmq_hwm DESC: Defines the messages high watermark, that is, "The high water mark is a hard limit on the maximum number of outstanding messages ZeroMQ shall queue in memory for any single peer that the specified socket is communicating with. A value of zero means no limit.". If configured, upon reaching the set watermark value, exceeding data will be discaded and an error log message will be output. DEFAULT: 0 KEY: plugin_exit_any VALUES: [ true | false ] DESC: Daemons gracefully shut down (core process and all plugins) if either the core process or all the registered plugins bail out. Setting this to true makes the daemon to gracefully shut down in case any single one of the plugins bails out and regardless there may be more plugins still active. DEFAULT: false KEY: propagate_signals [GLOBAL] VALUES: [ true | false ] DESC: When a signal is sent to the Core Process, propagate it to all active plugins; this may come handy in scenarios where pmacct is run inside a (Docker) container. DEFAULT: false KEY: files_umask DESC: Defines the mask for newly created files (log, pid, etc.) and their related directory structure. A mask less than "002" is not accepted due to security reasons. DEFAULT: 077 KEY: files_uid DESC: Defines the system user id (UID) for files opened for writing (log, pid, etc.); this is indeed possible only when running the daemon as super-user. This is also applied to any intermediary directory structure which might be created. Both user string and id are valid input. DEFAULT: Operating System default (current user UID) KEY: files_gid DESC: Defines the system group id (GID) for files opened for writing (log, pid, etc.); this is indeed possible only when running the daemon as super-user; this is also applied to any intermediary directory structure which might be created. Both group string and id are valud input. DEFAULT: Operating System default (current user GID) KEY: pcap_interface (-i) [GLOBAL, PMACCTD_ONLY] DESC: Interface on which 'pmacctd' listens. If such directive isn't supplied, a libpcap function is used to select a valid device. [ns]facctd can catch similar behaviour by employing the [ns]facctd_ip directives; also, note that this directive is mutually exclusive with 'pcap_savefile' (-I). DEFAULT: Interface is selected by by the Operating System KEY: pcap_interface_wait (-w) [GLOBAL, PMACCTD_ONLY] VALUES: [ true | false ] DESC: If set to true, this option causes 'pmacctd' to wait for the listening device to become available; it will try to open successfully the device each few seconds. Whenever set to false, 'pmacctd' will exit as soon as any error (related to the listening interface) is detected. DEFAULT: false KEY: pcap_savefile (-I) [GLOBAL, NO_UACCTD, NO_PMBGPD] DESC: File in libpcap savefile format to read data from (as an alternative to live data collection). As soon as the daemon finished processing the file, it exits (unless in pmacctd the 'pcap_savefile_wait' config directive is specified). The directive is mutually exclusive with reading live traffic (ie. pcap_interface (-i) for pmacctd, [ns]facctd_ip (-L) and [ns]facctd_port (-l) for nfacctd and sfacctd respectively, bmp_daemon_ip for pmbmpd). If using a traffic daemon (ie. nfacctd) with a BMP thread (ie. bmp_daemon: true) and wanting to feed both with a savefile, only one file can be supplied (that is, only a single pcap_savefile can be specified in the config): if having multiple files, ie. one with traffic data and one with BMP data, these can be merged using, for example, Wireshark which offers options to prepend, merge chronologically and append data. Note: reading libpcap savefiles does use the cap_next_ex() call which seems not to be highly portable, ie. a capture produced on a Linux does not always read on a MacOS. DEFAULT: none KEY: pcap_savefile_wait (-W) [GLOBAL, NO_UACCTD, NO_PMBGPD] VALUES: [ true | false ] DESC: If set to true, this option will cause the daemon to wait indefinitely for a signal (ie. CTRL-C when not daemonized or 'killall -9 pmacctd' if it is) after being finished processing the supplied libpcap savefile (pcap_savefile). This is particularly useful when inserting fixed amounts of data into memory tables. DEFAULT: false KEY: pcap_savefile_delay (-Z) [GLOBAL, NO_UACCTD, NO_PMBGPD] DESC: When reading from a pcap_savefile, sleep for the supplied amount of seconds before (re)playing the file. For example this is useful to let a BGP session be established and a RIB be finalised before playing a given file or buy time among replays so for a dump event to trigger. DEFAULT: 0 KEY: pcap_savefile_replay (-Y) [GLOBAL, NO_UACCTD, NO_PMBGPD] DESC: When reading from a pcap_savefile, replay content for the specified amount of times. Other than for testing in general, this may be useful when playing templated-based protocols, ie. NetFlow v9/IPFIX, to replay data packets that could not be parsed the first time due to the template not being sent yet. DEFAULT: 1 KEY: [ pcap_direction | uacctd_direction ] [GLOBAL, ONLY_PMACCTD, ONLY_UACCTD] VALUES: [ "in", "out" ] DESC: Defines the traffic capturing direction with two possible values, "in" and "out". In pmacctd this is used to 1) determine which primitive to populate, whether in_iface or out_iface with the pcap_ifindex value and 2) tag / filter data basing on direction in pre_tag_map. Not all platforms do support pcap_set_direction() and a quick test is to check if tcpdump, ie. 'tcpdump -i -Q in', does work as intended. In uacctd the only functionality is the latter of the two use-cases. DEFAULT: none KEY: pcap_ifindex [GLOBAL, PMACCTD_ONLY] VALUES: [ "sys", "hash", "map", "none" ] DESC: Defines how to source the ifindex of the capturing interface. If "sys" then a if_nametoindex() call is triggered to the underlying OS and the result is used; if "hash" an hashing algorithm is used against the interface name to generate a unique number per interface; if "map" then ifindex definitions are expected as part of a pcap_interfaces_map (see below). DEFAULT: none KEY: pcap_interfaces_map [GLOBAL, PMACCTD_ONLY, MAP] DESC: Allows to listen for traffic data on multiple interfaces (compared to pcap_interface where only a single interface can be defined). The map allows to define also ifindex and capturing direction on a per-interface basis. The map can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). Sample map in examples/pcap_interfaces.map.example . DEFAULT: none KEY: promisc (-N) [GLOBAL, PMACCTD_ONLY] VALUES: [ true | false ] DESC: If set to true, puts the listening interface in promiscuous mode. It's mostly useful when running 'pmacctd' in a box which is not a router, for example, when listening for traffic on a mirroring port. DEFAULT: true KEY: imt_path (-p) DESC: Specifies the full pathname where the memory plugin has to listen for client queries. When multiple memory plugins are active, each one has to use its own file to communicate with the client tool. Note that placing these files into a carefully protected directory (rather than /tmp) is the proper way to control who can access the memory backend. DEFAULT: /tmp/collect.pipe KEY: imt_buckets (-b) DESC: Defines the number of buckets of the memory table which is organized as a chained hash table. A prime number is highly recommended. Read INTERNALS 'Memory table plugin' chapter for further details. DEFAULT: 32771 KEY: imt_mem_pools_number (-m) DESC: Defines the number of memory pools the memory table is able to allocate; the size of each pool is defined by the 'imt_mem_pools_size' directive. Here, a value of 0 instructs the memory plugin to allocate new memory chunks as they are needed, potentially allowing the memory structure to grow undefinitely. A value > 0 instructs the plugin to not try to allocate more than the specified number of memory pools, thus placing an upper boundary to the table size. DEFAULT: 16 KEY: imt_mem_pools_size (-s) DESC: Defines the size of each memory pool. For further details read INTERNALS 'Memory table plugin'. The number of memory pools is defined by the 'imt_mem_pools_number' directive. DEFAULT: 8192 KEY: syslog (-S) [GLOBAL] VALUES: [ auth | mail | daemon | kern | user | local[0-7] ] DESC: Enables syslog logging, using the specified facility. DEFAULT: none (logging to stderr) KEY: logfile [GLOBAL] DESC: Enables logging to a file (bypassing syslog); expected value is a pathname. The target file can be re-opened by sending a SIGHUP to the daemon so that, for example, logs can be rotated. DEFAULT: none (logging to stderr) KEY: amqp_host DESC: Defines the AMQP/RabbitMQ broker IP. All amqp_* directives are used by the AMQP plugin of flow daemons only. Check *_amqp_host out (ie. bgp_daemon_msglog_amqp_host) for the equivalent directives relevant to other RabbitMQ exports. DEFAULT: localhost KEY: [ bgp_daemon_msglog_amqp_host | bgp_table_dump_amqp_host | bmp_dump_amqp_host | bmp_daemon_msglog_amqp_host | sfacctd_counter_amqp_host | telemetry_daemon_msglog_amqp_host | telemetry_dump_amqp_host ] [GLOBAL] DESC: See amqp_host. bgp_daemon_msglog_amqp_* directives are used by the BGP thread/daemon to stream data out; bgp_table_dump_amqp_* directives are used by the BGP thread/daemon to dump data out at regular time intervals; bmp_daemon_msglog_amqp_* directives are used by the BMP thread/daemon to stream data out; bmp_dump_amqp_* directives are used by the BMP thread/daemon to dump data out at regular time intervals; sfacctd_counter_amqp_* directives are used by sfacctd to stream sFlow counter data out; telemetry_daemon_msglog_amqp_* are used by the Streaming Telemetry thread/daemon to stream data out; telemetry_dump_amqp_* directives are used by the Streaming Telemetry thread/daemon to dump data out at regular time intervals. DEFAULT: See amqp_host KEY: amqp_vhost DESC: Defines the AMQP/RabbitMQ server virtual host; see also amqp_host. DEFAULT: "/" KEY: [ bgp_daemon_msglog_amqp_vhost | bgp_table_dump_amqp_vhost | bmp_dump_amqp_vhost | bmp_daemon_msglog_amqp_vhost | sfacctd_counter_amqp_vhost | telemetry_daemon_msglog_amqp_vhost | telemetry_dump_amqp_vhost ] [GLOBAL] DESC: See amqp_vhost; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_vhost KEY: amqp_user DESC: Defines the username to use when connecting to the AMQP/RabbitMQ server; see also amqp_host. DEFAULT: guest KEY: [ bgp_daemon_msglog_amqp_user | bgp_table_dump_amqp_user | bmp_dump_amqp_user | bmp_daemon_msglog_amqp_user | sfacctd_counter_amqp_user | telemetry_daemon_msglog_amqp_user | telemetry_dump_amqp_user ] [GLOBAL] DESC: See amqp_user; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_user KEY: amqp_passwd DESC: Defines the password to use when connecting to the server; see also amqp_host. DEFAULT: guest KEY: [ bgp_daemon_msglog_amqp_passwd | bgp_table_dump_amqp_passwd | bmp_dump_amqp_passwd | bmp_daemon_msglog_amqp_passwd | sfacctd_counter_amqp_passwd | telemetry_daemon_msglog_amqp_passwd | telemetry_dump_amqp_passwd ] [GLOBAL] DESC: See amqp_passwd; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_passwd KEY: amqp_routing_key DESC: Name of the AMQP routing key to attach to published data. Dynamic names are supported through the use of variables, which are computed at the moment when data is purged to the backend. The list of variables supported is: $peer_src_ip Value of the peer_src_ip primitive of the record being processed. $tag Value of the tag primitive of the record being processed. $tag2 Value of the tag2 primitive of the record being processed. $post_tag Configured value of post_tag. $post_tag2 Configured value of post_tag2. See also amqp_host. DEFAULT: 'acct' KEY: [ bgp_daemon_msglog_amqp_routing_key | bgp_table_dump_amqp_routing_key | bmp_daemon_msglog_amqp_routing_key | bmp_dump_amqp_routing_key | sfacctd_counter_amqp_routing_key | telemetry_daemon_msglog_amqp_routing_key | telemetry_dump_amqp_routing_key ] [GLOBAL] DESC: See amqp_routing_key; see also bgp_daemon_msglog_amqp_host. Variables supported by the configuration directives described in this section: $peer_src_ip BGP peer IP address (bgp_*) or sFlow agent IP address (sfacctd_*). $bmp_router BMP peer IP address. $telemetry_node Streaming Telemetry exporter IP address. $peer_tcp_port BGP peer TCP port. $bmp_router_port BMP peer TCP port. $telemetry_node_port Streaming Telemetry exporter port. DEFAULT: none KEY: [ amqp_routing_key_rr | kafka_topic_rr ] DESC: Performs round-robin load-balancing over a set of AMQP routing keys or Kafka topics. The base name for the string is defined by amqp_routing_key or kafka_topic. This key accepts a positive int value. If, for example, amqp_routing_key is set to 'blabla' and amqp_routing_key_rr to 3 then the AMQP plugin will round robin as follows: message #1 -> blabla_0, message #2 -> blabla_1, message #3 -> blabla_2, message #4 -> blabla_0 and so forth. This works in the same fashion for kafka_topic. By default the feature is disabled, meaning all messages are sent to the base AMQP routing key or Kafka topic (or the default one, if no amqp_routing_key or kafka_topic is being specified). For Kafka it is adviced to create topics in advance with a tool like kafka-topics.sh (ie. "kafka-topics.sh --zookeepeer --topic --create") even if auto.create.topics.enable is set to true (default) on the broker. This is because topic creation, especially on distributed systems, may take time and lead to data loss. DEFAULT: 0 KEY: [ bgp_daemon_msglog_amqp_routing_key_rr | bgp_table_dump_amqp_routing_key_rr | bmp_daemon_msglog_amqp_routing_key_rr | bmp_dump_amqp_routing_key_rr | telemetry_daemon_msglog_amqp_routing_key_rr | telemetry_dump_amqp_routing_key_rr ] [GLOBAL] DESC: See amqp_routing_key_rr; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_routing_key_rr KEY: amqp_exchange DESC: Name of the AMQP exchange to publish data; see also amqp_host. DEFAULT: pmacct KEY: [ bgp_daemon_msglog_amqp_exchange | bgp_table_dump_amqp_exchange | bmp_daemon_msglog_amqp_exchange | bmp_dump_amqp_exchange | sfacctd_counter_amqp_exchange | telemetry_daemon_msglog_amqp_exchange | telemetry_dump_amqp_exchange ] [GLOBAL] DESC: See amqp_exchange DEFAULT: See amqp_exchange; see also bgp_daemon_msglog_amqp_host. KEY: amqp_exchange_type DESC: Type of the AMQP exchange to publish data to. 'direct', 'fanout' and 'topic' types are supported; "rabbitmqctl list_exchanges" can be used to check the exchange type. Upon mismatch of exchange type, ie. exchange type is 'direct' but amqp_exchange_type is set to 'topic', an error will be returned. DEFAULT: direct KEY: [ bgp_daemon_msglog_amqp_exchange_type | bgp_table_dump_amqp_exchange_type | bmp_daemon_msglog_amqp_exchange_type | bmp_dump_amqp_exchange_type | sfactd_counter_amqp_exchange_type | telemetry_daemon_msglog_amqp_exchange_type | telemetry_dump_amqp_exchange_type ] [GLOBAL] DESC: See amqp_exchange_type; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_exchange_type KEY: amqp_persistent_msg VALUES: [ true | false ] DESC: Marks messages as persistent and sets Exchange as durable so to prevent data loss if a RabbitMQ server restarts (it will still be consumer responsibility to declare the queue durable). Note from RabbitMQ docs: "Marking messages as persistent does not fully guarantee that a message won't be lost. Although it tells RabbitMQ to save message to the disk, there is still a short time window when RabbitMQ has accepted a message and hasn't saved it yet. Also, RabbitMQ doesn't do fsync(2) for every message -- it may be just saved to cache and not really written to the disk. The persistence guarantees aren't strong, but it is more than enough for our simple task queue."; see also amqp_host. DEFAULT: false KEY: [ bgp_daemon_msglog_amqp_persistent_msg | bgp_table_dump_amqp_persistent_msg | bmp_daemon_msglog_amqp_persistent_msg | bmp_dump_amqp_persistent_msg | sfacctd_counter_persistent_msg | telemetry_daemon_msglog_amqp_persistent_msg | telemetry_dump_amqp_persistent_msg ] [GLOBAL] VALUES: See amqp_persistent_msg; see also bgp_daemon_msglog_amqp_host. DESC: See amqp_persistent_msg DEFAULT: See amqp_persistent_msg KEY: amqp_frame_max DESC: Defines the maximum size, in bytes, of an AMQP frame on the wire to request of the broker for the connection. 4096 is the minimum size, 2^31-1 is the maximum; it may be needed to up the value from its default especially when making use of amqp_multi_values which will produce larger batched messages. See also amqp_host. DEFAULT: 131072 KEY: [ bgp_daemon_msglog_amqp_frame_max | bgp_table_dump_amqp_frame_max | bmp_daemon_msglog_amqp_frame_max | bmp_dump_amqp_frame_max | sfacctd_counter_amqp_frame_max | telemetry_daemon_msglog_amqp_frame_max | telemetry_dump_amqp_frame_max ] [GLOBAL] DESC: See amqp_frame_max; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_frame_max KEY: amqp_heartbeat_interval DESC: Defines the heartbeat interval in order to detect general failures of the RabbitMQ server. The value is expected in seconds. By default the heartbeat mechanism is disabled with a value of zero. According to RabbitMQ C API, detection takes place only upon publishing a JSON message, ie. not at login or if idle. The maximum value supported is INT_MAX (or 2147483647); see also amqp_host. DEFAULT: 0 KEY: [ bgp_daemon_msglog_amqp_heartbeat_interval | bgp_table_dump_amqp_heartbeat_interval | bmp_daemon_msglog_amqp_heartbeat_interval | bmp_dump_amqp_heartbeat_interval | sfacctd_counter_amqp_heartbeat_interval | telemetry_daemon_msglog_amqp_heartbeat_interval | telemetry_dump_amqp_heartbeat_interval ] [GLOBAL] DESC: See amqp_heartbeat_interval; see also bgp_daemon_msglog_amqp_host. DEFAULT: See amqp_heartbeat_interval KEY: [ bgp_daemon_msglog_amqp_retry | bmp_daemon_msglog_amqp_retry | sfacctd_counter_amqp_retry | telemetry_daemon_msglog_amqp_retry ] [GLOBAL] DESC: Defines the interval of time, in seconds, after which a connection to the RabbitMQ server should be retried after a failure is detected; see also amqp_host. See also bgp_daemon_msglog_amqp_host. DEFAULT: 60 KEY: kafka_topic DESC: Name of the Kafka topic to attach to published data. Dynamic names are supported by kafka_topic through the use of variables, which are computed at the moment when data is purged to the backend. The list of variables supported by amqp_routing_key: $peer_src_ip Value of the peer_src_ip primitive of the record being processed. $tag Value of the tag primitive of the record being processed. $tag2 Value of the tagw primitive of the record being processed. $post_tag Configured value of post_tag. $post_tag2 Configured value of post_tag2. It is adviced to create topics in advance with a tool like kafka-topics.sh (ie. "kafka-topics.sh --zookeepeer --topic --create") even if auto.create.topics.enable is set to true (default) on the broker. This is because topic creation, especially on distributed systems, may take time and lead to data loss. DEFAULT: 'pmacct.acct' KEY: kafka_config_file DESC: Full pathname to a file containing directives to configure librdkafka. All knobs whose values are string, integer, boolean, CSV are supported. Pointer values, ie. for setting callbacks, are currently not supported through this infrastructure. The syntax of the file is CSV and expected in the format: where 'type' is one of 'global' or 'topic' and 'key' and 'value' are set according to librdkafka doc https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md Both 'key' and 'value' are passed onto librdkafka without any validation being performed; the 'value' field can also contain commas no problem as it is also not parsed. Examples are: topic, compression.codec, snappy global, socket.keepalive.enable, true DEFAULT: none KEY: kafka_broker_host DESC: Defines one or multiple, comma-separated, Kafka brokers for the bootstrap process. If only a single broker IP address is defined then the broker port is read via the kafka_broker_port config directive (legacy syntax); if multiple brokers are defined then each broker port, if not left to default 9092, is expected as part of this directive, for example: "broker1:10000,broker2". When defining multiple brokers, if the host is IPv4, the value is expected as 'address:port'. If IPv6, it is expected as '[address]:port' (although when defining a single broker, this is not required as the IPv6 address is detected and wrapped-around '[' ']' symbols). Resolvable hostnames are also accepted, if host resolves to multiple addresses it will round-robin the addresses for each connection attempt. SSL connections can be configured as "ssl://broker3:9000,ssl://broker2". All kafka_* directives are used by the Kafka plugin of flow daemons only. Check other *_kafka_broker_host out (ie. bgp_daemon_msglog_kafka_broker_host) for the equivalent directives relevant to other Kafka exports. DEFAULT: 127.0.0.1 KEY: kafka_broker_port DESC: Defines the Kafka broker port. See also kafka_broker_host. DEFAULT: 9092 KEY: kafka_partition DESC: Defines the Kafka broker topic partition ID. RD_KAFKA_PARTITION_UA or ((int32_t)-1) is to define the configured or default partitioner (slower than sending to a fixed partition). See also kafka_broker_host. DEFAULT: -1 KEY: kafka_partition_dynamic VALUES [ true | false ] DESC: Enables dynamic Kafka partitioning, ie. data is partitioned according to the value of the Kafka broker topic partition key. See also kafka_partition_key. DEFAULT: false KEY: kafka_partition_key DESC: Defines the Kafka broker topic partition key. A string of printable characters is expected as value. Dynamic names are supported through the use of variables, which are computed at the moment data is purged to the backend. The list of supported variables follows: $peer_src_ip Record value for peer_src_ip primitive (if primitive is not part of the aggregation method then this will be set to a null value). $tag Record value for tag primitive (if primitive is not part of the aggregation method then this will be set to a null value). $tag2 Record value for tag2 primitive (if primitive is not part of the aggregation method then this will be set to a null value). $src_host Record value for src_host primitive (if primitive is not part of the aggregation method then this will be set to a null value). $dst_host Record value for dst_host primitive (if primitive is not part of the aggregation method then this will be set to a null value). $src_port Record value for src_port primitive (if primitive is not part of the aggregation method then this will be set to a null value). $dst_port Record value for dst_port primitive (if primitive is not part of the aggregation method then this will be set to a null value). $proto Record value for proto primitive (if primitive is not part of the aggregation method then this will be set to a null value). $in_iface Record value for in_iface primitive (if primitive is not part of the aggregation method then this will be set to a null value). DEFAULT: none KEY: [ bgp_daemon_msglog_kafka_broker_host | bgp_table_dump_kafka_broker_host | bmp_daemon_msglog_kafka_broker_host | bmp_dump_kafka_broker_host | sfacctd_counter_kafka_broker_host | telemetry_daemon_msglog_kafka_broker_host | telemetry_dump_kafka_broker_host ] [GLOBAL] DESC: See kafka_broker_host. bgp_daemon_msglog_kafka_* directives are used by the BGP thread/ daemon to stream data out; bgp_table_dump_kafka_* directives are used by the BGP thread/ daemon to dump data out at regular time intervals; bmp_daemon_msglog_kafka_* directives are used by the BMP thread/daemon to stream data out; bmp_dump_kafka_* directives are used by the BMP thread/daemon to dump data out at regular time intervals; sfacctd_counter_kafka_* directives are used by sfacctd to stream sFlow counter data out; telemetry_daemon_msglog_kafka_* are used by the Streaming Telemetry thread/daemon to stream data out; telemetry_dump_kafka_* directives are used by the Streaming Telemetry thread/daemon to dump data out at regular time intervals. DEFAULT: See kafka_broker_host KEY: [ bgp_daemon_msglog_kafka_broker_port | bgp_table_dump_kafka_broker_port | bmp_daemon_msglog_kafka_broker_port | bmp_dump_kafka_broker_port | sfacctd_counter_kafka_broker_port | telemetry_daemon_msglog_kafka_broker_port | telemetry_dump_kafka_broker_port ] [GLOBAL] DESC: See kafka_broker_port; see also bgp_daemon_msglog_kafka_broker_host. DEFAULT: See kafka_broker_port KEY: [ bgp_daemon_msglog_kafka_topic | bgp_table_dump_kafka_topic | bmp_daemon_msglog_kafka_topic | bmp_dump_kafka_topic | sfacctd_counter_kafka_topic | telemetry_daemon_msglog_kafka_topic | telemetry_dump_kafka_topic ] [GLOBAL] DESC: See kafka_topic; see also bgp_daemon_msglog_kafka_broker_host. Variables supported by the configuration directives described in this section: $peer_src_ip BGP peer IP address (bgp_*) or sFlow agent IP address (sfacctd_*). $bmp_router BMP peer IP address. $telemetry_node Streaming Telemetry exporter IP address. $peer_tcp_port BGP peer TCP port. $bmp_router_port BMP peer TCP port. $telemetry_node_port Streaming Telemetry exporter port. DEFAULT: none KEY: [ bgp_daemon_msglog_kafka_topic_rr | bgp_table_dump_kafka_topic_rr | bmp_daemon_msglog_kafka_topic_rr | bmp_dump_kafka_topic_rr | telemetry_daemon_msglog_kafka_topic_rr | telemetry_dump_kafka_topic_rr ] [GLOBAL] DESC: See kafka_topic_rr; see also bgp_daemon_msglog_kafka_broker_host. DEFAULT: See kafka_topic_rr KEY: [ bgp_daemon_msglog_kafka_partition | bgp_table_dump_kafka_partition | bmp_daemon_msglog_kafka_partition | bmp_dump_kafka_partition | sfacctd_counter_kafka_partition | telemetry_daemon_msglog_kafka_partition | telemetry_dump_kafka_partition ] [GLOBAL] DESC: See kafka_partition; see also bgp_daemon_msglog_kafka_broker_host. DEFAULT: See kafka_partition KEY: [ bgp_daemon_msglog_kafka_partition_key | bgp_table_dump_kafka_partition_key ] [GLOBAL] DESC: Defines the Kafka broker topic partition key. A string of printable characters is expected as value. Dynamic names are supported through the use of variables, listed below: $peer_src_ip The IP address of the BGP peer exporting data $peer_tcp_port The TCP port of the BGP session. Useful in case of BGP x-connects DEFAULT: none KEY: [ bmp_daemon_msglog_kafka_partition_key | bmp_dump_kafka_partition_key ] [GLOBAL] DESC: Defines the Kafka broker topic partition key. A string of printable characters is expected as value. Dynamic names are supported through the use of variables, listed below: $bmp_router The IP address of the router exporting data via BMP $bmp_router_port The TCP port of the BMP session DEFAULT: none KEY: [ telemetry_daemon_msglog_kafka_partition_key | telemetry_dump_kafka_partition_key ] [GLOBAL] DESC: Defines the Kafka broker topic partition key. A string of printable characters is expected as value. Dynamic names are supported through the use of variables, listed below: $telemetry_node The IP address of the node exporting Streaming Telemetry $telemetry_node_port The TCP/UDP port of the Streaming Telemetry session DEFAULT: none KEY: [ bgp_daemon_msglog_kafka_retry | bmp_daemon_msglog_kafka_retry | sfacctd_counter_kafka_retry | telemetry_daemon_msglog_kafka_retry ] [GLOBAL] DESC: Defines the interval of time, in seconds, after which a connection to the Kafka broker should be retried after a failure is detected. DEFAULT: 60 KEY: [ bgp_daemon_msglog_kafka_config_file | bgp_table_dump_kafka_config_file | bmp_daemon_msglog_kafka_config_file | bmp_dump_kafka_config_file | sfacctd_counter_kafka_config_file | telemetry_daemon_msglog_kafka_config_file | telemetry_dump_kafka_config_file ] [GLOBAL] DESC: See kafka_config_file; see also bgp_daemon_msglog_kafka_broker_host. DEFAULT: See kafka_config_file KEY: pidfile (-F) [GLOBAL] DESC: Writes PID of Core process to the specified file. PIDs of the active plugins are written aswell by employing the following syntax: 'path/to/pidfile--'. This gets particularly useful to recognize which process is which on architectures where pmacct does not support the setproctitle() function. DEFAULT: none KEY: networks_file (-n) DESC: Full pathname to a file containing a list of networks - and optionally ASN information and BGP next-hop (peer_dst_ip). Purpose of the directive is to act as a resolver when network, next-hop and/or peer/origin ASN information is not available through other means (ie. BGP, IGP, telemetry protocol) or for the purpose of overriding such information with custom/self-defined one. DEFAULT: none KEY: networks_file_filter VALUES [ true | false ] DESC: Makes networks_file work as a filter in addition to its basic resolver functionality: networks and hosts not belonging to defined networks are zeroed out. This feature can interfere with the intended behaviour of networks_no_mask_if_zero, if they are both set to true. DEFAULT: false KEY: networks_file_no_lpm VALUES [ true | false ] DESC: Makes a matching IP prefix defined in a networks_file win always, even if it is not the longest. It applies when the aggregation method includes src_net and/or dst_net and nfacctd_net (or equivalents) and/or nfacctd_as (or equivalents) configuration directives are set to 'longest' (or 'fallback'). For example we receive the following PDU via NetFlow: SrcAddr: 10.0.8.29 (10.0.8.29) DstAddr: 192.168.5.47 (192.168.5.47) [ .. ] SrcMask: 24 (prefix: 10.0.8.0/24) DstMask: 27 (prefix: 192.168.5.32/27) a BGP peering is available and BGP contains the following prefixes: 192.168.0.0/16 and 10.0.0.0/8. Such a scenario is typical when more specifics are not re-distributed in BGP but are only available in the IGP. A networks_file contains the prefixes 10.0.8.0/24 and 192.168.5.0/24. 10.0.8.0/24 is the same as in NetFlow; but 192.168.5.0/24 (say, representative of a range dedicated to a specific customer across several locations and hence composed of several sub-prefies) would not be the longest match and hence the prefix from NetFlow, 192.168.5.32/27, would be the outcome of the network aggregation process; setting networks_file_no_lpm to true makes 192.168.5.0/24, coming from the networks_file, win instead. DEFAULT: false KEY: networks_no_mask_if_zero VALUES [ true | false ] DESC: If set to true, IP prefixes with zero mask - that is, unknown ones or those hitting a default route - are not masked (ie. they are applied a full 0xF mask, that is, 32 bits for IPv4 addresses and 128 bits for IPv6 ones). The feature applies to *_net fields and makes sure individual IP addresses belonging to unknown IP prefixes are not zeroed out. This feature can interfere with the intended behaviour of networks_file_filter, if they are both set to true. DEFAULT: false KEY: networks_mask DESC: Specifies the network mask - in bits - to apply to IP address values in L3 header. The mask is applied sistematically and before evaluating the 'networks_file' content (if any is specified). The mask must be part of the aggregation method in order to be applied, ie. 'aggregate: dst_net, dst_mask', 'aggregate: src_net, src_mask', etc. DEFAULT: none KEY: networks_cache_entries DESC: Networks Lookup Table (which is the memory structure where the 'networks_file' data is loaded) is preeceded by a Network Lookup Cache where lookup results are saved to speed up later searches. NLC is structured as an hash table, hence, this directive is aimed to set the number of buckets for the hash table. The default value should be suitable for most common scenarios, however when facing with large-scale network definitions, it is quite adviceable to tune this parameter to improve performances. A prime number is highly recommended. DEFAULT: IPv4: 99991; IPv6: 32771 KEY: ports_file DESC: Full pathname to a file containing a list of (known/interesting/meaningful) TCP/UDP ports (one per line, read more about the file syntax into examples/ tree). The directive zeroes port numbers not matching those defined in the list. Not being a filter but an aggregator, this directive makes sense only if aggregating on 'src_port' and/or 'dst_port' primitives. DEFAULT: none KEY: protos_file DESC: Full pathname to a file containing a list of (known/interesting/meaningful) IP protocols (one per line). Both protocol names, ie. "tcp", and protocol numbers, ie. 1 (for icmp), are accepted. The directive uses IANA reserved protocol value 255 to bucket as 'others' those IP protocols not matching the ones defined in the list. Not being a filter but an aggregator, this directive makes sense only if aggregating on the 'proto' primitive. DEFAULT: none KEY: tos_file DESC: Full pathname to a file containing a list of (meaningful) IP ToS values (one per line); if tos_encode_as_dscp is set to true then DSCP values are expected as part of the file. The directive uses value 255 to bucket as 'others' those ToS/DSCP values not matching the ones defined in the list. Not being a filter but an aggregator, this directive makes sense only if aggregating on the 'tos' primitive. DEFAULT: none KEY: sql_db DESC: Defines the SQL database to use. When using the SQLite3 plugin, this directive refers to the full path to the database file; if multiple sqlite3 plugins are in use, it is recommended to point them to different files to prevent locking issues. DEFAULT: 'pmacct'; sqlite3: '/tmp/pmacct.db' KEY: [ sql_table | print_output_file ] DESC: In SQL this defines the table to use; in print plugin it defines the file to write output to. Dynamic names are supported through the use of variables, which are computed at the moment when data is purged to the backend. The list of supported variables follows: %d The day of the month as a decimal number (range 01 to 31). %H The hour as a decimal number using a 24 hour clock (range 00 to 23). %m The month as a decimal number (range 01 to 12). %M The minute as a decimal number (range 00 to 59). %s The number of seconds since Epoch, ie., since 1970-01-01 00:00:00 UTC. %S The seconds as a decimal number second (range 00 to 60). %w The day of the week as a decimal, range 0 to 6, Sunday being 0. %W The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01. %Y The year as a decimal number including the century. %z The +hhmm numeric time zone in ISO8601:1988 format (ie. -0400) $tzone The time zone in rfc3339 format (ie. -04:00 or 'Z' for +00:00) $ref Configured refresh time value for the plugin. $hst Configured sql_history value, in seconds, for the plugin. $peer_src_ip Record value for peer_src_ip primitive (if primitive is not part of the aggregation method then this will be set to a null value). $tag Record value for tag primitive (if primitive is not part of the aggregation method then this will be set to a null value). $tag2 Record value for tag2 primitive (if primitive is not part of the aggregation method then this will be set to a null value). $post_tag Configured value of post_tag. $post_tag2 Configured value of post_tag2. SQL plugins notes: Time-related variables require 'sql_history' to be specified in order to work correctly (see 'sql_history' entry in this in this document for further information) and that the 'sql_refresh_time' setting is aligned with the 'sql_history', ie.: sql_history: 5m sql_refresh_time: 300 Furthermore, if the 'sql_table_schema' directive is not specified, tables are expected to be already in place. This is an example on how to split accounted data among multiple tables basing on the day of the week: sql_history: 1h sql_history_roundoff: h sql_table: acct_v4_%w The above directives will account data on a hourly basis (1h). Also the above sql_table definition will make: Sunday data be inserted into the 'acct_v4_0' table, Monday into the 'acct_v4_1' table, and so on. The switch between the tables will happen each day at midnight: this behaviour is ensured by the use of the 'sql_history_roundoff' directive. Ideally sql_refresh_time and sql_history values should be aligned for the dynamic tables to work; sql_refresh_time with a value smaller than sql_history is also supported; whereas the feature does not support values of sql_refresh_time greater than sql_history. The maximum table name length is 64 characters. Print plugin notes: If a non-dynamic filename is selected, content is overwritten to the existing file in case print_output_file_append is set to false (default). When creating a target file, the needed level of directories are created too (equivalent to mkdir -p), for example "/path/to/%Y/%Y-%m/%Y-%m-%d/blabla-%Y%m%d-%H%M.txt". However shell replacements are not supported, ie. the '~' symbol to denote the user home directory. Time-related variables require 'print_history' to be specified in order to work correctly. The output file can be a named pipe (ie. created with mkfifo), however the pipe has to be manually created in advance. Common notes: The maximum number of variables it may contain is 32. DEFAULT: see notes KEY: print_output_file_append VALUES: [ true | false ] DESC: If set to true, print plugin will append to existing files instead of overwriting. If appending, and in case of an output format requiring a title, ie. csv, formatted, etc., intuitively the title is not re-printed. DEFAULT: false KEY: print_output_lock_file DESC: If no print_output_file is defined (ie. print plugin output goes to stdout), this directive defined a global lock to serialize output to stdout, ie. in cases where multiple print plugins are defined or purging events of the same plugin queue up. By default output is not serialized and a warning message is printed to flag the condition. KEY: print_latest_file DESC: Defines the full pathname to pointer(s) to latest file(s). Dynamic names are supported through the use of variables, which are computed at the moment when data is purged to the backend: refer to print_output_file for a full listing of supported variables; time-based variables are not allowed. Three examples follow: #1: print_output_file: /path/to/spool/foo-%Y%m%d-%H%M.txt print_latest_file: /path/to/spool/foo-latest #2: print_output_file: /path/to/spool/%Y/%Y-%m/%Y-%m-%d/foo-%Y%m%d-%H%M.txt print_latest_file: /path/to/spool/latest/foo #3: print_output_file: /path/to/$peer_src_ip/foo-%Y%m%d-%H%M.txt print_latest_file: /path/to//spool/latest/blabla-$peer_src_ip NOTES: Update of the latest pointer is done evaluating files name. For correct working of the feature, responsibility is put on the user. A file is reckon as latest if it is lexicographically greater than an existing one: this is generally fine but requires dates to be in %Y%m%d format rather than %d%m%Y. Also, upon restart of the daemon, if print_output_file is modified to a different location good practice would be to 1) manually delete latest pointer(s) or 2) move existing print_output_file files to the new targer location. Finally, if upgrading from pmacct releases before 1.5.0rc1, it is recommended to delete existing symlinks. DEFAULT: none KEY: print_write_empty_file VALUES: [ true | false ] DESC: If set to true, print plugin will write an empty file (zero length) if there was no data to output; this also aligns to the pre 1.5.0 behaviour, as documnted in the UPGRADE document. The default behaviour is instead to only produce a log message with "ET: X" as Estimated Time value. DEFAULT: false KEY: sql_table_schema DESC: Full pathname to a file containing a SQL table schema. It allows to create the SQL table if it does not exist; a config example where this directive could be useful follows: sql_history: 5m sql_history_roundoff: h sql_table: acct_v4_%Y%m%d_%H%M sql_table_schema: /usr/local/pmacct/acct_v4.schema In this configuration, the content of the file pointed by 'sql_table_schema' should be: CREATE TABLE acct_v4_%Y%m%d_%H%M ( [ ... PostgreSQL/MySQL specific schema ... ] ); It is recommended that the content of the file is stripped by any un-necessary comments, strings and characters besides the SQL statement. This setup, along with this directive, are mostly useful when the dynamic tables are not closed in a 'ring' fashion (e.g., the days of the week) but 'open' (e.g., current date). DEFAULT: none KEY: sql_table_version VALUES [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ] DESC: Defines the version of the SQL table. SQL table versioning was introduced to achieve two goals: a) make tables work out-of-the-box for the SQL beginners, smaller installations and quick try-outs; and in this context b) to allow introduction of new features over time without breaking backward compatibility. For the SQL experts, the alternative to versioning is 'sql_optimize_clauses' which allows custom mix-and-match of primitives: in such a case you have to build yourself custom SQL schemas and indexes. Check in the 'sql/' sub-tree the SQL table profiles which are supported by the pmacct version you are currently using. It is always adviced to explicitely define a sql_table_version in order to predict which primitive will be written to which column. All versioning rules are captured in sql/README.[mysql|sqlite3|pgsql] documents. DEFAULT: 1 KEY: sql_table_type VALUES [ original | bgp ] DESC: BGP-related primitives are divided in legacy and non-legacy. Legacy are src_as, dst_as; non-legacy are all the rest. Up to "original" tables v5 src_as and dst_as were written in the same field as src_host and dst_host. From "original" table v6 and if sql_table_type "bgp" is selected, src_as and dst_as are written in their own field (as_src and as_dst respectively). sql_table_type is by default set to "original" and is switched to "bgp" automatically if any non-legacy primitive is in use, ie. peer_dst_ip, as_path, etc. This directive allows to make the selection explicit and/or circumvent default behaviour. Apart from src_as and dst_as, regular table versioning applies to all non-BGP related fields, for example: a) if "sql_table_type: bgp" and "sql_table_version: 1" then the "tag" field will be written in the "agent_id" column whereas; b) if "sql_table_type: bgp" and "sql_table_version: 9" instead, then the "tag" field will be written in the "tag" column. All versioning rules are captured in sql/README.[mysql|sqlite3|pgsql] documents. DEFAULT: original KEY: sql_data VALUES: [ typed | unified ] DESC: This switch applies to the PostgreSQL plugin and when using default tables up to v5: pgsql scripts in the sql/ tree, up to v5, will in fact create a 'unified' table along with multiple 'typed' tables. The 'unified' table has IP and MAC addresses specified as standard CHAR strings, slower and not space savy but flexible; 'typed' tables feature PostgreSQL own types (inet, mac, etc.), resulting in a faster but more rigid structure. Since v6 unified mode is being discontinued leading to simplification. DEFAULT: typed KEY: sql_conn_ca_file DESC: In MySQL and PostgreSQL plugins, this is the path name of the Certificate Authority (CA) certificate file. If used, it must specify the same certificate used by the server. DEFAULT: none KEY: sql_host DESC: Defines the backend server IP/hostname. In case of the MySQL plugin, prepending the 'unix:' string, ie. 'unix:/path/to/unix.socket', will cause the rest to be treated as a UNIX socket (rather than an IP address/hostname). DEFAULT: localhost KEY: sql_port DESC: Defines the backend server TCP/UDP port DEFAULT: [ MySQL: 3306; PostgreSQL: 5432 ] KEY: sql_user DESC: Defines the username to use when connecting to the server. DEFAULT: pmacct KEY: sql_passwd DESC: Defines the password to use when connecting to the server. Note that since this directive does encompass a default value (see below), it is not possible to connect to a server that performs password authentication with an empy password. DEFAULT: 'arealsmartpwd' KEY: [ sql_refresh_time | print_refresh_time | amqp_refresh_time | kafka_refresh_time ] (-r) DESC: Time interval, in seconds, between consecutive executions of the plugin cache scanner. The scanner purges data into the plugin backend. Note: internally all these config directives write to the same variable; when using multiple plugins it is recommended to bind refresh time definitions to specific plugins, ie.: plugins: mysql[x] sql_refresh_time[x]: 900 As doing otherwise can originate unexpected behaviours. DEFAULT: 60 KEY: [ sql_startup_delay | print_startup_delay | amqp_startup_delay | kafka_startup_delay ] DESC: Defines the time, in seconds, the first cache scan event has to be delayed. This delay is, in turn, propagated to the subsequent scans. It comes useful in two scenarios: a) so that multiple plugins can use the same refresh time (ie. sql_refresh_time) value, allowing them to spread the writes among the length of the time-bin; b) with NetFlow, when using a RDBMS, to keep original flow start time (nfacctd_time_new: false) while enabling the sql_dont_try_update feature (for RDBMS efficiency purposes); in such a context, sql_startup_delay value should be greater (better >= 2x the value) of the NetFlow active flow timeout. DEFAULT: 0 KEY: sql_optimize_clauses VALUES: [ true | false ] DESC: Enables the optimization of the statements sent to the RDBMS essentially allowing to a) run stripped-down variants of the default SQL tables or b) totally customized SQL tables by a free mix-and-match of the available primitives. Either case, you will need to build the custom SQL table schema and indexes. As a rule of thumb when NOT using this directive always remember to specify which default SQL table version you intend to stick to by using the 'sql_table_version' directive. DEFAULT: false KEY: [ sql_history | print_history | amqp_history | kafka_history ] VALUES: #[s|m|h|d|w|M] DESC: Enables historical accounting by placing accounted data into configurable time-bins. It does use the 'stamp_inserted' (base time of the time-bin) and 'stamp_updated' (last time the time-bin was touched) fields. The supplied value defines the time slot length during which counters are accumulated. See also *_history_roundoff'. In nfacctd, where a flow can span across multiple time-bins, flow counters can be pro-rated (seconds timestamp resolution) over involved the time-bins by setting nfacctd_pro_rating to true. The end net effect of this directive is close to time slots in a RRD file. Examples of valid values are: '300s' or '5m' - five minutes, '3600s' or '1h' - one hour, '14400s' or '4h' - four hours, '86400s' or '1d' - one day, '1w' - one week, '1M' - one month). DEFAULT: none KEY: [ sql_history_offset | print_history_offset | amqp_history_offset | kafka_history_offset ] DESC: Sets an offset to timeslots basetime. If history is set to 30 mins (by default creating 10:00, 10:30, 11:00, etc. time-bins), with an offset of 900 seconds (so 15 mins) it will create 10:15, 10:45, 11:15, etc. time-bins. It expects a positive value, in seconds. DEFAULT: 0 KEY: [ sql_history_roundoff | print_history_roundoff | amqp_history_roundoff | kafka_history_roundoff ] VALUES [m,h,d,w,M] DESC: Enables alignment of minutes (m), hours (h), days of month (d), weeks (w) and months (M) in print (to print_refresh_time) and SQL plugins (to sql_history and sql_refresh_time). Suppose you go with 'sql_history: 1h', 'sql_history_roundoff: m' and it's 6:34pm. Rounding off minutes gives you an hourly timeslot (1h) starting at 6:00pm; so, subsequent ones will start at 7:00pm, 8:00pm, etc. Now, you go with 'sql_history: 5m', 'sql_history_roundoff: m' and it's 6:37pm. Rounding off minutes will result in a first slot starting at 6:35pm; next slot will start at 6:40pm, and then every 5 minutes (6:45pm ... 7:00pm, etc.). 'w' and 'd' are mutually exclusive, that is: you can either reset the date to last Monday or reset the date to the first day of the month. DEFAULT: none KEY: sql_recovery_backup_host DESC: Enables recovery mode; recovery mechanism kicks in if DB fails. It works by checking for the successful result of each SQL query. By default it is disabled. By using this key aggregates are recovered to a secondary DB. See INTERNALS 'Recovery modes' section for details about this topic. SQLite 3.x note: the plugin uses this directive to specify a the full path to an alternate database file (e.g., because you have multiple file system on a box) to use in the case the primary backend fails. DEFAULT: none KEY: [ sql_max_writers | print_max_writers | amqp_max_writers | kafka_max_writers ] DESC: Sets the maximum number of concurrent writer processes the plugin is allowed to start. This setting allows pmacct to degrade gracefully during major backend lock/outages/ unavailability. The value is split as follows: up to N-1 concurrent processes will queue up; the Nth process will go for the recovery mechanism, if configured (ie. sql_recovery_backup_host for SQL plugins), writers beyond Nth will stop managing data (so, data will be lost at this stage) and an error message is printed out. DEFAULT: 10 KEY: [ sql_cache_entries | print_cache_entries | amqp_cache_entries | kafka_cache_entries ] DESC: All plugins have a memory cache in order to store data until next purging event (see refresh time directives, ie. sql_refresh_time). In case of network traffic data, the cache allows to accumulate bytes and packets counters. This directive sets the number of cache buckets, the cache being structured in memory as a hash with conflict chains. Default value is suitable for mid-sized scenarios, however when facing large-scale networks, it is recommended to tune this parameter to improve performances (ie. keep conflict chains shorter). Cache entries value should be also reviewed if the amount of entries are not sufficient for a full refresh time interval - in which case a "Finished cache entries" informational message will appear in the logs. Use a prime number of buckets. NOTES: * non SQL plugins: the cache structure has two dimensions, a base and a depth. This setting defines the base (the amount of cache buckets) whereas the depth can't be influenced by configuration and is set to an average depth of 10. This means that the default value (16411) allows for approx 150K entries to fit the cache structure. To properly size a plugin cache, it is recommended to determine the maximum amount of entries purged by such plugin and make calculations basing on that; if, for example, the plugin purges a peak of 2M entries then a cache entries value of 259991 is sufficient to cover the worse-case scenario. In case memory is constrained, the alternative option is to purge more often (ie. lower print_refresh_time) while retaining the same time-binning (ie. equal print_history) at the expense of having to consolidate/aggregate entries later in the collection pipeline; if opting for this, be careful having print_output_file_append set to true if using the print plugin). * SQL plugins: the cache structure is similar to the one described for the non SQL plugins but slightly different and more complex. Soon this cache structure will be removed and SQL plugins will be migrated to the same structure as the non SQL plugins, as described in the previous paragraph. * It is important to estimate how much space will take the base cache structure for a configured amount of cache entries - especially because configuring too many entries for the available memory can result in a crash of the plugin process right at startup. For this purpose, before trying to allocate the cache structure, the plugin will log an informational message saying "base cache memory=". Why the wording "base cache memory": because cache entries, depending on the configured aggregation method, can have extra structures allocated ad-hoc, ie. BGP-, NAT-, MPLS-related primitives; all these can make the total cache memory size increase slightly at runtime. DEFAULT: print_cache_entries, amqp_cache_entries, kafka_cache_entries: 16411; sql_cache_entries: 32771 KEY: sql_dont_try_update VALUES: [ true | false ] DESC: By default pmacct uses an UPDATE-then-INSERT mechanism to write data to the RDBMS; this directive instructs pmacct to use a more efficient INSERT-only mechanism. This directive is useful for gaining performances by avoiding UPDATE queries. Using this directive puts some timing constraints, specifically sql_history == sql_refresh_time, otherwise it may lead to duplicate entries and, potentially, loss of data. When used in nfacctd it also requires nfacctd_time_new to be enabled. DEFAULT: false KEY: sql_use_copy VALUES: [ true | false ] DESC: Instructs the plugin to build non-UPDATE SQL queries using COPY (in place of INSERT). While providing same functionalities of INSERT, COPY is also more efficient. To have effect, this directive requires 'sql_dont_try_update' to be set to true. It applies to PostgreSQL plugin only. NOTES: Error handling of the underlying PostgreSQL API is somewhat limited. During a COPY only transmission errors are detected but not syntax/semantic ones, ie. related to the query and/or the table schema. DEFAULT: false KEY: sql_delimiter DESC: If sql_use_copy is true, uses the supplied character as delimiter. This is thought in cases where the default delimiter is part of any of the supplied strings to be inserted into the database, for example certain BGP AS PATHs like "AS1_AS2_AS3_{ASX,ASY,ASZ}". DEFAULT: ',' KEY: [ amqp_multi_values | sql_multi_values | kafka_multi_values ] DESC: In SQL plugin, sql_multi_values enables the use of multi-values INSERT statements. The value of the directive is intended to be the size (in bytes) of the multi-values buffer. The directive applies only to MySQL and SQLite 3.x plugins. Inserting many rows at the same time is much faster (many times faster in some cases) than using separate single-row INSERT statements. It is adviceable to check the size of this pmacct buffer against the size of the corresponding MySQL buffer (max_allowed_packet). In AMQP and Kafka plugins, [amqp|kafka]_multi_values allow the same with JSON serialization (for Apache Avro see avro_buffer_size); in this case data is encoded in JSON objects newline-separated (preferred to JSON arrays for performance); in AMQP, make sure to set amqp_frame_max to a size that can accomodate the collection of JSON objects. DEFAULT: 0 KEY: [ sql_trigger_exec | print_trigger_exec | amqp_trigger_exec | kafka_trigger_exec ] DESC: Defines the executable to be launched at fixed time intervals to post-process aggregates; in SQL plugins, intervals are specified by the 'sql_trigger_time' directive; if no interval is supplied 'sql_refresh_time' value is used instead: this will result in a trigger being fired each purging event (recommended since all environment variables will be set, see next). A number of environment variables are set in order to allow the trigger to take actions and are listed in docs/TRIGGER_VARS. Non-SQL plugins feature a simpler implementation: triggers can only be fired each time data is written to the backend (ie. print_refresh_time) and no environment variables are passed over to the executable; useful also to upload data to cloud storage that supports upload via API end-points. DEFAULT: none KEY: sql_trigger_time VALUES: #[s|m|h|d|w|M] DESC: Specifies time interval at which the executable specified by 'sql_trigger_exec' has to be launched; if no executables are specified, this key is simply ignored. Values need to be in the 'sql_history' directive syntax (for example, valid values are '300' or '5m', '3600' or '1h', '14400' or '4h', '86400' or '1d', '1w', '1M'; eg. if '3600' or '1h' is selected, the executable will be fired each hour). DEFAULT: none KEY: [ sql_preprocess | print_preprocess | amqp_preprocess | kafka_preprocess ] DESC: Allows to process aggregates (via a comma-separated list of conditionals and checks, ie. "qnum=1000000, minb=10000") while purging data to the backend thus resulting in a powerful selection tier; aggregates filtered out may be just discarded or saved through the recovery mechanism (if enabled, if supported by the backend). The set of available preprocessing directives follows: KEY: qnum DESC: conditional. Subsequent checks will be evaluated only if the number of queries to be created during the current cache-to-DB purging event is '>=' qnum value. SQL plugins only. KEY: minp DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of packets is '>=' minp value. All plugins. KEY: minf DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of flows is '>=' minf value. All plugins. KEY: minb DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the bytes counter is '>=' minb value. An interesting idea is to set its value to a fraction of the link capacity. Remember that you have also a timeframe reference: the 'sql_refresh_time' seconds. All plugins. For example, given the following parameters: Link Capacity = 8Mbit/s, THreshold = 0.1%, TImeframe = 60s minb = ((LC / 8) * TI) * TH -> ((8Mbit/s / 8) * 60s) * 0.1% = 60000 bytes. Given a 8Mbit link, all aggregates which have accounted for at least 60Kb of traffic in the last 60 seconds, will be written to the DB. KEY: maxp DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of packets is '<' maxp value. All plugins. KEY: maxf DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of flows is '<' maxf value. All plugins. KEY: maxb DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the bytes counter is '<' maxb value. All plugins. KEY: maxbpp DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of bytes per packet is '<' maxbpp value. SQL plugins only. KEY: maxppf DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of packets per flow is '<' maxppf value. SQL plugins only. KEY: minbpp DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of bytes per packet is '>=' minbpp value. All plugins. KEY: minppf DESC: check. Aggregates on the queue are evaluated one-by-one; each object is marked valid only if the number of packets per flow is '>=' minppf value. All plugins. KEY: fss DESC: check. Enforces flow (aggregate) size dependent sampling, computed against the bytes counter and returns renormalized results. Aggregates which have collected more than the supplied 'fss' threshold in the last time window (specified by the 'sql_refresh_time' configuration key) are sampled. Those under the threshold are sampled with probability p(bytes). The method allows to get much more accurate samples compared to classic 1/N sampling approaches, providing an unbiased estimate of the real bytes counter. It would be also adviceable to hold the the equality 'sql_refresh_time' = 'sql_history'. For further references: http://www.research.att.com/projects/flowsamp/ and specifically to the papers: N.G. Duffield, C. Lund, M. Thorup, "Charging from sampled network usage", http://www.research.att.com/~duffield/pubs/DLT01-usage.pdf and N.G. Duffield and C. Lund, "Predicting Resource Usage and Estimation Accuracy in an IP Flow Measurement Collection Infrastructure", http://www.research.att.com/~duffield/pubs/p313-duffield-lund.pdf SQL plugins only. KEY: fsrc DESC: check. Enforces flow (aggregate) sampling under hard resource constraints, computed against the bytes counter and returns renormalized results. The method selects only 'fsrc' flows from the set of the flows collected during the last time window ('sql_refresh_time'), providing an unbiasied estimate of the real bytes counter. It would be also adviceable to hold the equality 'sql_refresh_time' = 'sql_history'. For further references: http://www.research.att.com/projects/flowsamp/ and specifically to the paper: N.G. Duffield, C. Lund, M. Thorup, "Flow Sampling Under Hard Resource Constraints", http://www.research.att.com/~duffield/pubs/DLT03-constrained.pdf SQL plugins only. KEY: usrf DESC: action. Applies the renormalization factor 'usrf' to counters of each aggregate. Its use is suitable for use in conjunction with uniform sampling methods (for example simple random - e.g. sFlow, 'sampling_rate' directive or simple systematic - e.g. sampled NetFlow by Cisco and Juniper). The factor is applied to recovered aggregates also. It would be also adviceable to hold the equality 'sql_refresh_time' = 'sql_history'. Before using this action to renormalize counters generated by sFlow, take also a read of the 'sfacctd_renormalize' key. SQL plugins only. KEY: adjb DESC: action. Adds (or subtracts) 'adjb' bytes to the bytes counter multiplied by the number of packet in each aggregate. This is a particularly useful action when - for example - fixed lower (link, llc, etc.) layer sizes need to be included into the bytes counter (as explained by Q7 in FAQS document). SQL plugins only. KEY: recover DESC: action. If previously evaluated checks have marked the aggregate as invalid, a positive 'recover' value makes the packet to be handled through the recovery mechanism (if enabled). SQL plugins only. For example, during a data purge, in order to filter in only aggregates counting 100KB or more the following line can be used to instrument the print plugin: 'print_preprocess: minb=100000'. DEFAULT: none KEY: [ sql_preprocess_type | print_preprocess_type | amqp_preprocess_type | kafka_preprocess_type ] VALUES: [ any | all ] DESC: When more checks are to be evaluated, this directive tells whether aggregates on the queue are valid if they just match one of the checks (any) or all of them (all). DEFAULT: any KEY: timestamps_secs VALUES: [ true | false ] DESC: Sets timestamps (ie. timestamp_start, timestamp_end, timestamp_arrival primitives) resolution to seconds, ie. prevents residual time fields like timestamp_start_residual to be populated. In nfprobe plugin, when exporting via NetFlow v9 (nfprobe_version: 9), allows to fallback to first and last swithed times in seconds. DEFAULT: false KEY: timestamps_rfc3339 VALUES: [ true | false ] DESC: Formats timestamps (ie. timestamp_start, timestamp_end, timestamp_arrival primitives) in a rfc3339 compliant way, ie. if UTC timezone yyyy-MM-ddTHH:mm:ss(.ss)Z. This is set to false for backward compatibility. DEFAULT: false KEY: timestamps_utc VALUES: [ true | false ] DESC: When presenting timestamps, decode them to UTC even if the underlying operating system is set to a different timezone. On the goodness of having a system set to UTC, please read Q18 of the FAQS document. DEFAULT: false KEY: timestamps_since_epoch VALUES [ true | false ] DESC: All timestamps (ie. timestamp_start, timestamp_end, timestamp_arrival primitives; sql_history- related fields stamp_inserted, stamp_updated; etc.) in the standard seconds since the Epoch format. This not only makes output more compact but also prevents computationally expensive time-formatting functions to be invoked, resulting in speed gains at purge time. In case the output is to a RDBMS, setting this directive to true will require changes to the default types for timestamp fields in the SQL schema. MySQL: DATETIME ==> INT(8) UNSIGNED PostgreSQL: timestamp without time zone ==> bigint SQLite3: DATETIME ==> INT(8) DEFAULT: false KEY: tcpflags_encode_as_array VALUES: [ true | false ] DESC: The 'tcpflags' field is encoded by default as a short integer where the bits related to individual TCP flags are activated. Setting this knob to true, makes it being encoded as an array for JSON and Apache Avro encodings, ie. in JSON "tcp_flags": [ "URG", "ACK", "PSH", "RST", "SYN", "FIN" ] and in Avro "name": "tcp_flags", "type": { "type": "array", "items": { "type": "string" } }. This knob has no effects for other encodings (ie. CSV, formatted) and backends not supporting complex types (ie. SQL plugins). DEFAULT: false KEY: fwd_status_encode_as_string VALUES: [ true | false ] DESC: The 'fwd_status' is encoded by default as a short integer. Setting this knob to true, makes it being encoded in human-readable format like described by RFC-7270 Section 4.12 when JSON or Avro formats are selected for output. This knob has no effects for other encodings (ie. CSV, formatted) and backends not supporting complex types (ie. SQL plugins). DEFAULT: false KEY: mpls_label_stack_encode_as_array VALUES: [ true | false ] DESC: The 'mpls_label_stack' is encoded by default as a string, including a comma-separated list of integers (label values). Setting this knob to true, makes it being encoded as an array for JSON and Apache Avro encodings, ie. in JSON "mpls_label_stack": [ "0-label0", "1-label1", "2-label2", "3-label3", "4-label4", "5-label5" ] and in Avro "name": "mpls_label_stack", "type": { "type": "array", "items": { "type": "string" } }. This knob has no effects for other encodings (ie. CSV, formatted) and backends not supporting complex types (ie. SQL plugins). DEFAULT: false KEY: tos_encode_as_dscp VALUES: [ true | false ] The 'tos' field does honour the full 8 bits. This knob conveniently allows to honour only the 6 bits used by DSCP. DEFAULT: false KEY: [ print_markers | amqp_markers | kafka_markers ] VALUES: [ true | false ] DESC: Enables the use of start/end markers each time data is purged to the backend. Both start and end markers return additional information, ie. writer PID, number of entries purged, elapsed time, etc. In the print plugin markers are available for CSV and JSON outputs; in the AMQP and Kafka plugins markers are available for JSON and Avro outputs. In the case of Kafka topics with multiple partitions, the purge_close message can arrive out of order so other mechanisms should be used to correlate messages as being part of the same batch (ie. writer_id). DEFAULT: false KEY: print_output VALUES: [ formatted | csv | json | avro | avro_json | event_formatted | event_csv | custom ] DESC: Defines the print plugin output format. 'formatted' outputs in tab-separated format; 'csv' outputs comma-separated values format, suitable for injection into 3rd party tools. 'event' variant of both formatted and cvs strips bytes and packets counters fields. 'json' outpus as JavaScript Object Notation format, suitable for injection in Big Data systems; being a self-descriptive format, JSON does not require a event-counterpart; on the cons, JSON serialization may introduce some lag due to the string manipulations (as an example: 10M lines may be written to disk in 30 secs as CSV and 150 secs as JSON). JSON format requires compiling the package against Jansson library (downloadable at the following URL: http://www.digip.org/jansson/). 'avro' outputs data using the Apache Avro data serialization format: being a binary format, it's more compact than JSON; 'avro_json' outputs as JSON-encoded Avro objects, suitable to troubleshoot and/or familiarize with the binary format itself. Both 'avro' and 'avro_json' formats require compiling against the Apache Avro library (downloadable at the following URL: http://avro.apache.org/). 'custom' allows to specify own formtting, encoding and backend management (open file, close file, markers, etc.), see print_output_custom_lib and print_output_custom_cfg_file. NOTES: * Jansson and Avro libraries don't have the concept of unsigned integers. integers up to 32 bits are packed as 64 bits signed integers, working around the issue. No work around is possible for unsigned 64 bits integers except encoding them as strings. * If the output format is 'avro' and no print_output_file was specified, the Avro-based representation of the data will be converted to JSON-encoded Avro. * If the output format is 'formatted', variable length primitives (like AS path) cannot be printed and a warning message will be output instead. This is because, intuitively, it is not possible to properly format the title line upfront with variable length fields. Please use one of the other output formats instead. DEFAULT: formatted KEY: print_output_separator DESC: Defines the print plugin output separator when print_output is set to csv or event_csv. Value is expected to be a single character with the exception of tab (\t) and space (\s) strings allowed. Being able to choose a separator comes useful in cases in which the default separator value is part of any of the supplied strings, for example certain BGP AS PATHs like "AS1_AS2_AS3_{ASX,ASY,ASZ}". DEFAULT: ',' KEY: print_output_custom_lib DESC: Full path to a non-static library file that can be dinamically linked in pmacct to provide custom formatting of output data. The two main use-cases for this feature are 1) use available encodings (ie. CSV, JSON, etc.) but fix the format of the messages in a custom way and 2) use a different encoding than the available ones. pm_custom_output structure in plugin_cmn_custom.h can be looked at for guidance of which functions are expected to exist in the library and with which arguments they would be called. See an example library file in the examples/custom directory. DEFAULT: none KEY: print_output_custom_cfg_file DESC: Full path to a file that is passed to the shared object (.so) library both at init time and at runtime, that is, when processing elements. The config file content is opaque to pmacct. DEFAULT: none KEY: [ amqp_output | kafka_output ] VALUES: [ json | avro | avro_json ] DESC: Defines the output format for messages sent to a message broker (amqp and kafka plugins). 'json' is to encode messages as JavaScript Object Notation format. 'json' format requires compiling against the Jansson library (downloadable at: http://www.digip.org/jansson/). 'avro' is to binary-encode messages with the Apache Avro serialization format; 'avro_json' is to JSON-encode messages with Avro. 'avro' and 'avro_json' formats require compiling against the Apache Avro library (downloadable at: http://avro.apache.org/). Read more on the print_output directive. DEFAULT: json KEY: avro_buffer_size DESC: When the Apache Avro format is used to encode the messages sent to a message broker (amqp and kafka plugins), this option defines the size in bytes of the buffer used by the Avro data serialization system. The buffer needs to be large enough to store at least a single Avro record. If the buffer does not have enough capacity to store the number of records defined by the [amqp, kafka]_multi_values configuration directive, the current records stored in the buffer will be sent to the message broker and the buffer will be cleared to accomodate subsequent records. DEFAULT: 8192 KEY: avro_schema_file DESC: When the Apache Avro format is used to encode the messages sent to a message broker (amqp and kafka plugins), export the schema generated to the given file path. The schema can then be used by the receiving end to decode the messages. Note that the schema will be dynamically built based on the aggregation primitives chosen (this has also effect in the print plugin but in this case the schema is also always included in the print_output_file as mandated by Avro specification). inotify-tools can be used to take event-driven actions like notify a consumer whenever the file is modified. DEFAULT: none KEY: kafka_avro_schema_registry DESC: The URL to a Confluent Avro Schema Registry. The value is passed to libserdes as argument for "schema.registry.url". A sample of the expected value being https://localhost. This is a pointer to the REST API https://docs.confluent.io/current/schema-registry/docs/api.html The schema name is auto generated: if the topic is static, the schema name is createad as (ie. if kafka_topic is set to 'foobar' then the schema name will be "foobar"); if the topic is dynamic instead, the schema name is created as "pmacct__" (ie. if plugin name is 'foobar' then the schema name will be "pmacct-kafka_foobar"). To confirm that the schema is registered, the following CL can be used: "curl -X GET https:///subjects | jq . | grep ". Until reaching a stable 'aggregate' aggregation method, it is recommended to set Schema Registry compatibility type to 'none' as the schema may change. DEFAULT: none KEY: [ print_num_protos | sql_num_protos | amqp_num_protos | kafka_num_protos ] VALUES: [ true | false ] DESC: Defines whether IP protocols (ie. tcp, udp) should be looked up and presented in string format or left numerical. The default is to look protocol names up. If this feature is not available for the intended plugin - and NetFlow/IPFIX or libpcap/ULOG daemons are used - a custom primitive can be defined (see aggregate_primitives config directive), for example in the case of NetFlow/IPFIX: name=proto_int field_type=4 len=1 semantics=u_int DEFAULT: false KEY: sql_num_hosts VALUES: [ true | false ] DESC: Defines whether IP addresses should be left numerical (in network byte ordering) or converted to human-readable string. Applies to MySQL and SQLite plugins only and assumes the INET_ATON() and INET6_ATON() function are defined in the RDBMS. INET_ATON() is always defined in MySQL whereas INET6_ATON() requires MySQL >= 5.6.3. Both functions are not defined by default in SQLite instead and are to be user-defined. Default setting, false, is to convert IP addresses and prefixes into strings. If this feature is not available for the intended plugin - and NetFlow/IPFIX or libpcap/ULOG daemons are in use - a custom primitive can be defined (see aggregate_primitives configuration directive), for example in the case of NetFlow/IPFIX: name=src_host_int field_type=8 len=4 semantics=u_int name=dst_host_int field_type=12 len=4 semantics=u_int DEFAULT: false KEY: [ nfacctd_port | sfacctd_port ] (-l) [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines the UDP port where to bind nfacctd (nfacctd_port) and sfacctd (sfacctd_port) daemons. On systems where SO_REUSEPORT feature is available: it allows multiple daemons to bind the same local address and port in order to load-balance processing of incoming packets; if doing so with incoming NetFlow v9/IPFIX template-based protocols, nfacctd_templates_receiver and nfacctd_templates_port should be used. At the end of this document, reference (1) to a URL to a presentation of the SO_REUSEPORT feature. To enable SO_REUSEPORT on a Linux system supporting it 'sysctl net.core.allow_reuseport=1'. DEFAULT: nfacctd_port: 2100; sfacctd_port: 6343 KEY: [ nfacctd_ip | sfacctd_ip ] (-L) [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines the IPv4/IPv6 address where to bind the nfacctd (nfacctd_ip) and sfacctd (sfacctd_ip) daemons. DEFAULT: all interfaces KEY: [ nfacctd_interface | sfacctd_interface ] [GLOBAL] DESC: Defines the interface for the nfacctd / sfacctd daemon to listen on making it possible to receive data in VRFs on Linux. If having to listen on an IPv6 address inside the VRF, this has to be specified via the relevant config directive, ie. nfacctd_ip / sfacctd_ip, as not doing so prevents the daemon to correctly receive data. DEFAULT: none KEY: [ nfacctd_ipv6_only | sfacctd_ipv6_only ] [GLOBAL, NO_PMACCTD, NO_UACCTD] VALUES: [ true | false ] DESC: When listening on all interfaces (default setting for nfacctd_ip and sfacctd_ip) and IPv6 is enabled, it is possible to connect with both IPv4 (IPv6 IPv4-mapped) and IPv6. Setting this knob to true disables the IPv4 (IPv6 IPv4-mapped) part. DEFAULT: false KEY: [ nfacctd_rp_ebpf_prog | sfacctd_rp_ebpf_prog ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: If SO_REUSEPORT is supported by the Operating System (read more about this feature at the config key [ns]facctd_port) and eBPF support is configured when compiling (--enable-ebpf), this allows to load a custom load-balancer. To load-share, daemons have to be part of the same cluster_name and each be configured with a distinct cluster_id. An example of such eBPF program is available here: https://github.com/insa-unyte/ebpf-loadbalancer . Note: Linux kernel 4.x does not yet support eBPF locking so daemons have currently to be (re-) started with a short time gap to avoid race conditions. DEFAULT: none KEY: [ nfacctd_kafka_broker_host | sfacctd_kafka_broker_host ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines one or multiple, comma-separated, Kafka brokers to receive NetFlow/IPFIX and sFlow from. See kafka_broker_host for more info. DEFAULT: none KEY: [ nfacctd_kafka_broker_port | sfacctd_kafka_broker_port ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines the Kafka broker port to receive NetFlow/IPFIX and sFlow from. See kafka_broker_host for more info. DEFAULT: 9092 KEY: [ nfacctd_kafka_config_file | sfacctd_kafka_config_file ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Full pathname to a file containing directives to configure librdkafka to receive NetFlow/IPFIX and sFlow from. See kafka_config_file for more info. DEFAULT: none KEY: [ nfacctd_kafka_topic | sfacctd_kafka_topic ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Name of the Kafka topic to receive NetFlow/IPFIX and sFlow from. No variables are supported for dynamic naming of the topic. See kafka_topic for more info. DEFAULT: none KEY: [ nfacctd_zmq_address | sfacctd_zmq_address ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines the ZeroMQ queue address (host and port) to connect to for consuming NetFlow/IPFIX and sFlow from. An example of the expected value is "127.0.0.1:50000". DEFAULT: none KEY: core_proc_name [GLOBAL] DESC: Defines the name of the core process. This is the equivalent to instantiate named plugins but for the core process. DEFAULT: 'default' KEY: proc_priority DESC: Redefines the process scheduling priority, equivalent to using the 'nice' tool. Each daemon process, ie. core, plugins, etc., can define a different priority. DEFAULT: 0 KEY: [ nfacctd_allow_file | sfacctd_allow_file ] [GLOBAL, MAP, NO_PMACCTD, NO_UACCTD] DESC: Full pathname to a file containing the list of IPv4/IPv6 addresses/prefixes (one for each line) allowed to send packets to the daemon. The allow file is intended to be small; for longer ACLs, firewall rules should be preferred instead. If no allow file is specified, intuitively, that means 'allow all'; if an allow file is specified but its content is empty, that means 'deny all'. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). Sample map in examples/allow.lst.example . DEFAULT: none (ie. allow all) KEY: nfacctd_time_secs [GLOBAL, NFACCTD_ONLY] VALUES: [ true | false ] DESC: Makes 'nfacctd' expect times included in NetFlow header to be in seconds rather than msecs. This knob makes sense for NetFlow v5 since in NetFlow v9 and IPFIX different fields are reserved for secs and msecs timestamps, increasing collector awareness. DEFAULT: false KEY: [ nfacctd_time_new | pmacctd_time_new | sfacctd_time_new ] [GLOBAL, NO_UACCTD] VALUES: [ true | false ] DESC: Makes the daemon to ignore external timestamps associated to data, ie. included in NetFlow header or pcap header, and generate new ones (reflecting data arrival time to the collector). This gets particularly useful to assign flows to time-bins based on the flow arrival time at the collector rather than the flow original (start) time. DEFAULT: false KEY: nfacctd_pro_rating [NFACCTD_ONLY] VALUES: [ true | false ] DESC: If nfacctd_time_new is set to false (default) and historical accounting (ie. sql_history) is enabled, this directive enables pro rating of NetFlow/IPFIX flows over time-bins, if needed. For example, if sql_history is set to '5m' (so 300 secs), the considered flow duration is 1000 secs, its bytes counter is 1000 bytes and, for simplicity, its start time is at the base time of t0, time-bin 0, then the flow is inserted in time-bins t0, t1, t2 and t3 and its bytes counter is proportionally split among these time-bins: 300 bytes during t0, t1 and t2 and 100 bytes during t3. NOTES: If NetFlow sampling is enabled, it is recommended to have counters renormalization enabled (nfacctd_renormalize set to true). DEFAULT: false KEY: nfacctd_templates_file [GLOBAL, NFACCTD_ONLY] DESC: Full pathname to a file to store JSON-serialized templates for NetFlow v9/IPFIX data. At startup, nfacctd reads templates stored in this file (if any and if the file exists) in order to reduce the initial amount of dropped packets due to unknown templates. In steady state, templates received from the network are stored in this file. Warning: if, at startup time, data records are encoded with a template structure different than the one that was stored in the file, effectiveness of this feature is (intuitively) greatly reduced. This file will be created if it does not exist. Certain numeric values may be encoded in network byte order. This feature requires compiling against Jansson library (--enable-jansson when configuring pmacct for compiling). DEFAULT: none KEY: nfacctd_templates_receiver [GLOBAL, NFACCTD_ONLY] DESC: Defines a receiver where to export NetFlow v9/IPFIX templates, ideally a replicator. To help in clustered scenarios especially when leveraging SO_REUSEPORT (multiple nfacctd listening on the same IP and port). If IPv4, the value is expected as 'address:port'. If IPv6, it is expected as '[address]:port'. DEFAULT: none KEY: nfacctd_templates_port [GLOBAL, NFACCTD_ONLY] DESC: Defines the UDP port where to bind nfacctd for receiving (replicated) templates. If a template is received on this port and nfacctd_templates_receiver is specified, it is not replicated (in order to avoid the case of infinite loops). DEFAULT: none KEY: nfacctd_dtls_port [GLOBAL, NFACCTD_ONLY] DESC: Defines the UDP port where to bind nfacctd for receiving NetFlow/IPFIX over DTLS. Needs pmacct to be configured for compiling with the --enable-gnutls knob. The files (key, certificate, etc.) required by DTLS are to be supplied via the dtls_path config directive. DEFAULT: none KEY: [ nfacctd_stitching | sfacctd_stitching | pmacctd_stitching | uacctd_stitching ] VALUES: [ true | false ] DESC: If set to true adds two new fields, timestamp_min and timestamp_max: given an aggregation method ('aggregate' config directive), timestamp_min is the timestamp of the first element contributing to a certain aggregate, timestamp_max is the timestamp of the last element. In case the export protocol provides time references, ie. NetFlow/IPFIX, these are used; if not of if using NetFlow/IPFIX as export protocol and nfacctd_time_new is set to true the current time (hence time of arrival to the collector) is used instead. The feature is not compatible with pro-rating, ie. nfacctd_pro_rating. Also, the feature is supported on all plugins except the 'memory' one (please get in touch if you have a use-case for it). DEFAULT: false KEY: nfacctd_account_options [GLOBAL, NFACCTD_ONLY] VALUES: [ true | false ] DESC: If set to true account for NetFlow/IPFIX option records. This will require define custom primitives via aggregate_primitives. pre_tag_map offers sample_type value of 'option' in order to split option data records from flow or event data ones. DEFAULT: false KEY: [ nfacctd_as | sfacctd_as | pmacctd_as | uacctd_as ] [GLOBAL] VALUES: [ netflow | sflow | file | bgp | bmp | longest ] DESC: When set to 'netflow' or 'sflow' it instructs nfacctd and sfacctd to populate 'src_as', 'dst_as', 'peer_src_as' and 'peer_dst_as' primitives from information in NetFlow and sFlow datagrams; when set to 'file', it instructs nfacctd and sfacctd to populate 'src_as', 'dst_as' and 'peer_dst_as' by looking up source and destination IP addresses against a supplied networks_file. When 'bgp' or 'bmp' is specified, source and destination IP addresses are looked up against the BGP RIB of the peer from which the NetFlow (or sFlow) datagram was received (see also bgp_agent_map directive for more complex mappings). 'longest' behaves in a longest-prefix match wins fashion: in nfacctd and sfacctd lookup is done against a networks_file (if specified), sFlow/NetFlow protocol and BGP/BMP (if the BMP/BGP thread is started) with the following logics: networks_file < sFlow/NetFlow <= BGP/BMP; in pmacctd and uacctd 'longest' logics is networks_file <= BGP/BMP. Read nfacctd_net description for an example of operation of the 'longest' method. Unless there is a specific goal do achieve, it is highly recommended that this definition, ie. nfacctd_as, is kept in sync with its net equivalent, ie. nfacctd_net. DEFAULT: none KEY: [ nfacctd_net | sfacctd_net | pmacctd_net | uacctd_net ] [GLOBAL] VALUES: [ netflow | sflow | mask | file | igp | bgp | bmp | longest ] DESC: Determines the method for performing IP prefix aggregation - hence directly influencing 'src_net', 'dst_net', 'src_mask', 'dst_mask' and 'peer_dst_ip' primitives. 'netflow' and 'sflow' get values from NetFlow and sFlow protocols respectively; these keywords are only valid in nfacctd, sfacctd. 'mask' applies a defined networks_mask; 'file' selects a defined networks_file; 'igp', 'bgp' and 'bmp' source values from IGP/IS-IS, BGP and BMP daemon respectively. For backward compatibility, the default behaviour in pmacctd and uacctd is: 'mask' and 'file' are turned on if a networks_mask and a networks_file are respectively specified by configuration. If they are both defined, the outcome will be the intersection of their definitions. 'longest' behaves in a longest-prefix match wins fashion: in nfacctd and sfacctd lookup is done against a networks list (if networks_file is defined) sFlow/ NetFlow protocol, IGP (if the IGP thread started) and BGP/BMP (if the BGP/BMP thread is started) with the following logics: networks_file < sFlow/NetFlow < IGP <= BGP/BMP; in pmacctd and uacctd 'longest' logics is: networks_file < IGP <= BGP/BMP. For example we receive the following PDU via NetFlow: SrcAddr: 10.0.8.29 (10.0.8.29) DstAddr: 192.168.5.47 (192.168.5.47) [ .. ] SrcMask: 24 (prefix: 10.0.8.0/24) DstMask: 27 (prefix: 192.168.5.32/27) a BGP peering is available and BGP contains the following prefixes: 192.168.0.0/16 and 10.0.0.0/8. A networks_file contains the prefixes 10.0.8.0/24 and 192.168.5.0/24. 'longest' would select as outcome of the network aggregation process 10.0.8.0/24 for the src_net and src_mask respectively and 192.168.5.32/27 for dst_net and dst_mask. Unless there is a specific goal to achieve, it is highly recommended that the definition of this configuration directive is kept in sync with its ASN equivalent, ie. nfacctd_as. DEFAULT: nfacctd: 'netflow'; sfacctd: 'sflow'; pmacctd and uacctd: 'mask', 'file' KEY: use_ip_next_hop [GLOBAL] VALUES: [ true | false ] DESC: When IP prefix aggregation (ie. nfacctd_net) is set to 'netflow', 'sflow' or 'longest' (in which case longest winning match is via 'netflow' or 'sflow') populate 'peer_dst_ip' field from NetFlow/sFlow IP next hop field if BGP next-hop is not available. DEFAULT: false KEY: [ nfacctd_mcast_groups | sfacctd_mcast_groups ] [GLOBAL, NO_PMACCTD, NO_UACCTD] DESC: Defines one or more IPv4/IPv6 multicast groups to be joined by the daemon. If more groups are supplied, they are expected comma separated. A maximum of 20 multicast groups may be joined by a single daemon instance. Some OS (noticeably Solaris -- seems) may also require an interface to bind to which - in turn - can be supplied declaring an IP address ('nfacctd_ip' key). DEFAULT: none KEY: [ nfacctd_disable_checks | sfacctd_disable_checks ] [GLOBAL, NO_PMACCTD, NO_UACCTD] VALUES: [ true | false ] DESC: Both nfacctd and sfacctd can log warning messages for failing basic checks against incoming NetFlow/sFlow datagrams, ie. sequence number checks, protocol version. You may want to disable such feature, default, because of buggy or non-standard implementations. Also, for sequencing checks, the 'export_proto_seqno' primitive is recommended instead (see 'aggregate' description and notes). DEFAULT: true KEY: nfacctd_disable_opt_scope_check [GLOBAL, ONLY_NFACCTD] VALUES: [ true | false ] DESC: Mainly a workaround to implementations not encoding NetFlow v9/IPIFX option scope correctly, this knob allows to disable option scope checking. By doing so, options are considered scoped to the system level (ie. to the IP address of the expoter). DEFAULT: false KEY: pre_tag_map [MAP] DESC: Full pathname to a file containing specific tags for data. For all daemons, tags (be that numerical 'tag' or stringy 'label') can be exposed in output data; traffic daemons (ie. pmacctd, nfacctd, sfacctd, etc.) need 'tag', 'tag2' or 'label' primitives to be included in the 'aggregate' aggregation method. Again (only) in traffic daemons, all of which do feature a plugin-based architecture, tags can be used for filtering purposes (see the pre_tag_filter, pre_tag_label_filter config directives). Take a look to the examples/ sub-tree for all supported keys and detailed examples (pretag.map.example). In traffic daemons the evaluation of a pre_tag_map does override any tags passed via NetFlow/sFlow by a pmacct nfprobe/sfprobe plugin. The maximum number of entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: maps_entries DESC: Defines the maximum number of entries a map can contain (ie. pre_tag_map and all directives with the 'MAP' flag in this document). The default value is suitable for most scenarios, although tuning it could be required either to save on memory or to allow for more entries. DEFAULT: 384 KEY: maps_row_len DESC: Defines the maximum length of map entries (ie. pre_tag_map and all directives with the 'MAP' flag in this document). The default value is suitable for most scenarios, although tuning it could be wanted either to save on memory or to allow for longer entries (ie. for complex bpf filters). DEFAULT: 256 KEY: maps_refresh [GLOBAL] VALUES: [ true | false ] DESC: When enabled, this directive allows to reload map files (ie. pre_tag_map and all directives with the 'MAP' flag in this document) without restarting the daemon instance. For example, it may result particularly useful to reload pre_tag_map or networks_file entries in order to reflect some change in the network. After having modified the map files, a SIGUSR2 has to be sent (e.g.: in the simplest case "killall -USR2 pmacctd") to the daemon to notify the change. If a signal is sent to the daemon and this directive is set to 'false', the signal is silently discarded. Since signals can be sent either to the whole daemon (killall) or to just a specific process (kill), this mechanism also offers the advantage to elicit local reloads. DEFAULT: true KEY: maps_index [GLOBAL] VALUES: [ true | false ] DESC: Enables indexing of maps (ie. pre_tag_map) to increase lookup speeds on large maps and/or sustained lookup rates. Indexes are automatically defined basing on structure and content of the map, up to a maximum of 8 (one index is required per each combination of lookup keys in the map). Indexing of pre_tag_map, bgp_peer_src_as_map, flow_to_rd_map is supported. Only a sub-set of pre_tag_map keys are supported, including: ip, bgp_nexthop, vlan, cvlan, src_mac, dst_mac, src_net, dst_net, mpls_vpn_rd, mpls_pw_id, src_as, dst_as, peer_src_as, peer_dst_as, input, output. For keys accepting IP addresses as value (ie. ip, src_net and dst_net) specific IP addresses, ie. /32 for v4 and /128 for v6, are supported throughout. Also, negations are not supported (ie. 'in=-216' match all but input interface 216). bgp_agent_map and sampling_map implement a separate caching mechanism and hence do not leverage this feature. DEFAULT: false NOTES: * Initial support for networks has been introduced for src_net and dst_net keys: in any entry, only one key can include a network because matrixing of networks would degrade performances of the current implementation. A construction like the following would be perfectly valid, ie.: label=src_A src_net=X/24 jeq=dst_net label=src_B src_net=Y/25 jeq=dst_net label=src_C src_net=Z/26 jeq=dst_net label=dst_A dst_net=X/24 label=dst_net label=dst_B dst_net=Y/25 label=dst_C dst_net=Z/26 KEY: pre_tag_filter, pre_tag2_filter [NO_GLOBAL] VALUES: [ 0-2^64-1 ] DESC: Expects one or more tags as value (when multiple tags are supplied, they need to be comma separated and a logical OR is used in the evaluation phase) and allows to filter aggregates basing upon their tag (or tag2) value: in case of a match, data is allwoed in, ie. it is delivered to the plugin the filter is attached to. This directive has to be attached to a plugin (that is, it cannot be global) and is suitable, for example, to split data among the active plugins. This directive also allows to specify a value '0' to match untagged data, thus allowing to split tagged traffic from untagged one. It also allows negations by pre-pending a minus sign to the tag value (ie. '-6' would send everything but traffic tagged as '6' to the plugin it is attached to, hence achieving a filter out behaviour) and ranges (ie. '10-20' would send over traffic tagged in the range 10..20) and any combination of these. This directive makes sense if coupled with 'pre_tag_map'. DEFAULT: none KEY: pre_tag_label_filter [NO_GLOBAL] DESC: Expects one or more labels as value (when multiple labels are supplied, they need to be comma separated and a logical OR is performed when evaluating at runtime) and allows to filter in data basing upon label value(s): in case of match, data is delivered to the plugin. This directive has to be attached to a plugin (that is, it cannot be global). Null label values (ie. unlabelled data) can be matched using the special 'null' keyword. Negations are allowed by pre-pending a minus sign to the label value. The use of this directive is meant coupled with a 'pre_tag_map'; it is also currenly not compatible with the use of pre_tag_label_encode_as_map except for the basic use-case of filtering null vs non-null labels. DEFAULT: none KEY: pre_tag_label_encode_as_map VALUES: [ true | false ] DESC: The 'label' field is encoded by default as an unique comma-separated string, ie. in JSON "label": "value1,value2,value3". Setting this knob to true, makes it being encoded as a map for JSON and Apache Avro encodings, ie. in JSON "label": { "key1": "value1", "key2": "value2" }. For keys and values to be correctly mapped, the '%' delimiter is used when composing a pre_tag_map, ie. "set_label=key1%value1,key2%value2 ip=0.0.0.0/0". This knob has no effects for other encodings (ie. CSV, formatted) and backends not supporting complex types (ie. SQL plugins). DEFAULT: false KEY: [ post_tag | post_tag2 ] VALUES: [ 1-2^64-1 ] DESC: Expects a tag as value. Post-Tagging is evaluated in the plugins. The tag is used as 'tag' (post_tag) or 'tag2' (post_tag2) primitive value. Use of these directives hence makes sense if tag and/or tag2 primitives are part of the plugin aggregation method. post_tag does override any value computed by pre_tag_map. DEFAULT: none KEY: sampling_rate VALUES: [ >= 1 ] DESC: Enables packet sampling. It expects a number which is the mean ratio of packets to be sampled (1 out of N). The currently implemented sampling algorithm is a simple randomic one. If using any SQL plugin, look also to the powerful 'sql_preprocess' layer and the more advanced sampling choices it offers: they will allow to deal with advanced sampling scenarios (e.g. probabilistic methods). Finally, this 'sampling_rate' directive can be renormalized by renormalize feature, ie. pmacctd_renormalize, or by using the 'usrf' action of the 'sql_preprocess' layer. DEFAULT: none KEY: sampling_map [GLOBAL, NO_PMACCTD, NO_UACCTD, MAP] DESC: Full pathname to a file containing traffic sampling mappings. It is mainly meant to be used in conjunction with nfacctd and sfacctd for the purpose of fine-grained reporting of sampling rates ('sampling_rate' primitive) circumventing bugs and issues in router operating systems. If counters renormalization is wanted, nfacctd_renormalize or sfacctd_renormalize must be also set to true. If a specific router is not defined in the map, the sampling rate advertised by the router itself is applied. Take a look to the examples/ sub-tree 'sampling.map.example' for all supported keys and detailed examples. Number of map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: [ pmacctd_force_frag_handling | uacctd_force_frag_handling ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] VALUES: [ true | false ] DESC: Forces 'pmacctd' to join together IPv4/IPv6 fragments: 'pmacctd' does this only whether any of the port primitives are selected (src_port, dst_port, sum_port); in fact, when not dealing with any upper layer primitive, fragments are just handled as normal packets. However, available filtering rules ('aggregate_filter', Pre-Tag filter rules) will need such functionality enabled whether they need to match TCP/UDP ports. So, this directive aims to support such scenarios. DEFAULT: false KEY: [ pmacctd_frag_buffer_size | uacctd_frag_buffer_size ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines the maximum size of the fragment buffer. In case IPv6 is enabled two buffers of equal size will be allocated. The value is expected in bytes. DEFAULT: 4MB KEY: [ pmacctd_flow_buffer_size | uacctd_flow_buffer_size ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines the maximum size of the flow buffer. This is an upper limit to avoid unlimited growth of the memory structure. This value has to scale accordingly to the link traffic rate. In case IPv6 is enabled two buffers of equal size will be allocated. The value is expected in bytes. DEFAULT: 16MB KEY: [ pmacctd_flow_buffer_buckets | uacctd_flow_buffer_buckets ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines the number of buckets of the flow buffer - which is organized as a chained hash table. To exploit better performances, the table should be reasonably flat. This value has to scale to higher power of 2 accordingly to the link traffic rate. For example, it has been reported that a value of 65536 works just fine under full 100Mbit load. DEFAULT: 256 KEY: [ pmacctd_conntrack_buffer_size | uacctd_conntrack_buffer_size ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines the maximum size of the connection tracking buffer. In case IPv6 is enabled two buffers of equal size will be allocated. The value is expected in bytes. DEFAULT: 8MB KEY: [ pmacctd_flow_lifetime | uacctd_flow_lifetime ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines how long a non-TCP flow could remain inactive (ie. no packets belonging to such flow are received) before considering it expired. The value is expected in seconds. DEFAULT: 60 KEY: [ pmacctd_flow_tcp_lifetime | uacctd_flow_tcp_lifetime ] [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines how long a TCP flow could remain inactive (ie. no packets belonging to such flow are received) before considering it expired. The value is expected in seconds. DEFAULT: 60 secs if classification is disabled; 432000 secs (120 hrs) if clssification is enabled KEY: [ pmacctd_ext_sampling_rate | uacctd_ext_sampling_rate | nfacctd_ext_sampling_rate | sfacctd_ext_sampling_rate ] [GLOBAL] Flags that captured traffic is being sampled at the specified rate. Such rate can then be reported ('sampling_rate' primitive), renormalized by using ie. 'pmacctd_renormalize' or exported by the nfprobe/sfprobe plugins. External sampling might be performed by capturing frameworks the daemon is linked against (ie. PF_RING, NFLOG) or appliances (ie. sampled packet mirroring). In nfacctd and sfacctd daemons this directive can be used to tackle corner cases, ie. sampling rate reported by the NetFlow/sFlow agent is missing or not correct; in such cases sampling_map can be alternatively used to define sampling rate per exporter, ie. in case the rate is not omogeneous across all exporters. DEFAULT: none KEY: [ sfacctd_renormalize | nfacctd_renormalize | pmacctd_renormalize | uacctd_renormalize ] (-R) [GLOBAL] VALUES: [ true | false ] DESC: Automatically renormalizes bytes/packet counters value basing on available sampling info. The feature also calculates an effective sampling rate (sFlow only) which could differ from the configured one - expecially at high rates - because of various losses; such estimated rate is then used for renormalization purposes. DEFAULT: false KEY: [ sfacctd_nonroot | nfacctd_nonroot | pmacctd_nonroot ] [GLOBAL] VALUES: [ true | false ] DESC: Allow to run daemons from a user with non root privileges. This can be desirable on systems supporting a tool like setcap to assign specific system capabilities to unprivileged users. A couple of examples: allow nfacctd to bind to BGP port: "setcap 'cap_net_bind_service=+ep' /path/to/nfacctd ; allow a sfacctd replicator to forward packets transparently (spoofing): "setcap 'cap_net_raw=+ep' /path/to/nfacctd ; allow pmacctd to bind and use libpcap: "setcap 'cap_net_raw,cap_net_admin=+ep' /path/to/pmacctd". DEFAULT: false KEY: sfacctd_counter_file [GLOBAL, SFACCTD_ONLY] DESC: Enables streamed logging of sFlow counters. Each log entry features a time reference, sFlow agent IP address event type and a sequence number (to order events when time reference is not granular enough). Currently it is not possible to filter in/out specific counter types (ie. generic, ethernet, vlan, etc.). The list of supported filename variables follows: $peer_src_ip sFlow agent IP address. Files can be re-opened by sending a SIGHUP to the daemon core process. The output file can be a named pipe (ie. created with mkfifo), however it has to be manually created in advance. DEFAULT: none KEY: sfacctd_counter_output [GLOBAL, SFACCTD_ONLY] VALUES: [ json ] DESC: Defines output format for the streamed logging of sFlow counters. Only JSON format is currently supported and requires compiling against Jansson library (--enable-jansson when configuring for compiling). DEFAULT: json KEY: sql_locking_style VALUES: [ table | row | none ] DESC: Defines the locking style for the SQL table. MySQL supports "table" and "none" values whereas PostgreSQL supports "table", "row" and "none" values. With "table" value, the plugin will lock the entire table when writing data to the DB with the effect of serializing access to the table whenever multiple plugins need to access it simultaneously. Slower but light and safe, ie. no risk for deadlocks and transaction-friendly; "row", the plugin will lock only the rows it needs to UPDATE/DELETE. It results in better overral performances but has some noticeable drawbacks in dealing with transactions and making the UPDATE-then-INSERT mechanism work smoothly; "none" disables locking: while generally not recommended, this may suit some advanced use-cases or be needed when a locking mechanism is not available (ie. Infinidb/ Columnstore in MariaDB). DEFAULT: table KEY: nfprobe_timeouts DESC: Allows to tune a set of timeouts to be applied over collected packets. The value is expected in the following form: 'name=value:name=value:...'. The set of supported timeouts, in seconds, and their default values are listed below: tcp (generic tcp flow life) 3600 tcp.rst (TCP RST flow life) 120 tcp.fin (TCP FIN flow life) 300 udp (UDP flow life) 300 icmp (ICMP flow life) 300 general (generic flow life) 3600 maxlife (maximum flow life) 604800 expint (expiry interval) 60 expint is the interval between expiry checks, ie. every 60 secs it is checked which flows are ready for timeout-based evictioni; unscheduled evictions are possible if it's not possible to allocate more memory to cache flows. tcp, tcp.rst, tcp.fin, udp, icmp and general are passive timeouts, ie. a tcp flow is evicted after 3600 secs of inactivity ('general' applies to any IP protocol not being specified by other timeouts). maxlife is an active timeout and evicts flows even if still active and making traffic. DEFAULT: see above KEY: nfprobe_hoplimit VALUES: [ 1-255 ] DESC: Value of TTL for the newly generated NetFlow datagrams. DEFAULT: Operating System default KEY: nfprobe_maxflows DESC: Maximum number of flows that can be tracked simultaneously. DEFAULT: 8192 KEY: nfprobe_receiver DESC: Defines the remote IP address/hostname and port to which NetFlow datagrams are to be exported. If IPv4, the value is expected as 'address:port'. If IPv6, it is expected as '[address]:port'. DEFAULT: 127.0.0.1:2100 KEY: nfprobe_dtls VALUES: [ true | false ] DESC: Enables sending out NetFlow/IPFIX packets over DTLS. Needs pmacct to be configured for compiling with the --enable-gnutls knob. The files (key, certificate, etc.) required by DTLS are to be supplied via the dtls_path config directive. DEFAULT: false KEY: nfprobe_dtls_verify_cert DESC: If nfprobe_dtls is set to true, this validates that the certificate received from the server corresponds to the specified hostname. Sample of an expected value would be "www.example.com". DEFAULT: none KEY: nfprobe_source_ip DESC: Defines the local IP address from which NetFlow datagrams are exported. Only a numerical IPv4/ IPv6 address is expected. The supplied IP address is required to be already configured on one of the interfaces. This parameter is also required for graceful encoding of NetFlow v9 and IPFIX option scoping. DEFAULT: IP address is selected by the Operating System KEY: nfprobe_version VALUES: [ 5, 9, 10 ] DESC: Version of outgoing NetFlow datagrams. NetFlow v5/v9 and IPFIX (v10) are supported. NetFlow v5 features a fixed record structure and if not specifying an 'aggregate' directive it gets populated as much as possible; NetFlow v9 and IPFIX feature a dynamic template-based structure instead and by default it is populated as: 'src_host, dst_host, src_port, dst_Port, proto, tos'. DEFAULT: 10 KEY: nfprobe_engine DESC: Allows to define Engine ID and Engine Type fields for NetFlow v5 and Source ID/Obs Domain ID for NetFlow v9 and IPFIX respectiely. In case of NetFlow v5 export it expects two non-negative numbers, each up to maximum 8-bits length and separated by the ":" symbol; in case of NetFlow v9/IPFIX it expects a single non-negative number up-to maximum 32-bits length. This comes useful to allow a collector to distinguish between distinct probe instances running on the same host (collector would report missing flows due to sequencing jumps); this is also important for letting NetFlow v9/IPFIX templates to work correctly: in fact, template IDs get automatically selected only inside single daemon instances. DEFAULT: [ 0:0, 0 ] KEY: [ nfacctd_peer_as | sfacctd_peer_as | nfprobe_peer_as | sfprobe_peer_as ] VALUES: [ true | false ] DESC: When applied to [ns]fprobe src_as and dst_as fields are valued with peer-AS rather than origin-AS as part of the NetFlow/sFlow export. Requirements to enable this feature on the probes are: a) one of the nfacctd_as/sfacctd_as/pmacctd_as/uacctd_as set to 'bgp' and b) a fully functional BGP daemon (bgp_daemon). When applied to [ns]facctd instead it uses src_as and dst_as values of the NetFlow/sFlow export to populate peer_src_as and peer_dst_as primitives. DEFAULT: false KEY: [ nfprobe_ipprec | sfprobe_ipprec | tee_ipprec ] DESC: Marks self-originated NetFlow (nfprobe) and sFlow (sfprobe) messages with the supplied IP precedence value. DEFAULT: 0 KEY: [ nfprobe_direction | sfprobe_direction ] VALUES: [ in, out, tag, tag2 ] DESC: Defines traffic direction. Can be statically defined via 'in' and 'out' keywords. It can also be dynamically determined via lookup to either 'tag' or 'tag2' values. Tag value of 1 will be mapped to 'in' direction, whereas tag value of 2 will be mapped to 'out'. The idea underlying tag lookups is that pre_tag_map supports, among the other features, 'filter' matching against a supplied tcpdump-like filter expression; doing so against L2 primitives (ie. source or destination MAC addresses) allows to dynamically determine traffic direction (see example at 'examples/pretag.map.example'). DEFAULT: none KEY: [ nfprobe_ifindex | sfprobe_ifindex ] VALUES: [ tag, tag2, <1-4294967295> ] DESC: Associates an interface index (ifIndex) to a given nfprobe or sfprobe plugin. This is meant as an add-on to [ns]probe_direction directive, ie. when multiplexing mirrored traffic from different sources on the same interface (ie. split by VLAN). Can be statically defined via a 32-bit integer or semi-dynamically determined via lookup to either 'tag' or 'tag2' values (read full elaboration on [ns]probe_direction directive). Unless [ns]fprobe_ifindex_override is set true, by default this definition will be overridden whenever the ifIndex can be determined dynamically (ie. via NFLOG framework). DEFAULT: none KEY: [ nfprobe_ifindex_override | sfprobe_ifindex_override ] VALUES: [ true | false ] DESC: If an ifIndex can be determined dynamically (ie. via NFLOG framework), setting this to true allows for a non-zero value computed by [sn]fprobe_ifindex to override the original value; if the value is zero, the override does not take place. DEFAULT: false KEY: nfprobe_dont_cache VALUES: [ true | false ] DESC: Disables caching and summarisation of flows. By default a NetFlow/IPFIX agent would attempt to build uni-directional flows by caching individual packets and waiting for an expiration condition (see nfprobe_timeouts). This knob prevents that to happen and, if paired with a packet sampling strategy (external or ie. pmacctd_ext_sampling_rate), it makes a NetFlow/ IPFIX agent to match sFlow export responsiveness. DEFAULT: false KEY: nfprobe_tstamp_usec VALUES: [ true | false | DESC: Exports timestamps to the usec resolution (instead of default msec) using NetFlow v9 / IPFIX IEs 154 and 155. This knob is not compatible with timestamps_secs configuration directive. DEFAULT: false KEY: sfprobe_receiver DESC: Defines the remote IP address/hostname and port to which NetFlow datagrams are to be exported. If IPv4, the value is expected as 'address:port'. If IPv6, it is expected as '[address]:port'. DEFAULT: 127.0.0.1:6343 KEY: sfprobe_agentip DESC: Sets the value of agentIp field inside the sFlow datagram header. Only a numerical IPv4/ IPv6 address is expected. This value must be an IPv4 address if transport, that is sfprobe_source_ip and/or sfprobe_receiver, is set to IPv4; or an IPv6 address if transport is set to IPv6. DEFAULT: localhost KEY: sfprobe_agentsubid DESC: Sets the value of agentSubId field inside the sFlow datagram header. DEFAULT: 1402 KEY: sfprobe_ifspeed DESC: Statically associates an interface speed to a given sfprobe plugin. Value is expected in bps. DEFAULT: 100000000 KEY: sfprobe_source_ip DESC: Defines the local IP address from which sFlow datagrams are exported. Only a numerical IPv4/ IPv6 address is expected. The supplied IP address is required to be already configured on one of the interfaces. An IPv6 address must be configured in order to successfully export to an IPv6 sfprobe_receiver. DEFAULT: IP address is selected by the Operating System KEY: bgp_daemon [GLOBAL] VALUES: [ true | false ] DESC: Enables the BGP daemon thread. Neighbors are not defined explicitely but a maximum amount of peers is specified (bgp_daemon_max_peers); also, for security purposes, the daemon does not implement outbound BGP UPDATE messages and acts passively (ie. it never establishes a connection to a remote peer but waits for incoming connections); upon receipt of a BGP OPEN message the local daemon presents itself as belonging to the same AS number as the remote peer, unless bgp_daemon_as is set, and supporting the same (or a subset of the) BGP capabilities; capabilities currently supported are MP-BGP, 4-bytes ASNs, ADD-PATH. Per-peer RIBs are maintained. For some ADD-PATH capability notes, please check the "BGP daemon implementation concluding notes" section of the QUICKSTART document. DEFAULT: false KEY: bmp_daemon [GLOBAL] VALUES: [ true | false ] DESC: Enables the BMP daemon thread. BMP, BGP Monitoring Protocol, can be used to monitor BGP sessions. The BMP daemon supports BMP data, events and stats, ie. initiation, termination, peer up, peer down, stats and route monitoring messages. The daemon enables to write BMP messages to files, AMQP and Kafka brokers, real-time (msglog) or at regular time intervals (dump). Also, route monitoring messages are saved in a RIB structure for IP prefix lookup. For further referece see examples in the QUICKSTART document and/or description of the bmp_* config keys in this document. The BMP daemon is a separate thread in the NetFlow (nfacctd) and sFlow (sfacctd) collectors. DEFAULT: false KEY: [ bgp_daemon_ip | bmp_daemon_ip ] [GLOBAL] DESC: Binds the BGP/BMP daemon to a specific interface. Expects as value an IP address. For the BGP daemon the same is value is presented as BGP Router-ID (read more about the BGP Router-ID selection process at the bgp_daemon_id config directive description). Setting this directive is highly adviced. DEFAULT: 0.0.0.0 KEY: [ bgp_daemon_ipv6_only | bmp_daemon_ipv6_only ] [GLOBAL, NO_PMACCTD, NO_UACCTD] VALUES: [ true | false ] DESC: When listening on all interfaces (default setting for nfacctd_ip and sfacctd_ip) and IPv6 is enabled, it is possible to connect with both IPv4 (IPv6 IPv4-mapped) and IPv6. Setting this knob to true disables the IPv4 (IPv6 IPv4-mapped) part. DEFAULT: false KEY: [ bgp_daemon_interface | bmp_daemon_interface ] [GLOBAL] DESC: Defines the interface for the BGP / BMP daemon to listen on. This makes it possible to have the session happen entirely in one VRF by specifying the VRF device name here. DEFAULT: none KEY: bgp_daemon_id [GLOBAL] DESC: Defines the BGP Router-ID to the supplied value. Expected value is an IPv4 address. If this feature is not used or an invalid IP address is supplied, ie. IPv6, the bgp_daemon_ip value is used instead. If also bgp_daemon_ip is not defined or invalid, the BGP Router-ID defaults to "1.2.3.4". DEFAULT: 1.2.3.4 KEY: bgp_daemon_as [GLOBAL] DESC: Defines the BGP Local AS to the supplied value. By default, no value supplied, the session will be setup as iBGP with the Local AS received from the remote peer being copied back in the BGP OPEN reply. This allows to explicitely set a Local AS which could be different from the remote peer one hence establishing an eBGP session. DEFAULT: none KEY: [ bgp_daemon_port | bmp_daemon_port ] [GLOBAL] DESC: Makes the BGP/BMP daemon listen to a port different from the standard port. Default port for BGP is 179/tcp; default port for BMP is 1790. On systems where SO_REUSEPORT feature is available: it allows multiple daemons to bind the same local address and port in order to load-balance processing of incoming packets. This is best combined with a list of allowed IP addresses, ie. bgp_daemon_allow_file, to explicitely wire peers to collectors. At the end of this document, reference (1) to a URL to a presentation of the SO_REUSEPORT feature. To enable SO_REUSEPORT on a Linux system supporting it 'sysctl net.core.allow_reuseport=1'. DEFAULT: bgp_daemon_port: 179; bmp_daemon_port: 1790 KEY: [ bgp_daemon_rp_ebpf_prog | bmp_daemon_rp_ebpf_prog ] [GLOBAL] DESC: If SO_REUSEPORT is supported by the Operating System (read more about this feature at the config key b[mg]p_daemon_port) and eBPF support is configured when compiling (--enable-ebpf), this allows to load a custom load-balancer. To load-share, daemons have to be part of the same cluster_name and each be configured with a distinct cluster_id. An example of such eBPF program is available here: https://github.com/insa-unyte/ebpf-loadbalancer . Note: Linux kernel 4.x does not yet support eBPF locking so daemons have currently to be (re-) started with a short time gap to avoid race conditions. DEFAULT: none KEY: [ bgp_daemon_tag_map | bmp_daemon_tag_map | telemetry_daemon_tag_map ] [GLOBAL] [MAP] DESC: Full pathname to a file containing specific tags for data. Equivalent to pre_tag_map but for BGP, BMP and Streaming Telemetry threads / daemons. Take a look to the examples/pretag.map.example for syntax. Currently only 'ip' is supported as MATCH and set_tag, set_label as SET. The maximum number of entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 pmbgpd"). DEFAULT: none KEY: [ bgp_daemon_ipprec | bmp_daemon_ipprec ] [GLOBAL] DESC: Marks self-originated BGP/BMP messages with the supplied IP precedence value. DEFAULT: 0 KEY: [ bgp_daemon_max_peers | bmp_daemon_max_peers ] [GLOBAL] DESC: Sets the maximum number of neighbors the BGP/BMP daemon can peer to. Upon reaching of the limit, no more BGP/BMP sessions can be established. BGP/BMP neighbors don't need to be defined explicitely one-by-one rather an upper boundary to the number of neighbors applies. pmacctd, uacctd daemons are limited to only two BGP peers: such hardcoded limit is imposed as the only scenarios supported in conjunction with the BGP daemon are as NetFlow/sFlow probes on-board software routers and firewalls. DEFAULT: 10 KEY: [ bgp_daemon_batch_interval | bmp_daemon_batch_interval ] [GLOBAL] DESC: To prevent all BGP/BMP peers contend resources, this defines the time interval, in seconds, between any two BGP/BMP peer batches. The first peer in a batch sets the base time, that is the time from which the interval is calculated, for that batch. DEFAULT: 0 KEY: [ bgp_daemon_batch | bmp_daemon_batch ] [GLOBAL] DESC: To prevent all BGP/BMP peers to contend resources, this defines the number of BGP peers in each batch. If a BGP/BMP peer is not allowed by an ACL (ie. bgp_daemon_allow_file), room is recovered in the current batch; if a BGP/BMP peer in a batch is replenished (ie. connection drops, is reset, etc.) no new room is made in the current batch (rationale being: be a bit conservative, batch might have been set too big, let's try to limit flapping). DEFAULT: 0 KEY: [ bgp_daemon_msglog_file | bmp_daemon_msglog_file | telemetry_daemon_msglog_file ] [GLOBAL] DESC: Enables streamed logging of BGP tables/BMP events/Streaming Telemetry data. Each log entry features a time reference, peer/exporter IP address, event type and a sequence number (to order events when time reference is not granular enough). BGP UPDATE messages also contain full prefix and BGP attributes information. The list of supported filename variables follows: $peer_src_ip BGP peer IP address. $bmp_router BMP peer IP address. $telemetry_node Streaming Telemetry exporter IP address. $peer_tcp_port BGP peer TCP port. $bmp_router_port BMP peer TCP port. $telemetry_node_port Streaming Telemetry exporter port. Files can be re-opened by sending a SIGHUP to the daemon core process. The output file can be a named pipe (ie. created with mkfifo), however it has to be manually created in advance. DEFAULT: none KEY: [ bgp_daemon_msglog_avro_schema_file | bmp_daemon_msglog_avro_schema_file | bgp_table_dump_avro_schema_file | bmp_dump_avro_schema_file ] [GLOBAL] DESC: Export the schema(s) generated to encode BGP/BMP messages to the given file path. The schema can then be used by the receiving end to decode the messages. inotify-tools can be used to take event-driven actions like notify a consumer whenever the file is modified. DEFAULT: none KEY: [ bgp_daemon_msglog_kafka_avro_schema_registry | bmp_daemon_msglog_kafka_avro_schema_registry bgp_table_dump_kafka_avro_schema_registry | bmp_dump_kafka_avro_schema_registry ] [GLOBAL] DESC: The URL to a Confluent Avro Schema Registry. The value is passed to libserdes as argument for "schema.registry.url". A sample of the expected value being https://localhost. This is a pointer to the REST API https://docs.confluent.io/current/schema-registry/docs/api.html The schema name is auto generated: if the topic is static, the schema name is createad as "-" (ie. if Kafka topic is set to 'foobar' then the schema name will be "foobar-bgp_msglog", "foobar-bmp_msglog_rm", etc.). Dynamic topics are not supported. To confirm that the schema is registered, the following CL can be used: "curl -X GET https:///subjects | jq . | grep ". DEFAULT: none KEY: [ bgp_daemon_msglog_output | bmp_daemon_msglog_output ] [GLOBAL] VALUES: [ json | avro | avro_json ] DESC: Defines output format for the streamed logging of BGP messages and BMP messages and events. JSON, binary-encoded Avro and JSON-encoded Avro formats are supported. DEFAULT: json KEY: bgp_daemon_add_path_ignore [GLOBAL] VALUES: [ true | false ] DESC: By default pmacct does reply to the BGP Open of the peers enabling all shared supported capabilities. There are cases where BGP ADD-PATH may want to be ignored, ie. because in traffic flows BGP next-hop is not available (NetFlow v5, sFlow from switches, etc.) and hence the BGP next-hop guided ADD-PATH path-id selection gets not possible. DEFAULT: false KEY: bgp_aspath_radius [GLOBAL] DESC: Cuts down AS-PATHs to the specified number of ASN hops. If the same ASN is repeated multiple times (ie. as effect of prepending), each of them is regarded as one hop. By default AS-PATHs are left intact unless reaching the maximum length of the buffer (128 chars). DEFAULT: none KEY: [ bgp_stdcomm_pattern | bgp_extcomm_pattern | bgp_lrgcomm_pattern ] [GLOBAL] DESC: Filters BGP standard, extended and large communities against the supplied pattern. The underlying idea is that many communities can be attached to a prefix; some of these can be of little or no interest for the accounting task; this feature allows to select only the relevant ones. The memory plugin brings a buffer limit of 96 chars; all the others do not as buffers are handled dynamically. The filter does substring matching, ie. 12345:64 will match communities in the ranges 64-64, 640-649, 6400-6499 and 64000-64999. The '.' symbol can be used to wildcard a defined number of characters, ie. 12345:64... will match community values in the range 64000-64999 only. Multiple patterns can be supplied comma-separated. DEFAULT: none KEY: [ bgp_stdcomm_pattern_to_asn | bgp_lrgcomm_pattern_to_asn ] [GLOBAL] DESC: Filters BGP standard communities against the supplied pattern. The algorithm employed is the same as for the bgp_*comm_pattern directives: read implementation details there. The first matching community is taken and split using the ':' symbol as delimiter. The first part is mapped onto the peer AS field while the second is mapped onto the origin AS field; in case of Large Communities, the third part is unused. The aim of this directive is to deal with IP prefixes on the own address space, ie. statics or connected redistributed in BGP. As an example: BGP standard community XXXXX:YYYYY is mapped as: Peer-AS=XXXXX, Origin-AS=YYYYY. Multiple patterns can be supplied comma-separated. DEFAULT: none KEY: bgp_peer_as_skip_subas [GLOBAL] VALUES: [ true | false ] DESC: When determining the peer AS (source and destination), skip potential confederated sub-AS and report the first ASN external to the routing domain. When enabled if no external ASNs are found on the AS-PATH except the confederated sub-ASes, the first sub-AS is reported. DEFAULT: false KEY: bgp_peer_src_as_type [GLOBAL] VALUES: [ netflow | sflow | map | bgp ] DESC: Defines the method to use to map incoming traffic to a source peer ASN. "map" selects a map, reloadable at runtime, specified by the bgp_peer_src_as_map directive (refer to it for further information); "bgp" implements native BGP RIB lookups. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: netflow, sflow KEY: bgp_peer_src_as_map [GLOBAL, MAP] DESC: Full pathname to a file containing source peer AS mappings. The AS can be mapped to one or a combination of: ifIndex, source MAC address and BGP next-hop (query against the BGP RIB to look up the source IP prefix). This is sufficient to model popular tecniques for both public and private BGP peerings. Sample map in 'examples/peers.map.example'. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). To automate mapping of MAC addresses to ASNs please see https://github.com/pierky/mactopeer Written by Pier Carlo Chiodi, it leverages the popular NAPALM framework and, for the case of route-servers at IXPs, PeeringDB info. DEFAULT: none KEY: bgp_src_std_comm_type [GLOBAL] VALUES: [ bgp ] DESC: Defines the method to use to map incoming traffic to a set of standard communities. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_ext_comm_type [GLOBAL] VALUES: [ bgp ] DESC: Defines the method to use to map incoming traffic to a set of extended communities. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_lrg_comm_type [GLOBAL] VALUES: [ bgp ] DESC: Defines the method to use to map incoming traffic to a set of large communities. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_as_path_type [GLOBAL] VALUES: [ bgp ] DESC: Defines the method to use to map incoming traffic to an AS-PATH. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_local_pref_type [GLOBAL] VALUES: [ map | bgp ] DESC: Defines the method to use to map incoming traffic to a local preference. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_local_pref_map [GLOBAL, MAP] DESC: Full pathname to a file containing source local preference mappings. The LP value can be mapped to one or a combination of: ifIndex, source MAC address and BGP next-hop (query against the BGP RIB to look up the source IP prefix). Sample map in 'examples/ lpref.map.example'. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: bgp_src_med_type [GLOBAL] VALUES: [ map | bgp ] DESC: Defines the method to use to map incoming traffic to a MED value. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_roa_type [GLOBAL] VALUES: [ bgp ] DESC: Defines the method to use to map incoming traffic to a ROA status. Only native BGP RIB lookups are currently supported. BGP lookups assume traffic is symmetric, which is often not the case, affecting their accuracy. DEFAULT: none KEY: bgp_src_med_map [GLOBAL, MAP] DESC: Full pathname to a file containing source MED (Multi Exit Discriminator) mappings. The MED value can be mapped to one or a combination of: ifIndex, source MAC address and BGP next-hop (query against the BGP RIB to look up the source IP prefix). Sample map in 'examples/med.map.example'. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: [ bgp_agent_map | bmp_agent_map ] [GLOBAL, MAP] DESC: Full pathname to a file to map source 1a) IP address of NetFlow/IPFIX agents or 1b) AgentID of sFlow agents to 2a) session IP address or Router ID of BGP peers or 2b) session IP address of BMP peers. This feature is meant to provide flexibility in a number of scenarios, for example BGP peering with RRs, hub-and-spoke topologies, single-homed networks - but also BGP sessions traversing NAT. pmacctd and uacctd daemons are required to use this map with at most two "catch-all" entries: this is because these daemons do not have a NetFlow/sFlow source address to match to. Number of map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: flow_to_rd_map [GLOBAL, MAP] DESC: Full pathname to a file to map flows (typically, a) router or b) ingress router, input interfaces or c) MPLS bottom label, BGP next-hop couples) to BGP/MPLS Virtual Private Network (VPN) Route Distinguisher (RD), based upon rfc4364. See flow_to_rd.map file in the examples section for further info. Definitions in this map do override same data received from the export protocol if any (ie. NetFlow v9/IPFIX IE #90). Number of map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: bgp_follow_default [GLOBAL] DESC: Expects positive number value which instructs how many times a default route, if any, can be followed in order to successfully resolve source and destination IP prefixes. This is aimed at scenarios where neighbors peering with pmacct have a default-only or partial BGP view. At each recursion (default route follow-up) the value gets decremented; the process stops when one of these conditions is met: * both source and destination IP prefixes are resolved * there is no available default route * the default gateway is not BGP peering with pmacct * the the recusion value reaches zero As soon as an IP prefix is matched, it is not looked up anymore in case more recursions are required (ie. the closer the router is, the most specific the route is assumed to be). pmacctd, uacctd daemons are internally limited to only two BGP peers hence this feature can't properly work. DEFAULT: 0 KEY: bgp_follow_nexthop [GLOBAL] DESC: Expects one or more IP prefix(es), ie. 192.168.0.0/16, comma separated. A maximum of 32 IP prefixes is supported. It follows the BGP next-hop up (using each next-hop as BGP source-address for the next BGP RIB lookup), returning the last next-hop part of the supplied IP prefix(es) as value for the 'peer_ip_dst' primitive. bgp_agent_map is supported at each recursion. This feature is aimed at networks, for example, involving BGP confederations; underlying goal being to see the routing-domain "exit-point". The The feature is internally protected against routing loops with an hardcoded limit of 20 lookups; pmacctd, uacctd daemons are internally limited to only two BGP peers hence this feature can't properly work. DEFAULT: none KEY: bgp_follow_nexthop_external [GLOBAL] VALUES: [ true | false ] DESC: If set to true makes bgp_follow_nexthop return the next-hop from the routing table of the last node part of the supplied IP prefix(es) as value for the 'peer_ip_dst' primitive. This may help to pin-point the (set of) exit interface(s). DEFAULT: false KEY: bgp_disable_router_id_check [GLOBAL] VALUES: [ true | false ] DESC: If set to true disables the BGP Router-ID check both at BGP OPEN time and BGP lookup. This knob is useful, for example, in scenarios where v4 AFs are over a v4 transport and v6 AFs are over v6 transport but both share the same BGP Router-ID. DEFAULT: false KEY: bgp_neighbors_file [GLOBAL] DESC: Writes a list of the BGP neighbors in the established state to the specified file, one per line. This gets particularly useful for automation purposes (ie. auto-discovery of devices to poll via SNMP). DEFAULT: none KEY: [ bgp_daemon_allow_file | bmp_daemon_allow_file ] [GLOBAL, MAP] DESC: Full pathname to a file containing the list of IP addresses/prefixes (one for each line) allowed to establish a BGP/BMP session. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"); changes are applied to new sessions only. Sample map in examples/allow.lst.example . DEFAULT: none (ie. allow all) KEY: bgp_daemon_md5_file [GLOBAL] DESC: Full pathname to a file containing the BGP peers (IP address only, one for each line) and their corresponding MD5 passwords in CSV format (ie. 10.15.0.1, arealsmartpwd). BGP peers not making use of a MD5 password should not be listed. The maximum number of peers supported is 8192. For a sample map look in: 'examples/bgp_md5.lst.example'. /proc/sys/net/core/optmem_max default value allows for some 150 keys to be registered as https://patchwork.ozlabs.org/patch/138861/ documents: its value should be reviewed upwards in order to register more keys. DEFAULT: none KEY: [ bgp_table_peer_buckets | bmp_table_peer_buckets ] [GLOBAL] VALUES: [ 1-1000 ] DESC: Routing information related to BGP prefixes is kept per-peer in order to simulate a multi-RIB environment and is internally structured as an hash with conflict chains. This parameter sets the number of buckets of such hash structure; the value is directly related to the number of expected BGP peers, should never exceed such amount and: a) if only best-path is received this is best set to 1/10 of the expected peers; b) if BGP ADD-PATHs is received this is best set to 1/1 of the expected peers. The default value proved to work fine up to aprox 100 BGP peers sending best-path only, in lab. More buckets means better CPU usage but also increased memory footprint - and vice-versa. DEFAULT: 13 KEY: [ bgp_table_per_peer_buckets | bmp_table_per_peer_buckets ] [GLOBAL] VALUE: [ 1-128 ] DESC: With same background information as bgp_table_peer_buckets, this parameter sets the number of buckets over which per-peer information is distributed (hence effectively creating a second dimension on top of bgp_table_peer_buckets, useful when much BGP information per peer is received, ie. in case of BGP ADD-PATHs). Default proved to work fine if BGP sessions are passing best-path only. In case of BGP ADD-PATHs it is instead recommended to set this value to 1/3 of the configured maximum number of paths per prefix to be exported. DEFAULT: 1 KEY: [ bgp_table_attr_hash_buckets | bmp_table_attr_hash_buckets ] [GLOBAL] VALUE: [ 1-1000000 ] DESC: Sets the number of buckets of BGP attributes hashes (ie. AS-PATH, communities, etc.). Default proved to work fine with BGP sessions passing best-path only and with up to 25 BGP sessions passing ADD-PATH. DEFAULT: 65535 KEY: [ bgp_table_per_peer_hash | bmp_table_per_peer_hash ] [GLOBAL] VALUE: [ path_id ] DESC: If bgp_table_per_peer_buckets is greater than 1, this parameter allows to set the hashing to be used. By default hashing happens against the BGP ADD-PATH path_id field. Hashing over other fields or field combinations (hashing over BGP next-hop is on the radar) are planned to be supported in future. DEFAULT: path_id KEY: [ bgp_table_dump_file | bmp_dump_file | telemetry_dump_file ] [GLOBAL] DESC: Enables dump of BGP tables/BMP events/Streaming Telemetry data at regular time intervals (as defined by, for example, bgp_table_dump_refresh_time) into files. The specified file can be a named pipe (ie. created with mkfifo), however it has to be manually created in advance. Each dump event features a time reference and peer/exporter IP address along with the rest of BGP/BMP/Streaming Telemetry data. The list of supported filename variables follows: %d The day of the month as a decimal number (range 01 to 31). %H The hour as a decimal number using a 24 hour clock (range 00 to 23). %m The month as a decimal number (range 01 to 12). %M The minute as a decimal number (range 00 to 59). %s The number of seconds since Epoch, ie., since 1970-01-01 00:00:00 UTC. %S The seconds as a decimal number second (range 00 to 60). %w The day of the week as a decimal, range 0 to 6, Sunday being 0. %W The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01. %Y The year as a decimal number including the century. %z The +hhmm numeric time zone in ISO8601:1988 format (ie. -0400). $tzone The time zone in rfc3339 format (ie. -04:00 or 'Z' for +00:00). $peer_src_ip BGP peer IP address. $bmp_router BMP peer IP address. $telemetry_node Streaming Telemetry exporter IP address. $peer_tcp_port BGP peer TCP port. $bmp_router_port BMP peer TCP port. $telemetry_node_port Streaming Telemetry exporter port. DEFAULT: none KEY: [ bgp_table_dump_output | bmp_dump_output ] [GLOBAL] VALUES: [ json | avro | avro_json ] DESC: Defines output format for the dump of BGP tables and BMP events. JSON, binary-encoded Avro and JSON-encoded Avro formats are supported. DEFAULT: json KEY: [ bgp_table_dump_refresh_time | bmp_dump_refresh_time | telemetry_dump_refresh_time ] [GLOBAL] VALUES: [ 60 .. 86400 ] DESC: Time interval, in seconds, between two consecutive executions of the dump of BGP tables / BMP events / Streaming Telemetry data to files. DEFAULT: 0 KEY: [ bgp_table_dump_time_slots | bmp_dump_time_slots | telemetry_dump_time_slots ] [GLOBAL] VALUES: [ 1 .. 86400 ] DESC: Enables spreading the load deriving by BGP, BMP and Streaming Telemetry dumps over bgp_table_dump_refresh_time / bmp_dump_refresh_time time / telemetry_dump_refresh_time intervals. Refresh time interval is divided into time slots and BGP / BMP / telemetry nodes are assigned to these slots. By default this knob is set to 1, then all the content of the dumps is sent at once. The slot for each node is determined using its IP address. The number of slots must be a divisor of the refresh time. DEFAULT: 1 KEY: [ bgp_table_dump_latest_file | bmp_dump_latest_file | telemetry_dump_latest_file ] [GLOBAL] DESC: Defines the full pathname to pointer(s) to latest file(s). Dynamic names are supported through the use of variables, which are computed at the moment when data is purged to the backend: refer to bgp_table_dump_file (and companion directives) for a full listing of supported variables; time-based variables are not allowed. Update of the latest pointer is done evaluating files modification time. See also print_latest_file for examples. DEFAULT: none KEY: bgp_daemon_lg [GLOBAL] VALUES: [ true | false ] DESC: Enables the BGP Looking Glass server allowing to perform queries, ie. lookup IP addresses/prefixes or get the list of BGP peers, against available BGP RIBs. The server is asyncronous and uses ZeroMQ as transport layer to serve incoming queries. Sample C/Python LG clients are available in 'examples/lg'. Sample LG server config is available in QUICKSTART . Request/Reply Looking Glass formats are documented in 'docs/LOOKING_GLASS_FORMAT'. DEFAULT: false KEY: bgp_daemon_lg_ip [GLOBAL] DESC: Binds the BGP Looking Glass server to a specific interface. Expects as value an IP address. DEFAULT: 0.0.0.0 KEY: bgp_daemon_lg_port [GLOBAL] DESC: Makes the BGP Looking Glass server listen to a specific port. DEFAULT: 17900 KEY: bgp_daemon_lg_user [GLOBAL] DESC: Enables plain username/password authentication in the BGP Looking Glass server. This directive sets the expected username. By default authentication is disabled. DEFAULT: none KEY: bgp_daemon_lg_passwd [GLOBAL] DESC: Enables plain username/password authentication in the BGP Looking Glass server. This directive sets the expected password. By default authentication is disabled. DEFAULT: none KEY: bgp_daemon_lg_threads [GLOBAL] DESC: Defines the amount of threads of the BGP Looking Glass to serve incoming queries. DEFAULT: 8 KEY: bgp_daemon_xconnect_map [MAP, GLOBAL] DESC: Enables BGP proxying. Full pathname to a file to cross-connect BGP peers (ie. edge routers part of an observed network topology) to BGP collectors (ie. nfacctd daemons correlating flow and BGP data). The mapping works only against the IP address layer and not the BGP Router ID, only 1:1 relationships are formed (ie. this is about cross-connecting, not replication) and only one session per BGP peer is supported (ie. multiple BGP agents are running on the same IP address or NAT traversal scenarios are not supported [yet]). TCP-MD5 is supported on inbound sessions to the proxy (via bgp_daemon_md5_file) but not on outbound ones. A sample map is provided in 'examples/bgp_xconnects.map.example'. Number of map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: bmp_daemon_parse_proxy_header VALUES: [ true | false ] DESC: Defines whether to parse the first packet of a connection looking for a Proxy Protocol header containing client information (IP addresses and TCP ports). The source IP Address and TCP port of the header replaces the peer IP address and peer TCP port obtained from the socket. The following is a simple HAProxy configuration example where an HAProxy listens on TCP port 5001 for BMP packets and forwards them to a PMBMPD daemon listening on TCP port 5000. A binary version 2 Proxy Protocol header is prepended to the first packet of the TCP connection. frontend bmp_ha_proxy bind :5001 mode tcp default_backend bmpnodes backend bmpnodes mode tcp server bmp-dev :5000 send-proxy-v2 DEFAULT: false KEY: [ bgp_table_dump_workers | bmp_dump_workers | telemetry_dump_workers ] DESC: Sets the amount of parallel worker threads to set up for dump events. By default 1 (no parallelization), it may be set to a fraction of the available CPU threads. The unit of parallelization is the exporter (BGP, BMP or telemetry exporter), ie. in a scenario where there are 4 workers and 4 exporters each worker is assigned one exporter data to dump. DEFAULT: 1 KEY: rpki_roas_file [MAP, GLOBAL] DESC: Full pathname to a file containing RPKI ROA data. Data encoding is JSON and format supported are RIPE Validator OpenBSD Validator ones. ROA data can be obtained for example from https://rpki.gin.ntt.net/api/export.json . An example of the format: { "roas" : [ { "asn" : "AS2914", "prefix" : "128.121.0.0/16", "maxLength" : 16, "ta" : "ARIN" }, { "asn" : "AS2914", "prefix" : "128.121.0.0/19", "maxLength" : 24, "ta" : "ARIN" } ] } Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: rpki_rtr_cache [GLOBAL] DESC: Defines the remote IP address and port of a RPKI RTR cache to connect to. If IPv4, the value is expected as 'address:port'. If IPv6, it is expected as '[address]:port'. DEFAULT: none KEY: rpki_rtr_cache_version [GLOBAL] VALUES: [ 0 | 1 ] DESC: Defines the RPKI RTR protocol version to use. Version 0 is documented in rfc6810; Version 1 is documented in rfc8210. DEFAULT: 0 KEY: rpki_rtr_cache_pipe_size [GLOBAL] DESC: Defines the size of the kernel socket used for RPKI RTR datagrams (see also bgp_daemon_pipe_size for more info). DEFAULT: Operating System default KEY: rpki_rtr_cache_ipprec [GLOBAL] DESC: Marks self-originated RPKI RTR messages with the supplied IP precedence value. DEFAULT: 0 KEY: isis_daemon [GLOBAL] VALUES: [ true | false ] DESC: Enables the skinny IS-IS daemon thread. It implements P2P Hellos, CSNP and PSNP - and does not send any LSP information out. It currently supports a single L2 P2P neighborship. Testing has been done over a GRE tunnel. DEFAULT: false KEY: isis_daemon_ip [GLOBAL] DESC: Sets the sub-TLV of the Extended IS Reachability TLV that contains an IPv4 address for the local end of a link. No default value is set and a non-zero value is mandatory. It should be set to the IPv4 address configured on the interface pointed by isis_daemon_iface. DEFAULT: none KEY: isis_daemon_net [GLOBAL] DESC: Defines the Network entity title (NET) of the IS-IS daemon. In turn a NET defines the area addresses for the IS-IS area and the system ID of the router. No default value is set and a non-zero value is mandatory. Extensive IS-IS and ISO literature cover the topic, example of the NET value format can be found as part of the "Quickstart guide to setup the IS-IS daemon" in the QUICKSTART document. DEFAULT: none KEY: isis_daemon_iface [GLOBAL] DESC: Defines the network interface (ie. gre1) where to bind the IS-IS daemon. No default value is set and a non-zero value is mandatory. DEFAULT: none KEY: isis_daemon_mtu [GLOBAL] DESC: Defines the available MTU for the IS-IS daemon. P2P HELLOs will be padded to such length. When the daemon is configured to set a neighborship with a Cisco router running IOS, this value should match the value of the "clns mtu" IOS directive. DEFAUT: 1476 KEY: isis_daemon_msglog [GLOBAL] VALUES: [ true | false ] DESC: Enables IS-IS messages logging: as this can get easily verbose, it is intended for debug and troubleshooting purposes only. DEFAULT: false KEY: [ geoip_ipv4_file | geoip_ipv6_file ] [GLOBAL] DESC: If pmacct is compiled with --enable-geoip, this defines full pathname to the Maxmind GeoIP Country v1 ( http://dev.maxmind.com/geoip/legacy/install/country/ ) IPv4/IPv6 databases to use. pmacct, leveraging the Maxmind API, will detect if the file is updated and reload it. The use of --enable-geoip is mutually exclusive with --enable-geoipv2. DEFAULT: none KEY: geoipv2_file [GLOBAL] DESC: If pmacct is compiled with --enable-geoipv2, this defines full pathname to a Maxmind GeoIP database v2 (libmaxminddb, ie. https://dev.maxmind.com/geoip/geoip2/geolite2/ ). It does allow to resolve GeoIP-related primitives like countries, pocodes and coordinates. Only the binary database format is supported (ie. it is not possible to load distinct CSVs for IPv4 and IPv6 addresses). --enable-geoip is mutually exclusive with --enable-geoipv2. Files can be reloaded at runtime by sending the daemon a SIGUSR signal (ie. "killall -USR2 nfacctd"). KEY: uacctd_group [GLOBAL, UACCTD_ONLY] DESC: Sets the Linux Netlink NFLOG multicast group to be joined. DEFAULT: 0 KEY: uacctd_nl_size [GLOBAL, UACCTD_ONLY] DESC: Sets NFLOG Netlink internal buffer size (specified in bytes). It is 128KB by default, but to safely record bursts of high-speed traffic, it could be further increased. For high loads, values as large as 2MB are recommended. When modifying this value, it is also recommended to reflect the change to the 'snaplen' option. DEFAULT: 131072 KEY: uacctd_threshold [GLOBAL, UACCTD_ONLY] DESC: Sets the number of packets to queue inside the kernel before sending them to userspace. Higher values result in less overhead per packet but increase delay until the packets reach userspace. DEFAULT: 1 KEY: tunnel_0 [GLOBAL, NO_NFACCTD, NO_SFACCTD] DESC: Defines tunnel inspection in pmacctd and uacctd, disabled by default (note: this feature is currently unrelated to tunnel_* primitives). The daemon will then account on tunnelled data rather than on the envelope. The implementation approach is stateless, ie. control messages are not handled. Up to 4 tunnel layers are supported (ie. , ; , ; ...). Up to 8 tunnel stacks will be supported (ie. configuration directives tunnel_0 .. tunnel_8), to be used in a strictly sequential order. First stack matched at the first layering, wins. Below tunnel protocols supported and related options: GTP, GPRS tunnelling protocol. Expects as option the UDP port identifying the protocol. tunnel_0: gtp, DEFAULT: none KEY: tee_receivers [MAP] DESC: Defines full pathname to a list of remote IP addresses and ports to which NetFlow/sFlow datagrams are to be replicated to. Examples are available in "examples/tee_receivers.lst. example" file. Number of map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). DEFAULT: none KEY: tee_pipe_size DESC: Defines the size of the kernel socket to write replicated traffic data. The socket is highlighted below with "XXXX": XXXX [kernel] ----> [core process] ----> [tee plugin] ----> [kernel] ----> [network] [_____________pmacct____________] On Linux systems, if this configuration directive is not specified default socket size awarded is defined in /proc/sys/net/core/[rw]mem_default ; the maximum configurable socket size is defined in /proc/sys/net/core/[rw]mem_max instead. Still on Linux, the "drops" field of /proc/net/udp or /proc/net/udp6 can be checked to ensure its value is not increasing. DEFAULT: Operating System default KEY: tee_source_ip DESC: Defines the local IP address from which NetFlow/sFlow datagrams are to be replicate from. Only a numerical IPv4/IPv6 address is expected. The supplied IP address is required to be already configured on one of the interfaces. Value is ignored when transparent replication is enabled. DEFAULT: IP address is selected by the Operating System KEY: tee_transparent VALUES: [ true | false ] DESC: Enables transparent replication mode. It essentially spoofs the source IP address to the original sender of the datagram. It requires super-user permissions. DEFAULT: false KEY: tee_max_receiver_pools DESC: Tee receivers list is organized in pools (for present and future features that require grouping) of receivers. This directive defines the amount of pools to be allocated and cannot be changed at runtime. DEFAULT: 128 KEY: tee_max_receivers DESC: Tee receivers list is organized in pools (for present and future features that require grouping) of receivers. This directive defines the amount of receivers per pool to be allocated and cannot be changed at runtime. DEFAULT: 32 KEY: tee_kafka_config_file DESC: Full pathname to a file containing directives to configure librdkafka when emitting replicated datagrams to a Kafka broker. See kafka_config_file for more info. Other aspects like the Kafka broker IP address / port and topic name are to be configured via an entry in the tee_receivers map (see examples/tee_receivers.lst) using the kafka_broker and kafka_topic keys. DEFAULT: none KEY: thread_stack DESC: Defines the stack size for threads screated by the daemon. The value is expected in bytes. A value of 0, default, leaves the stack size to the system default or pmacct minimum (8192000) if system default is too low. Some systems may throw an error if the defined size is not a multiple of the system page size. DEFAULT: 0 KEY: telemetry_daemon [GLOBAL] VALUES: [ true | false ] DESC: Enables the Streaming Telemetry thread in all daemons except pmtelemetryd (which does collect telemetry as part of its core functionalities). Quoting Cisco IOS-XR Telemetry Configuration Guide at the time of this writing: "Streaming telemetry lets users direct data to a configured receiver. This data can be used for analysis and troubleshooting purposes to maintain the health of the network. This is achieved by leveraging the capabilities of machine-to-machine communication. The data is used by development and operations (DevOps) personnel who plan to optimize networks by collecting analytics of the network in real-time, locate where problems occur, and investigate issues in a collaborative manner.". DEFAULT: false KEY: telemetry_daemon_port_tcp [GLOBAL] DESC: Makes the Streaming Telemetry daemon, pmtelemetryd, or the Streaming Telemetry thread listen on the specified TCP port. (see telemetry/README.telemetry for gRPC support). If SO_REUSEPORT is supported by the Operating System, you can read more about it at the config key telemetry_daemon_port_udp. DEFAULT: none KEY: telemetry_daemon_port_udp [GLOBAL] DESC: Makes the Streaming Telemetry daemon, pmtelemetryd, or the Streaming Telemetry thread listen on the specified UDP port. On systems where SO_REUSEPORT feature is available: it allows multiple daemons to bind the same local address and port in order to load- balance processing of incoming packets. This is best combined with a list of allowed IP addresses, ie. bgp_daemon_allow_file, to explicitely wire peers to collectors. At the end of this document, reference (1) to a URL to a presentation of the SO_REUSEPORT feature. To enable SO_REUSEPORT on a Linux system supporting it 'sysctl net.core.allow_reuseport=1'. DEFAULT: none KEY: telemetry_daemon_ip [GLOBAL] DESC: Binds the Streaming Telemetry daemon to a specific interface. Expects as value an IPv4/ IPv6 address. DEFAULT: 0.0.0.0 KEY: telemetry_daemon_interface [GLOBAL] DESC: Defines the interface for the Streaming Telemetry daemon to listen on. This makes it possible to have the session happen entirely in one VRF by specifying the VRF device name here. DEFAULT: none KEY: telemetry_daemon_ipv6_only [GLOBAL] VALUES: [ true | false ] DESC: When listening on all interfaces (default setting for telemetry_daemon_ip) and IPv6 is enabled, it is possible to connect with both IPv4 (IPv6 IPv4-mapped) and IPv6. Setting this knob to true disables the IPv4 (IPv6 IPv4-mapped) part. DEFAULT: false KEY: telemetry_daemon_rp_ebpf_prog [GLOBAL] DESC: If SO_REUSEPORT is supported by the Operating System (read more about this feature at the config key telemetry_daemon_port_udp) and eBPF support is configured when compiling (--enable-ebpf), this allows to load a custom load-balancer. To load-share, daemons have to be part of the same cluster_name and each be configured with a distinct cluster_id. An example of such eBPF program is available here: https://github.com/insa-unyte/ebpf-loadbalancer Note: Linux kernel 4.x does not yet support eBPF locking so daemons have currently to be (re-) started with a short time gap to avoid race conditions. DEFAULT: none KEY: telemetry_daemon_decoder [GLOBAL] VALUES: [ json | gpb | cisco_v0 | cisco_v1 ] DESC: Sets the Streaming Telemetry data decoder to the specified type (over TCP or UDP transports. Cisco 32-bits OS versions tend to prepend a 12 bytes proprietary header to GPB compact / GPB KV data and this can be read with the 'cisco_v1' decoder; the 'cisco_v0' is mostly obsoleted at this point. GPB de-marshaling is not supported and will produce an output JSON object with a base64'd encoding of the original GPB (see telemetry/README.telemetry for gRPC support and GPB de-marshalling). DEFAULT: none KEY: telemetry_daemon_max_peers [GLOBAL] DESC: Sets the maximum number of exporters the Streaming Telemetry daemon can receive data from. Upon reaching of such limit, no more exporters can send data to the daemon. DEFAULT: 100 KEY: telemetry_daemon_peer_timeout [GLOBAL] DESC: Sets the timeout time, in seconds, to determine when a Streaming Telemetry session is to be expired. Applies to UDP and ZeroMQ sessions. DEFAULT: 300 KEY: telemetry_daemon_allow_file [GLOBAL, MAP] DESC: Full pathname to a file containing the list of IPv4/IPv6 addresses/prefixes (one for each line) allowed to send packets to the daemon. The allow file is intended to be small for connectionless sessons; for longer ACLs, firewall rules should be preferred instead. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). Sample map in examples/allow.lst.example . DEFAULT: none (ie. allow all) KEY: telemetry_daemon_pipe_size [GLOBAL] DESC: Defines the size of the kernel socket used for Streaming Telemetry datagrams (see also bgp_daemon_pipe_size for more info). DEFAULT: Operating System default KEY: telemetry_daemon_ipprec [GLOBAL] DESC: Marks self-originated Streaming Telemetry messages with the supplied IP precedence value. Applies to TCP sessions only. DEFAULT: 0 KEY: telemetry_daemon_zmq_address [GLOBAL] DESC: Defines the ZeroMQ queue address (host and port) to connect to for consuming JSON-encoded Streaming Telemetry data from. An example of the expected value is "127.0.0.1:50000". DEFAULT: none KEY: telemetry_daemon_kafka_broker_host [GLOBAL] DESC: Defines one or multiple, comma-separated, Kafka brokers to consume JSON-encoded Streaming Telemetry data from. See kafka_broker_host for more info. DEFAULT: none KEY: telemetry_daemon_kafka_broker_port [GLOBAL] DESC: Defines the Kafka broker port to consume JSON-encoded Streaming Telemetry data from. See kafka_broker_host for more info. DEFAULT: 9092 KEY: telemetry_daemon_kafka_config_file [GLOBAL] DESC: Full pathname to a file containing directives to configure librdkafka to consume JSON-encoded Streaming Telemetry data from. See kafka_config_file for more info. DEFAULT: none KEY: telemetry_daemon_kafka_topic [GLOBAL] DESC: Name of the Kafka topic to consume JSON-encoded Streaming Telemetry data from. No variables are supported for dynamic naming of the topic. See kafka_topic for more info. DEFAULT: none KEY: telemetry_daemon_udp_notif_ip [GLOBAL] DESC: Defines the IP address to listen to for UDP-Notif, a proposed standard at IETF for UDP-based Transport for Configured Subscriptions. Expects as value an IPv4/ IPv6 address. UDP-Notif collection relies on the Unyte UDP-Notif C collector library developed by INSA Lyon and publicly available on GitHub at this URL: https://github.com/insa-unyte/udp-notif-c-collector DEFAULT: none KEY: telemetry_daemon_udp_notif_port [GLOBAL] DESC: Defines the UDP port to bind to for UDP-Notif. DEFAULT: none KEY: telemetry_daemon_udp_notif_interface [GLOBAL] DESC: Defines the interface for the Streaming Telemetry daemon to listen on for UDP-Notif. This makes it possible to have the session happen entirely in one VRF by specifying the VRF device name here. DEFAULT: none KEY: telemetry_daemon_udp_notif_ipv6_only [GLOBAL] VALUES: [ true | false ] DESC: When listening on all interfaces (default setting for telemetry_daemon_udp_notif_ip) and IPv6 is enabled, it is possible to connect with both IPv4 (IPv6 IPv4-mapped) and IPv6. Setting this knob to true disables the IPv4 (IPv6 IPv4-mapped) part. DEFAULT: false KEY: telemetry_daemon_udp_notif_nmsgs [GLOBAL] DESC: Defines the buffer of messages to receive at once for UDP-Notif. The default, 1, is excellent for lab environments, PoC scenarios and no-latency processing. The Unyte UDP-Notif C collector recommended default is 10: for production scenarios this number may need to be raised for increased processing efficiency. DEFAULT: 1 KEY: telemetry_daemon_msglog_output [GLOBAL] VALUES: [ json ] DESC: Defines output format for Streaming Telemetry data (pmtelemetryd). Only JSON format is currently supported and requires compiling against Jansson library (--enable-jansson when configuring for compiling). DEFAULT: json KEY: telemetry_dump_output [GLOBAL] VALUES: [ json ] DESC: Defines output format for the dump of Streaming Telemetry data (pmtelemetryd). Only JSON format is currently supported and requires compiling against Jansson library (--enable-jansson when configuring for compiling). DEFAULT: json KEY: classifier_num_roots [GLOBAL] DESC: Defines the number of buckets of the nDPI memory structure on which to hash flows. The more the buckets, the more memory will be allocated at startup and the smaller - and hence more performing - each memory structure will be. DEFAULT: 512 KEY: classifier_max_flows [GLOBAL] DESC: Maximum number of concurrent flows allowed in the nDPI memory structure. DEFAULT: 200000000 KEY: classifier_proto_guess [GLOBAL] VALUES: [ true | false ] DESC: If DPI classification is unsuccessful, and before giving up, try guessing the protocol given collected flow characteristics, ie. IP protocol, port numbers, etc. DEFAULT: false KEY: classifier_idle_scan_period [GLOBAL] DESC: Defines the time interval, in seconds, at which going through the memory structure to find for idle flows to expire. DEFAULT: 10 KEY: classifier_idle_scan_budget [GLOBAL] DESC: Defines the amount of idle flows to expire per each classifier_idle_scan_period. This feature is to prevent too many flows to expire can disrupt the regular classification activity. DEFAULT: 1024 KEY: classifier_giveup_proto_tcp [GLOBAL] DESC: Defines the maximum amount of packets to try to classify a TCP flow. After such amount of trials, the flow will be marked as given up and no classification attempts will be made anymore, until it expires. DEFAULT: 10 KEY: classifier_giveup_proto_udp [GLOBAL] DESC: Same as classifier_giveup_proto_tcp but for UDP flows. DEFAULT: 8 KEY: classifier_giveup_proto_other [GLOBAL] DESC: Same as classifier_giveup_proto_tcp but for flows which IP protocol is different than TCP and UDP. DEFAULT: 8 KEY: redis_host DESC: Defines the Redis server IP address and port to connect to, ie. "127.0.0.1:6379". The port needs to be specified. This directive, in conjunction with the cluster_* ones, enables forming a cluster with the other daemons pointed to the same . It needs pmacct to be compiled with --enable-redis. DEFAULT: none KEY: redis_db DESC: Defines the Redis database to select. The database is a positive integer and, at time of this writing, allowed numbers are in the range 0 to 15. DEFAULT: 0 KEY: cluster_name DESC: Defines the name of the cluster and is expected to be a string, ie. "test", "pmacct", etc.; this is relevant in two contexts: 1) it enables forming a cluster with other daemons pointed to the same ; 2) it makes daemons binding to the same TCP/UDP port to be part of the same load-sharing SO_REUSEPORT group (see *_rp_ebpf_prog config keys for more info). DEFAULT: none KEY: cluster_id DESC: Defines the ID of the node inside the cluster and is expected to be a positive integer. Each daemon must be assigned a unique ID and responsibility for respecting this property is left to the user. DEFAULT: 0 KEY: tmp_asa_bi_flow VALUES: [ true | false ] DESC: Bi-flows use two sets of counters to report bytes and packets, in initiator and responder directions. This makes a total of four counters (2 for packets, 2 for bytes) whereas pmacct does support two only (1 for packets, 1 for bytes). This hack (ab)uses the packets field in order to store the extra bytes counter, more specifically the bytes counter is used for the Initiator bytes and the packets counter is used for the Responder bytes. The patch specifically targets NetFlow v9/IPFIX field types #231 and #232 and has been tested against Cisco ASA exports. DEFAULT: false KEY: tmp_bgp_lookup_compare_ports VALUES: [ true | false ] DESC: When looking up BGP RIBs in traffic accounting daemons (ie. nfacctd, sfacctd, etc.), if set to true, try to compare both the socket IP address and the TCP port of a BGP session (that is, not only the socket IP address as when this knob is set to false). This is always the case when a bgp_agent_map is defined and the 'bgp_port' keyword is specified; when 'bgp_port' is not specified (or a bgp_agent_map is not defined), this knob essentially forces the comparison against only the BGP Router-ID. This may be wanted in NAT traversal scenarios and/or BGP xconnects (bgp_daemon_xconnect_map). DEFAULT: false KEY: tmp_bgp_daemon_route_refresh VALUES: [ true | false ] DESC: If set to true, a Route Refresh capability is presented at BGP OPEN message to the peers (if, indeed, it was originally set by the peer). When receiving a route refresh message, that is simply ignored. This does not intend to be a feature but a hack to counter certain vendor bugs. DEFAULT: false KEY: tmp_bgp_daemon_origin_type_int VALUES: [ true | false ] DESC: If set to true, the BGP attribute "origin" is encoded on output as an integer value; this was the legacy behaviour now replaced by a string encoding since version 1.7.3. This may help existing deployments <= 1.7.3 to upgrade smoothly. DEFAULT: false KEY: tmp_telemetry_daemon_udp_notif_legacy VALUES: [ true | false ] DESC: If set to true, make use of the legacy UDP publish channel protocol as described in draft-ietf-netconf-udp-pub-channel-05. DEFAULT: false KEY: tmp_telemetry_decode_cisco_v1_json_string VALUES: [ true | false ] DESC: If set to true, the "telemetry_data" received from the router will not be parsed by the JSON library and will be passed as a string for post-processing. Only relevant when telemetry_daemon_decoder is set to 'cisco_v1' and meant as a short-term remedy for 64-bit integer values that cannot be properly parsed by Jansson JSON library. DEFAULT: false REFERENCES: (1) https://domsch.com/linux/lpc2010/Scaling_techniques_for_servers_with_high_connection%20rates.pdf pmacct-1.7.8/m4/0000755000175000017500000000000014354105411012322 5ustar paolopaolopmacct-1.7.8/m4/ltsugar.m40000644000175000017500000001044014354105411014244 0ustar paolopaolo# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) pmacct-1.7.8/m4/libtool.m40000644000175000017500000112677114354105411014247 0ustar paolopaolo# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 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 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 . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*|11.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cr} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* 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@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # 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). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS pmacct-1.7.8/m4/ltversion.m40000644000175000017500000000127314354105411014614 0ustar paolopaolo# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) pmacct-1.7.8/m4/ltoptions.m40000644000175000017500000003426214354105411014626 0ustar paolopaolo# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) pmacct-1.7.8/m4/lt~obsolete.m40000644000175000017500000001377414354105411015152 0ustar paolopaolo# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) pmacct-1.7.8/m4/ac_linearize_path.m40000644000175000017500000000044014354105275016233 0ustar paolopaolo# # Author: Paolo Lucente # Last Modified: 2006-03-07 # Synopsis: AC_LINEARIZE_PATH(PATH) # Reference: # AC_DEFUN([AC_LINEARIZE_PATH], [ absdir=`cd $1 2>/dev/null && pwd` if test x$absdir != x ; then [$2] fi ]) pmacct-1.7.8/m4/ax_lib_mysql.m40000644000175000017500000000522514354105275015263 0ustar paolopaolo# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_lib_mysql.html # =========================================================================== # # SYNOPSIS # # AX_LIB_MYSQL([MINIMUM-VERSION]) # # DESCRIPTION # # This macro provides tests of availability of MySQL client library of # particular version or newer. # # AX_LIB_MYSQL macro takes only one argument which is optional. If there # is no required version passed, then macro does not run version test. # # This is a short and adapted version of the original macro. # # LICENSE # # Copyright (c) 2008 Mateusz Loskot # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 13 AC_DEFUN([AX_LIB_MYSQL], [ if test "$MYSQL_CONFIG" != "no"; then MYSQL_VERSION=`$MYSQL_CONFIG --version` found_mysql="yes" else found_mysql="no" fi dnl dnl Check if required version of MySQL is available dnl mysql_version_req=ifelse([$1], [], [], [$1]) if test "$found_mysql" = "yes" -a -n "$mysql_version_req"; then AC_MSG_CHECKING([if MySQL version is >= $mysql_version_req]) dnl Decompose required version string of MySQL dnl and calculate its number representation mysql_version_req_major=`expr $mysql_version_req : '\([[0-9]]*\)'` mysql_version_req_minor=`expr $mysql_version_req : '[[0-9]]*\.\([[0-9]]*\)'` mysql_version_req_micro=`expr $mysql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test "x$mysql_version_req_micro" = "x"; then mysql_version_req_micro="0" fi mysql_version_req_number=`expr $mysql_version_req_major \* 1000000 \ \+ $mysql_version_req_minor \* 1000 \ \+ $mysql_version_req_micro` dnl Decompose version string of installed MySQL dnl and calculate its number representation mysql_version_major=`expr $MYSQL_VERSION : '\([[0-9]]*\)'` mysql_version_minor=`expr $MYSQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'` mysql_version_micro=`expr $MYSQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test "x$mysql_version_micro" = "x"; then mysql_version_micro="0" fi mysql_version_number=`expr $mysql_version_major \* 1000000 \ \+ $mysql_version_minor \* 1000 \ \+ $mysql_version_micro` mysql_version_check=`expr $mysql_version_number \>\= $mysql_version_req_number` if test "$mysql_version_check" = "1"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi AC_SUBST([MYSQL_VERSION]) ]) pmacct-1.7.8/AUTHORS0000644000175000017500000000307214354105275013064 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI : IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2022 by Paolo Lucente Founder: Paolo Lucente Package maintainers: Ryan Steinmetz (FreeBSD) Bernd Zeimetz (Debian) MOTU Developers (Ubuntu) Martin Hauke (OpenSUSE) netmon (Gentoo) KP Kirchdoerfer (LEAF Bering-uClibc) Slava Dubrovskyi (ALTLinux) A (non-exhaustive) list of code and documentation contributors: https://github.com/pmacct/pmacct/graphs/contributors Thanks to the following people for their strong support along the time: Arash Afrakhteh Martin Anderberg Sven Anderson Matthias Arnold Raphael Barazzutti David Barroso Joerg Behrens Vincent Bernat Robert Blechinger Stefano Birmani Juan Camilo Cardona Pier Carlo Chiodi Codethink.co.uk Salvatore Cuzzilla Arnaud De-Bermingham Francois Deppierraz Pierre Francois Rich Gade Aaron Glenn Alan Gous Thomas Graf Gianluca Guida Elisa Jasinska Wim Kerkhoff Tim LaBerge Paul Mabey Arman Maghbouleh Jared Mauch Peter Nixon Claudio Ortega Ivan Pepelnjak Vaibhav Phatarpekar Peter Pothier Karl O. Pinc Vasiliy Ponomarev Martin Pot Pether Pothier A.O. Prokofiev Edwin Punt Anik Rahman Job Snijders Gabriel Snook Rene Stoutjesdijk Marc Sune Thomas Telkamp Matthieu Texier Stig Thormodsrud Marco Tollini Luca Tosolini Brent Van Dussen Markus Weber Chris Wilson pmacct-1.7.8/ChangeLog0000644000175000017500000112447614354105275013603 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI : IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2022 by Paolo Lucente The keys used are: !: fixed/modified feature, -: deleted feature, +: new feature 1.7.8 -- 31-12-2022 + Introduced support for eBPF for all daemons: if SO_REUSEPORT is supported by the OS and eBPF support is compiled in, this allows to load a custom load-balancer. To load-share, daemons have to be part of the same cluster_name and each be configured with a distinct cluster_id. + Introduced support for listening on VRF interfaces on Linux for all daemons. The feature can be enabled via nfacctd_interface, bgp_daemon_interface and equivalent knobs. Many thanks to Marcel Menzel ( @WRMSRwasTaken ) for this contribution. + pre_tag_map: introduced limited tagging / labelling support for BGP (pmbgpd), BMP (pmbmpd), Streaming Telemetry (pmtelemetryd) daemons. ip, set_tag, set_label keys being currently supported. + pre_tag_map: defined a new pre_tag_label_encode_as_map config knob to encode the output 'label' value as a map for JSON and Apache Avro encodings, ie. in JSON "label": { "key1": "value1", "key2": "value2" }. For keys and values to be correctly mapped, the '%' delimiter is used when composing a pre_tag_map, ie. "set_label=key1%value1,key2%value2 ip=0.0.0.0/0". Thanks to Salvatore Cuzzilla ( @scuzzilla ) for this contribution. + pre_tag_map: introduced support for IP prefixes for src_net and dst_net keys for indexed maps (maps_index set to true). Indexing being an hash map, this feature currently tests data against all defined IP prefix lenghts in the map for a match (first defined matching prefix wins). + pre_tag_map: introduced two new 'is_nsel', 'is_nel' keys to check for the presence of firewallEvent field (233) and natEvent field (230) in NetFlow/IPFIX respectively in order to infer whether data is NSEL / NEL. If set to 'true' this does match NSEL / NEL data, if set to 'false' it does match non NSEL / NEL data respectively. + Introduced a new mpls_label_stack primitive, encoded as a string and includes a comma-separated list of integers (label values). Thanks to Salvatore Cuzzilla ( @scuzzilla ) for this contribution. + Introduced a new fw_event primitive, to support NetFlow v9/ IPFIX firewallEvent 233 Information Element. + Introduced a new tunnel_tcp_flags primitive for pmacctd and sfacctd to record TCP flags for the inner layer of a tunneled technology (ie. VXLAN). Also tunnel_dst_port decoding was fixed for sfacctd. + Introduced support for in/out VLAN support for sfacctd. To be savy, 'in_vlan' and 'vlan' were muxed onto the same primitive depending on the daemon being used. Thanks to Jim Westfall ( @jwestfall69 ) for this contribution. + Introduced a new mpls_label_stack_encode_as_array config knob to encode the MPLS label stack as an array for JSON and Apache Avro encodings, ie. in JSON "mpls_label_stack": [ "0-label0", "1-label1", "2-label2", "3-label3", "4-label4", "5-label5" ] and in Avro "name": "mpls_label_stack", "type": { "type": "array", "items": { "type": "string" } }. Thanks to Salvatore Cuzzilla ( @scuzzilla ) for this contribution. + Introduced a new tcpflags_encode_as_array config knob to encode TCP flags as an array for JSON and Apache Avro, ie. in JSON "tcp_flags": [ "URG", "ACK", "PSH", "RST", "SYN", "FIN" ] and in Avro "name": "tcp_flags", "type": { "type": "array", "items": { "type": "string" } }. Thanks to Salvatore Cuzzilla ( @scuzzilla ) for this contribution. + Introduced a new fwd_status_encode_as_string config knob to encode the 'fwd_status' primitive in human-readable format like described by RFC-7270 Section 4.12 when JSON or Avro formats are selected for output. Thanks to Salvatore Cuzzilla ( @scuzzilla ) for this contribution. + Introduced a new protos_file to define a list of (known/ interesting/meaningful) IP protocols. Both protocol names, ie. "tcp", and protocol numbers, ie. 1 (for icmp), are accepted. IANA reserved protocol value 255 is used to bucket as 'others' those IP protocols not matching the ones defined in the list. + Introduced a new tos_file to define a list of (meaningful) IP ToS values; if tos_encode_as_dscp is set to true then DSCP values are expected as part of the file. The directive uses value 255 to bucket as 'others' those ToS/DSCP values not matching the ones defined in the list. + A new tos_encode_as_dscp config knob makes pmacct to honour only the 6 bits used by DSCP and report only on those. + BGP, BMP, Streaming Telemetry daemons: introduced a new dump_time_slots config knob to spread the load deriving by dumps over the configured refresh time interval. The interval is divided into time slots and nodes are assigned to such slots. The slot for each node is determined using its IP address. Thanks to Raphael Barazzutti ( @rbarazzutti ) for this contribution. + BGP, BMP daemons: End-of-RIB messages are now being exposed in the output feed in order to facilitate tracking their arrival (or not!). + pmtelemetryd: aligned daemon to the latest Unyte UDP-Notif API (0.6.1) and related standardization draft-ietf-netconf-udp-notif + RPKI daemon: added case for input "asn" value being integer (ie. "asn" : 2914) on top of the string case (ie. "asn" : "AS2914"). + Kafka, amqp plugins: introduced a new writer_id_string config knob to allow to customize the the "writer_id" field value. A few variables are supported along with static text definitions. + Added a new aggregate_unknown_etype config knob to account also frames with EtherTypes for which there is no decoding support and allow to aggregate them by the available Ethernet L2 fields (ie. 'src_mac', 'dst_mac', 'vlan', 'cos', 'etype'). Thanks to @singularsyntax for this contribution. + Added a new bgp_daemon_add_path_ignore config knob to ignore (do not advertise back) the ADD-PATH capability advertised by remote BGP peers. + nfacctd, sfacctd: extended the possibility to run daemons from a user with non root privileges to these daemons. + nfacctd: if Information Element 90 (MPLS VPN RD) is present in NetFlow v9/IPFIX, make it available for BGP/BMP correlation. + pmacctd, sfacctd: introduced basic support for QinQ, 802.1AD. + [print|kafka|amqp]_preprocess: added suppport for 'maxp', 'maxb' and 'maxf' keys when preprocessing aggregates of non- SQL plugins. Thanks to Andrew R. Lake ( @arlake228 ) for this contribution. + nDPI: newer versions of the library (ie. >= 4.0) bring changes to the API. pmacct is now aligned to compile against these. At the same time support for nDPI 3.x was dropped. ! fix, plugin_common.[ch]: when stitching feature was enabled, ie. nfacctd_stitching, timestamp_min was never reset. Also both timestamp_min and timestamp_max were clamped to sec granularity. ! fix, BGP, BMP daemons: added a tmp_bgp_daemon_origin_type_int to print out BGP "origin" field as int (legacy behaviour) instead of string (current behaviour). In a future major release the legacy behaviour will be dropped. ! fix, BGP, BMP daemons: MPLS labels are now encoded in both JSON and Apache Avro as 'mpls_label' instead of 'label'. This is to align behaviour with pre_tag_map where 'label' has a different semantic. ! fix, BGP, BMP daemons: resolved memory leak when encoding log messaging (logmsg) in Avro format with Schema Registry support. ! fix, BGP daemon: improved handling of ADD-PATH capability, making it per-AF (as it is supposed to be) and not global. ! fix, BMP daemon: now checking that ADD-PATH capability is enabled at both ends of the monitored session (check both BGP OPEN in a Peer Up message) in order to infer that the capability exchange was successful. Also some heuristics were added to conciliate BGP Open vs BGP Update 4-bytes ASN reality. ! fix, nfacctd: improved parsing of NetFlow v9 Options data particularly when multiple IEs are packed as part of a flowset. ! fix, nfacctd: corrected parsing of Information Element 351 (layer2SegmentId). ! fix, pmacctd: improved processing of pcap_interfaces_map for cases where the same interface is present multiple times (maybe with different directions). Also, if the map is empty then bail out at startup. ! fix, pmacctd: SEGV when ICMP/ICMPv6 traffic was processed and 'flows' primitive was enabled. ! fix, pmacctd: sampling_rate primitive value was not reported correctly when 'sampling_rate' config directive was specified. ! fix, pmbgpd, pmpmbd, pmtelemtryd: changed SIGCHLD handler to prevent zombification of last spawned data dump writer. ! fix, Kafka plugin: moved the schema registration from the dump writer to the plugin process in order to register the schemas only once at plugin startup and not on every start of a writer process. Thanks to Uwe Storbeck ( @ustorbeck ) for this contribution. ! fix, Kafka plugin: a check for kafka_partition was missing, leading the plugin to always use the default partitioner instead of sending data to the configured fixed partition. Thanks to Martin Pels ( @rodecker ) for this contribution. ! fix, nfprobe plugin: BGP data enrichment was not working due to a mistakenly moved pointer. ! fix, sfprobe plugin: AS-PATH was being populated even when null; added a check to see if the destination AS is not zero in order to put the destination AS into the AS-PATH for sFlow packets. Thanks to Marcel Menzel ( @WRMSRwasTaken ) for this contribution. ! fix, networks_file: remove_dupes() was making partial commits of valid rows hence creating data inconsistencies. ! fix, pre_tag_map: resolved a potential string overflow that was being triggered in pretag_append_label() when data would be assigned more than one single label. Also now allow ',' chars in set_label. ! fix, maps_index: uninitialized var could cause SEGV in case no results are found in the map index. Also introduced support for catch-all rules, ie. "set_label=unknown". ! fix, maps_index: optimized the case of no 'ip' key specified (for nfacctd and sfacctd): when indexing is enabled, prevent recirculation from happening, ie. test v4 first then v6, since the 'ip' key is not going to be part of the hash serializer. ! fix, pretag.c: allow to allocate maps greater than 2GB in size. Also several optimizations were carried out yelding to a better memory utilization for allocated maps along with improved times to resolve JEQs. ! fix, pre_tag_label_filter: optimized and improved runtime evaluation part of this feature, avoiding a costly strdup() and returning immediately on certain basic mismatch conditions. ! fix, kafka_common.[ch]: a new p_kafka_produce_data_and_free() is invoked to optimize memory allocations and releases. ! fix, plugin_cmn_avro.c: when a schema registry is being defined, ie. kafka_avro_schema_registry, the logic to generate the schema name has been changed: use topic plus record name as the schema name, use underscore as separator within the record name, stop adding a "-value" suffix. Thanks to Uwe Storbeck ( @ustorbeck ) for this contribution. ! fix, util.c: roundoff_time() to reason always with the locally configured time, like for the rest of functional (as in non-data) timestamps, ie. refresh time, deadline, etc. ! fix, log.c: when log messages are longer than message buffer, the message gets cut off. As the trailing newline also gets cut off the message will be concatenated with the following message which makes the log hard to read. Thanks to Uwe Storbeck ( @ustorbeck ) for this contribution. - Completed the retirement of legacy packet classification based on home-grown code (Shared Objects) and the L7 layer project. - Removed the mpls_stck_depth primitive due to the introduction of the mpls_label_stack primitive. 1.7.7 -- 07-11-2021 + BGP, BMP, Streaming Telemetry daemons: introduced parallelization of dump events via a configurable amount of workers where the unit of parallelization is the exporter (BGP, BMP, telemetry exporter), ie. in a scenario where there are 4 workers and 4 exporters each worker is assigned one exporter data to dump. + pmtelemetryd: added support for draft-ietf-netconf-udp-notif: a UDP-based notification mechanism to collect data from networking devices. A shim header is proposed to facilitate the data streaming directly from the publishing process on network processor of line cards to receivers. The objective is a lightweight approach to enable higher frequency and less performance impact on publisher and receiver process compared to already established notification mechanisms. Many thanks to Alex Huang Feng ( @ahuangfeng ) and the whole Unyte team. + BGP, BMP, Streaming Telemetry daemons: now correctly honouring the supplied Kafka partition key for BGP, BMP and Telemetry msg logs and dump events. + BGP, BMP daemons: a new "rd_origin" field is added to output log/ dump to specify the source of Route Distinguisher information (ie. flow vs BGP vs BMP). + pre_tag_map: added ability to tag new NetFlow/IPFIX and sFlow sample_type types: "flow-ipv4", "flow-ipv6", "flow-mpls-ipv4" and "flow-mpls-ipv6". Also added a new "is_bi_flow" true/false key to tag (or exclude) NSEL bidirectional flows. Added as well a new "is_multicast" true/false config key to tag (or exclude) IPv4/IPv6 multicast destinations. + maps_index: enables indexing of maps to increase lookup speeds on large maps and/or sustained lookup rates. The feature has been remplemented using stream-lined structures from libcdada. This is a major work that helps preventing the unpredictable behaviours caused by the homegrown map indexing mechanism. Many thanks to Marc Sune ( @msune ). + maps_index: support for indexing src_net and dst_net keywords has been added. + Added _ipv6_only config directives to optionally enable the IPV6_V6ONLY socket option. Also changed the wrong setsockopt() IPV6_BINDV6ONLY id to IPV6_V6ONLY. + Added log function to libserdes to debug transactions with the Schema Registry when kafka_avro_schema_registry is set. + nDPI: newer versions of the library (ie. >= 3.5) bring changes to the API. pmacct is now aligned to compile against these. + pmacctd: added pcap_arista_trailer_offset config directive since Arista has changed the structure of the trailer format in recent releases of EOS. Thanks to Jeremiah Millay ( @floatingstatic ) for his patch. + More improvements carried out on the Continuous Integration (CI) side by migrating from Travis CI to GitHub Actions. Huge thanks to Marc Sune ( @msune ) to make all of this possible. + More improvements also carried out in the space of the Docker images being created: optimized image size and a better layered pipeline. Thanks to Marc Sune ( @msune ) and Daniel Caballero ( @dcaba ) to make all of this possible. + libcdada shipped with pmacct was upgraded to version 0.3.5. Many thanks Marc Sune ( @msune ) for his work with libcdada. ! build system: several improvements carried out in this area, ie. improved MySQL checks, introduced pcap-config tool for libpcap, compiling on BSD/old compilers, etc. Monumental thanks to Marc Sune ( @msune ) for his continued help. ! fix, nfacctd: improved euristics to support the case of flows with both IPv4 and IPv6 source / destination addresses (either or populated). Also improved euristics to distinguish event data vs traffic data in NetFlow v9/IPFIX from Cisco 9300/9500, ASA firewalls and Cisco 4500X. ! fix, nfacctd: improved support for initiatorOctets (IE #231) and responderOctets (IE #232). Thanks to Esben Laursen ( @hyberdk ) for reporting the issue. ! fix, nfacctd: in NF_mpls_vpn_id_handler() double ntohl() calls were applied for the case of 'vrfid'-encoded mpls_vpn_rd field. ! fix, sfacctd: wrong ethertype set for VLAN-tagged, MPLS-labelled IPv6 traffic. Impacting BGP resolution among others. Thanks to Jeremiah Millay ( @floatingstatic ) for his help resolving the problem. ! fix, BGP, BMP daemons: parsing improvements: added a check for BGP Open message and BGP Open Options lengths. Strengthened parsing of Peer Up, Route Monitoring and Peer Down v4 messages. ! fix, BGP, BMP daemon: when using Avro encoding and Avro Schema Registry, attempt to reconnect if serdes schemas are voided. Also now checking for serdes schema definitions before doing a serdes_schema_serialize_avro() to avoid triggering a SEGV. Finally improved serdes logging. ! fix, BGP, Streaming Telemetry daemons: in daemon logs, summary counters for amount of tables / entries dumped were wrong. ! fix, BGP daemon: distinguish among null and zero value AIGP and Prefix SID attributes. Same applies for Local Preference and MED attributes. ! fix, BMP daemon: resolved a memory leak in bgp_peers_free(). Thanks to Pether Pothier ( @pothier-peter ) for his patch. Also resolved a leak caused by an invalid BGP message contained in a BMP Route Message v4. ! fix, BMP daemon: correctly setting peer_ip and peer_tcp_port JSON fields for Term messages. Also the correct bmp_router value when bmp_daemon_parse_proxy_header feature is enabled. ! fix, BMP daemon: several encoding issues when using Apache Avro ie. u_int64_t now correctly encoded with avro_value_set_long(), certain u_int32_t fields switched to avro_value_set_long() due to lack of unsignedness in Avro encoding, improved various aspectes of Avro-JSON format output, etc. ! fix, pmtelemetryd: wrong parsing of pm_tfind() output was leading to mistaken data attribution of UDP-based peers (always first peer to connect was being picked). ! fix, pmtelemetryd: when set, the pidfile config directive was not being correctly honoured. ! fix, RPKI: the RTR PDU element for maxLength is uint8, therefore it might have been possible to transmit incorrect RTR data. Thanks to Job Snijders ( @job ) for his patch. ! fix, SQL plugins: amended the text composition of SQL queries that are involving latitude and longitude keys. ! fix, MySQL plugin: check for 'unix:' prefix string only when a sql_host configuration directive is specified. ! fix, nfprobe: modernized Application Information export. Until the previous release pmacct was adhering to aging NBAR model whereas now NBAR2 has been implemented. Thanks to Rob Cowart ( @robcowart ) for helping out resolving this issue. ! fix, tee plugin: restored usefulness of tee_source_ip which was broken in 1.7.6. Thanks to Jeremiah Millay ( @floatingstatic ) for reporting the issue. ! fix, maps_index: indexing of mpls_pw_id was broken. Also now, when the feature is enabled, actual data is being referenced in the index structure instead of creating a copy of it; thanks to Sander van Delden ( @SanderDelden ) for reporting the memory leak that was resulting from the copy. ! fix, kafka_common.c: solved memory leak in p_kafka_set_topic() when Kafka session was getting in down state. Many thanks to Peter Pothier ( @pothier-peter ) for nailing the issue. ! fix, net_aggr.[ch]: when a networks_file is specified in the config, gracefully handle max memory structure depth; added also de-duplication of entries. ! fix, pmacct-defines.h: if PCAP_NETMASK_UNKNOWN is not defined, ie. in libpcap < 1.1.0, let's define it. ! fix, SO_REUSEPORT feature was being restricted to Linux only in previous releases: now it has been unlocked to all other OS that do support the feature. ! fix, split SO_REUSEPORT and SO_REUSEADDR setsockopt() calls. Thanks to @eduarrrd for reporting and resolving the issue. ! fix, several code warnings catched gcc9 and clang. - Obsoleted sql_history_since_epoch, pre_tag_map_entries and refresh_maps configuration directives. 1.7.6 -- 07-02-2021 + Added dependency to libcdada in an effort to streamline basic data structures needed for everyday coding. All new structures will make use of libcdada, old ones will be ported over time. Libcdada offers basic data structures in C: ie. list, set, map/ hash table, queue and is a libstdc++ wrapper. Many thanks to Marc Sune ( @msune ) for his work with libcdada and his enormous help facilitating the integration. + BGP daemon: added suppport for Accumulated IGP Metric Attribute (AIGP) and Label-Index TLV of Prefix-SID Attribute. + BGP daemon: added SO_KEEPALIVE TCP socket option (ie. to keep the sessions alive via a firewall / NAT kind of device). Thanks to Jared Mauch ( @jaredmauch ) for his patch. + BGP daemon: if comparing source TCP ports among BGP peers is being enabled (config directive tmp_bgp_lookup_compare_ports), print also BGP Router-ID as distinguisher as part of log/dump output. + BMP daemon: added support for HAProxy Proxy Protocol Header in the first BMP message in order to determine the original sender IP address and port. The new bmp_daemon_parse_proxy_header config directive enables the feature. Contribution is by Peter Pothier ( @pothier-peter ). + BMP daemon: improved support and brought implementation on par with the latest drafting efforts at IETF wrt draft-cppy-grow-bmp- path-marking-tlv, draft-xu-grow-bmp-route-policy-attr-trace, draft-ietf-grow-bmp-tlv and draft-lucente-grow-bmp-tlv-ebit. + BMP daemon: added 'bgp_agent_map' equivalent feature for BMP. + nfacctd, nfprobe plugin: added support for collection and export of NetFlow/IPFIX data over Datagram Transport Layer Security (in short DTLS). The feature depends on the GnuTLS library. + nfacctd: added support for deprecated NetFlow v9 IE #104 (layer2packetSectionData) as it is implemented for NetFlow-lite on Cisco devices. Reused code from IPFIX IE #315. + nfacctd: added support for MPLS VPN RD IE #90. This comes in two flavours both found across vendor implementations: 1) IE present in flow data and 2) IE present in Options data as a lookup from IE #234 (ingressVRFID) and #235 (egressVRFID). + nfacctd: added a new timestamp_export aggregation primitive to record the timestamp being carried in the header of NetFlow/IPFIX messates (that is, the time at which the export was performed). + nfprobe plugin: added support for ICMP/ICMPv6 information as part of the NetFlow/IPFIX export. The piece of info is encoded in the destination port field as per the current common understandings across vendors. As a result of that, the 'dst_port' primitive is to be part of the aggregation method in order to leverage this feature. + MySQL plugin: introduced support to connect to a MySQL server via UNIX sockets. + tee plugin: added crc32 hash algorithm as a new balancing option for nodes in the receiving pool. It hashes original exporter IP address against a crc32 function. Thanks to @edge-intelligence for the contribution. + Massive improvements carried out on the Continuous Integration (CI) side, ie. to ensure better quality of the code, and on the containerization side by offering official stable / bleeding edge Docker images. Huge thanks to Marc Sune ( @msune ) to make all of this possible. ! fix, BGP daemon: re-worked internal structuring of 'modern' BGP attributes: for the sake of large-scale space optimization certain attributes are confined in a separate (less used) bgp_info_extra structure. ! fix, BGP daemon: improved support for BGP ADD-PATH, ie. made it per Address-Family rather than global. Also comparisons upon doing route looup were improved and normalized. ! fix, BGP daemon: use split buffers for recv and send functions of the BGP x-connects feature. Also improved validation when processing a bgp_daemon_xconnect_map. ! fix, BGP daemon: when using BGP x-connects, close unused file descriptors in bgp_peer_xconnect_init() in order to avoid quickly reaching the maximum amount of allowed open descriptors in case of BGP flaps. ! fix, BGP daemon: trigger a log message for a missing entry while processing bgp_daemon_xconnect_map in bgp_peer_xconnect_init(). ! fix, BGP daemon: enabled log notifications (that is, log anti- spam measure) upon reaching limit of allowed BGP peers. ! fix, BGP daemon: ecommunity_ecom2str(), first thing make sure that the destination size is enough! Missing this did cause some SEGVs due to heap corruption. Thanks to Chris Danis ( @cdanis ) for his help resolving the issue. ! fix, BGP daemon: solved a memory leak in aspath_make_str_count() by returning result from aspath_make_empty(), if any. Thanks very much to Peter Pothier ( @pothier-peter ) for his contribution. ! fix, BMP daemon: several encoding issues when using Apache Avro ie. missing conditional branching, wrong field names, etc. Thanks also to Raphael Barazzutti ( @rbarazzutti ) for several of those fixes. ! fix, BMP daemon: throw an error for any issues (error or zero length) related to the BGP Update PDU parsing; also added marker and length checks for BGP Open PDU in Peer Up messages. ! fix, BMP daemon: both timestamp of the BMP event and its arrival at the collector are now recorded and printed out separately; before they were wrongly muxed on one single field making it uncertain for the user what was the time reference. ! fix, BMP daemon: correctly print Peer Distinguisher for Route Monitoring messages. Also improved BMP lookup comparisons in order to factor in Peer Distinguisher if any. ! fix, BMP daemon: print 'is_in' boolean for Adj-Rib-In data instead of having it implicit. Also print 'is_post' for Post- Policy Adj-Rib-In data. ! fix, BMP daemon: upon receipt of a Termination message, do proactively close the TCP session. ! fix, nDPI: newer versions of the library (ie. >= 3.2) require calling ndpi_finalize_initialization() somewhere after the detection module init finished. Contribution is from Toni Uhlig ( @lnslbrty ). ! fix, pmacctd: link checks were being mistakenly skipped when reading from a pcap_savefile. Also now if a selected aggregation primitive is unsuitable for a given Layer2, it is simply cleared (with an info message issued) instead of making the daemon bail out. | fix, print plugin: bail the plugin out if its output was set to stdout while the daemon was started as daemonized. ! fix, PostgreSQL plugin: in PG_compose_conn_string() allow any intersection of host, port and cafile options. ! fix, nfprobe plugin: changed default export version from NetFlow v5 to IPFIX. ! fix, sfprobe plugin: FreeBSD was complaining of errno 22 (Invalid argument) upon sendto(). ! fix, tee plugin: replication of IPv6 packets has been now tested working. Previously the output message size was obviously encoded wrongly and the checksum (mandatory piece of info to fill in IPv6, contrary to IPv4 where it is optional) was not being computed. ! fix, kafka_common.c: improved p_kafka_check_outq_len() error log message to report the amount of elements have been successfully processed in order to better assess impact and dynamics of the problem when inspecting logs. ! fix, net_aggr.c: if networks_file_filter is set to true, don't add a default route to the table. ! fix, cfg.c: throw error if config file is not a regular file. ! fix, compiling against gcc10: renamed some variables and unified declaration of others in order to be more friendly to the new version of gcc. Also fixed several code warnings catched gcc8. - Removed the IP prefix label feature that was enabled via the --enable-plabel configure script switch. 1.7.5 -- 17-06-2020 + pmacct & Redis: pmacct daemons can now connect to a Redis cache. The main use-case currenly covered is: registering every stable daemon component in a table so to have, when running a cluster comprising several daemons / components, an olistic view of what is currently running and where; shall a component stop running or crash it will disappear from the inventory. + BMP daemon: as part of the IETF 107 vHackaton, preliminar support for draft-xu-grow-bmp-route-policy-attr-trace and draft-lucente- grow-bmp-tlv-ebit was introduced. Also added support for Peer Distinguisher field in the BMP Per-Peer Header. + BMP daemon: added support for reading from savefiles in libpcap format (pcap_savefile, pcap_savefile_delay, pcap_savefile_replay, pcap_filter) as an alternative to the use of bmp_play.py. + BMP daemon: re-worked, improved and generalized support for TLVs at the end of BMP messages. In this context, unknown Stats data is handled as a generic TLV. + BMP daemon: added SO_KEEPALIVE TCP socket option (ie. to keep the sessions alive via a firewall / NAT kind of device). Thanks to Jared Mauch ( @jaredmauch ) for his patch. + nfacctd, nfprobe plugin: added usec timestamp resolution to IPFIX collector and export via IEs #154, #155. For export, this can be configured via the new nfprobe_tstamp_usec knob. + nfacctd: new nfacctd_templates_receiver and nfacctd_templates_port config directives allow respectively to specify a destination where to copy NetFlow v9/IPFIX templates to and a port where to listen for templates from. If nfacctd_templates_receiver points to a replicator and the replicator exports to nfacctd_templates_port of a set of collectors then, for example, it gets possible to share templates among collectors in a cluster for the purpose of seamless scale-out. + pmtelemetryd: in addition to existing TCP, UDP and ZeroMQ inputs, the daemon can now read Streaming Telemetry data in JSON format from a Kafka broker (telemetry_daemon_kafka_* config knobs). + pmgrpcd.py: Use of multiple processes for the Kafka Avro exporter to leverage the potential of multi-core/processors architectures. Code is from Raphael P. Barazzutti ( @rbarazzutti ). + pmgrpcd.py: added -F / --no-flatten command-line option to disable object flattening (default true for backward compatibility); also export to a Kafka broker for (flattened) JSON objects was added (in addition to existing export to ZeroMQ). + nDPI: introduced support for nDPI 3.2 and dropped support for all earlier versions of the library due to changes to the API. + Docker: embraced the technology for CI purposes; added a docker/ directory in the file distribution where Dockerfile and scripts to build pmacct and dependencies are shared. Thanks to Claudio Ortega ( @claudio-ortega ) for contributing his excellent work in the area. ! fix, pmacctd: pcap_setdirection() enabled and moved to the right place in code. Libpcap tested for function presence. Thanks to Mikhail Sennikovsky for his patch. ! fix, pmacctd: SEGV has been detected if passing messages with an unsupported link layer. ! fix, uacctd: handle non-ethernet packets correctly. Use mac_len = 0 for non-ethernet packets in which case a zeroed ethernet header is used. Thanks to @aleksandrgilfanov for his patch. ! fix, BGP daemon: improved handling of withdrawals for label-unicast and mpls-vpn NLRIs. ! fix, BGP daemon: improved decoding of MPLS labels by passing it via a "0x%02x%02x%01x" formatter. In the past some labels may have been printed out incorrectly. ! fix, BGP daemon: decoding origin field correctly. Thanks to Peter Pothier ( @pothier-peter ) for his patch. ! BGP Looking Glass: LG code was moved from pmbgpd to pmacct libbgp so to be re-used in other components (ie. BGP thread of a flow daemon, BMP daemon, etc.). ! fix, BMP daemon: timestamps for Route Monitoring message were set to the current time rather than timestamp in the Per-Peer Header. Thanks to Peter Pothier ( @pothier-peter ) for reporting the issue. ! fix, BMP daemon: V flag test to allow IPv6 prefixes/peers was not correct (details in PR #362 on GitHub). Thanks @bcavns01 for his patch. ! fix, BGP, BMP daemons: modified approach to message segmentation by ensuring reading exactly one message at a time (instead of the previous unaligned approach that was aiming to fill the available read buffer up) and waiting for all segments be available before processing a message (instead of the previous greedy approach that was trying to parse also partial messages). ! fix, RPKI daemon: in rpki_prefix_lookup_node_match_cmp() prevent invalid results to over-write a previously computed valid one. ! fix, pmtelemetryd: recv() does include a MSG_WAITALL option to make sure all data is available before processing a given message; now n alarm() syscall is introduced so to prevent stalls due to bogus / incomplete data. ! fix, tee plugin: Tee_init_socks() now does not overwrite previously computed address length anymore: issues were repoted with IPv6 IPv4- mapped addresses. ! fix, nfprobe plugin: take into account ingress/egress interfaces, if available, when comparing flows. Thanks to Mikhail Sennikovsky for his patch. ! fix, pretag.c: incorrect string termiantion in pretag_copy_label() was making the daemon SEGV upon certain conditions when defining set_label statements in a pre_tag_map. ! fix, pretag_handlers.c: pretag_copy_label() instead of memcpy() in pretag_label_handler() to not borrow reference to label value and consequently lead to SEGV. ! fix, zmq_common.c: missing variable init in p_zmq_zap_handler() was giving troubles with gcc7 compiler optimizations. Thanks to Yuri Lachin ( @yuyutime ) for his support resolving this bug. ! fix, sql_common.c: print custom primitives with hex semantics among quotes. Hexs require a char type defined in the SQL table schema. ! fix, addr.c: passing right aligned argument to ip6_addr_cmp() in host_addr_mask_cmp(). This was found to impact selective replication of IPv6 flows basing on src_net and/or dst_net primitives in the pre_tag_map. ! fix, several code warnings catched by gcc7 and gcc8. Also several functions were renamed to avoid namespace conflicts with linked libraries. - Obsoleted --enable-64bit knob which was already defaulting to true for some releases already. - Obsoleted savefile_wait config knob (pcap_savefile_wait must be used instead). 1.7.4p1 -- 09-02-2020 ! fix, pre_tag_map: a memory leak in pretag_entry_process() has been introduced in 1.7.4. Thanks to Fabien Vincent and Olivier Benghozi for their support resolving the issue. 1.7.4 -- 31-12-2019 + Released pmgrpcd.py v3: a Streaming Telemetry collector and decoder for multi-vendor environments written in Python3. It supports gRPC transport along with Protobuf encoding as input and can output to Kafka with Avro encoding. Output to files and JSON encoding is currently supported sending data via ZMQ to pmtelemetryd first. It was tested working with data input from Cisco and Huawei routers and v3 replaces v2. Thanks to the Streaming Telemetry core team: Matthias Arnold ( @tbearma1 ), Camilo Cardona ( @jccardonar ), Thomas Graf ( @graf3 , @graf3net ), Paolo Lucente ( @paololucente ). + Introduced support for the 'vxlan' VXLAN/VNI primitive in all traffic daemons (NetFlow/IPFIX, sFlow and libpcap/ULOG). Existing inner tunnel primitives (ie. tunnel_src_host, tunnel_dst_host, tunnel_proto, etc.) have been wired to the VXLAN decoding and new ones (tunnel_src_mac, tunnel_dst_mac, tunnel_src_port, tunnel_dst_port) were defined. + BMP daemon: added support for Peer Up message namespace for TLVs (draft-ietf-grow-bmp-peer-up) and also support for Route Monitor and Peer Down TLVs (draft-ietf-grow-bmp-tlv). + BGP, BMP daemons: in addition to existing JSON export, data can now be exported in Apache Avro format. There is also support for the Confluent Schema Registry. + Introduced support for JSON-encoded Apache Avro encoding. While the binary-encoded Apache Avro is always recommended for any production scenarios (also to optionallly leverage Confluent Schema Registry support), JSON-encoded is powerful for testing and troubleshooting scenarios. + sfprobe plugin: added support for IPv6 transport for sFlow export. sfprobe_agentip is an IP address put in the header of the sFlow packet. If underlying transport is IPv6, this must be configured to an IPv6 address. + zmq_common.[ch]: Improved modularity of the ZMQ internal API and decoupled bind/connect from push/pull and pub/sub; also improved support for inproc sockets. All to increase the amount of use-cases covered by the API. + bgp_peer_src_as_map: added 'filter' key to cover pmacctd/uacctd use cases. + nfprobe, sfprobe plugins: introduced [sn]fprobe_index_override to override ifindexes dynamically determined (ie. by NFLOG) with values computed by [sn]fprobe_ifindex. + MySQL, PostgreSQL plugins: added support for SSL/TLS connections by specifying a CA certificate (sql_conn_ca_file). + Kafka, AMQP plugins: amqp_markers and kafka_markers have now been properly re-implemented when output encoding is Avro using an own Avro schema (instead of squatting pieces of JSON in the data stream for the very purpose). + print plugin: introduced print_write_empty_file config knob (true, false) to create an empty output file when there are no cache entries to purge. Such behaviour was present in versions up to 0.14 and may be preferred by some to the new >= 1.5 versions behaviour. Thanks to Lee Yongjae ( @setup74 ) for the contribution. ! fix, signals.c: signals handling has been restructured in order to block certain signals during critical sections of data processing. Thanks to Vaibhav Phatarpekar ( @vphatarp ) for the contribution. ! fix, signals.c: slimmed reload() signal handler code and moved it to a synchronous section. The handler is to reset logging output to files or syslog. Thanks to Jared Mauch ( @jaredmauch ) for his support resolving this. ! fix, pmbgpd, pmbmpd and pmtelemetryd daemons: added extra signals handling (SIGINT, SIGTERM, SIGCHLD) consistently to traffic daemons. ! fix, BGP daemon: withdrawals of label-unicast (support introduced in 1.7.3) and mpls-vpn NLRIs did fail to parse in release 1.7.3 and were silently discarded. ! fix, nfacctd: wired (BGP, BMP, ISIS, etc) lookups to NetFlow (Secure) Event Logging (NEL/NSEL). ! fix, pmtelemetryd: re-implemented a decoder for so-called Cisco v1 Streaming Telemetry proprietary header over UDP/TCP streams. ! fix, pmtelemetryd: improved sanitization of input JSON objects by also checking for isspace() other than isprint() for pretty-printed objects. ! maps_index: optimized lookups, improved debugging output upon loading indexes. ! fix, tee plugin: overwriting computed IP address length with socket container length was found to prevent output data on some BSDs. ! fix, kafka_common.c: if taking the p_kafka_close() route, ensure to return and not perform any further polling in order to avoid SEGVs. ! fix, BMP daemon: incorrect decoding of type was preventing correct logging of Init and Term messages extra info. Also in Term messages TLV data was incorrectly consumed twice triggering length check warnings. ! fix, BMP daemon: added checks for successful BGP PDU parsing in both Peer Up (BGP OPEN) and Route Monitor (BGP UPDATE) messages. ! fix, BMP daemon: improved length checks and making sure that strings potentially non null-terminated are now terminated. Also TLV-related code has been refactored. ! fix, pmbgp.py: the example client for BGP Looking Glass was migrated to Python3: thanks to @brusilov for the contribution. ! fix, nfacctd: if src_port or dst_port primitives are selected, enable IP fragment handling. Needed to process L4 of IPFIX IE #351. ! fix, nfv9_template.c: correct handling of variable-length IPFIX fields. Thanks to Nimrod Mesika ( @nimrody ) for the contribution. ! fix, PostgreSQL plugin: ABSTIME was replaced with to_timestamp() in queries as support for ABSTIME was dropped as of PostgreSQL 12. Many thanks to Manuel Mendez ( @mmlb ) for the contribution. ! fix, PostgreSQL plugin: SEGVs were observed when the queue of pending queries was non-empty (ie. nfacctd_time_new set to false, default); thanks to Guo-Wei Su ( @nansenat16 ) for the contribution. ! fix, cfg_handlers: [sn]facctd_disable_checks, nfacctd_disable_opt_ scope_check could not be properly set to false. ! fix, sql_common.c: src_host_coords and dst_host_coords primitives have been correctly spaced in SQL queries. Also float values are now quoted. Finally, sampling_direction primitive is encoded correctly. ! fix, kafka plugin: if kafka_avro_schema_registry is in use, subject name is aligned to Kafka topic name (if topic is not dynamic). ! fix, pretag.c: when using 'label', store the label string in the heap (instead of the stack). Thanks to Raphael P. Barazzutti ( @rbarazzutti ) for the contribution. ! fix, pretag.c: JEQ labels are now correctly free() during init upon map reload. ! fix, zmq_common.c: missing variable init in p_zmq_zap_handler() was causing plugin_pipe_zmq operations to fail on certain compilers (ie. gcc7). Thanks to Yuri Lachin ( @yuyutime ) for his support. ! fix, cfg_handlers.c: reviewed handling of parsed 'zero' value for several config directives. ! fix, countless code warnings when enabling -Wall (--enable-debug); also included -Wall in Continuous Integration tests. Restructured globals, header inclusions, function prototypes definition, etc. Many thanks to Marc Sune ( @msune ) for all his efforts. ! fix, configure.ac: evaluation of --enable-debug pushed to the end of the script so to not interfere with tests (ie. alignment, endianess, etc.). - BMP daemon: retired support for draft-hsmit-bmp-extensible-routemon- -msgs. - AMQP plugin: obsoleted amqp_avro_schema feature (which includes amqp_avro_schema_routing_key and amqp_avro_schema_refresh_time keys config keys). Avro schemas can now only be written to files. 1.7.3 -- 16-05-2019 + Introduced the RPKI daemon to build a ROA database and check prefixes validation status and coverages. Resource Public Key Infrastructure (RPKI) is a specialized public key infrastructure (PKI) framework designed to secure the Internet routing. RPKI uses certificates to allow Local Internet Registries (LIRs) to list the Internet number resources they hold. These attestations are called Route Origination Authorizations (ROAs). ROA information can be acquired in one of the two following ways: 1) importing it using the rpki_roas_file config directive from a file in the RIPE Validator format or 2) connecting to a RPKI RTR Cache for live ROA updates; the cache IP address/port being defined by the rpki_rtr_cache config directive (and a few more optional rpki_rtr_* directives are available and can be reviwed in the CONFIG-KEYS doc). The ROA fields will be populated with one of these five values: 'u' Unknown, 'v' Valid, 'i' Invalid no overlaps, 'V' Invalid with a covering Valid prefix, 'U' Invalid with a covering Unknown prefix. Thanks to Job Snijders ( @job ) for his support and vision. + Introducing pmgrpcd.py, written in Python, a daemon to handle gRPC- based Streaming Telemetry sessions and unmarshall GPB data. Code was mostly courtesy by Matthias Arnold ( @tbearma1 ). This is in addition (or feeding into) pmtelemetryd, written in C, a daemon to handle TCP/UDP-based Streaming Telemetry sessions with JSON-encoded data. Thanks to Matthias Arnold ( @tbearma1 ) and Thomas Graf for their support and contributing code. + pmacctd, uacctd: added support for CFP (Cisco FabricPath) and Cisco Virtual Network Tag protocols. Both patches were courtesy by Stephen Clark ( @sclark46 ). + print plugin: added 'custom' to print_output. This is to cover two main use-cases: 1) use JSON or Avro encodings but fix the format of the messages in a custom way and 2) use a different encoding than JSON or Avro. See also example in examples/custom and new directives print_output_custom_lib and print_output_custom_cfg_file. The patch was courtesy by Edge Intelligence ( @edge-intelligence ). + Introducing mpls_pw_id aggregation primitive and mpls_pw_id key in pre_tag_map to filter on signalled L2 MPLS VPN Pseudowire IDs. + BGP daemon: added bgp_disable_router_id knob to enable/disable BGP Router-ID check, both at BGP OPEN time and BGP lookup. Useful, for example, in scenarios with split BGP v4/v6 AFs over v4/v6 transports. + BGP, BMP daemons: translate origin attribute numeric value into IGP (i), EGP (e) and Incomplete (u) strings. + plugins: added new plugin_exit_any feature to make the daemon bail out if any (not all, which is the default behaviour) of the plugins exits. + maps_index: improved selection of buckets for index hash structure by picking the closest prime number to the double of the entries of the map to be indexed in order to achieve better elements dispersion and hence better performances. + nfacctd: added support for IPFIX templateId-scoped (IE 145) sampling information. + pmacctd, uacctd, sfacctd, nfacctd: added a -M command-line option to set *_markers (ie. print_markers) to true and fixed -A command-line option to set print_output_file_append to align to true/false. ! fix, BGP, BMP, Streaming Telemetry daemons: improved sequencing of dump events by assigning a single sequence number per event (ie. for streaming pipeline scenarios in order to reduce correlation with dump_init/dump_close messages). Also amount of record dumped was added to the close message. ! fix, BGP, BMP, Streaming Telemetry daemons: removed hierarchical json_decref() since json_object_get() borrows reference. This was occasionaly leading to SEGVs. ! fix, uacctd: dynamically allocate jumbo_container buffer size as packets larger than 10KB, previous static allocation, would lead to crashes. ! fix, nfacctd: wired (BGP, BMP, ISIS, etc.) lookups to the NEL/NSEL use-case. ! fix, nfacctd: search for IE 408 (dataLinkFrameType) was leading to SEGVs. Also improved handling of variable-length IPFIX templates. ! fix, BMP daemon: solved an occasional truncation of the last message in a packet. ! fix, BGP daemon: when processing bgp_daemon_md5_file, ipv4 addresses were incorrectly translated to ipv4-mapped ipv6 ones as a result of which TCP-MD5 hashes were not correctly bound to sockets. ! fix, BGP daemon: improved label-unicast and mpls-vpn SAFIs handling (some bogus messages, multiple labels, etc.). ! fix, BGP daemon: introduced PREFIX_STRLEN to make enough room for prefix2str() calls (before unsufficient INET6_ADDRSTRLEN was used). ! fix, BMP daemon: improved handling of ADD-PATH capability. ! fix, plugins: an incorrect evaluation in P_cache_attach_new_node did make possible to buffer overrun in plugins cache allocation. This was found related to a "[..]: Assertion `!cache_ptr->stitch' failed." daemon bail-out message. ! fix, plugins: if pidfile directive was enabled, exit_gracefully() was mistakenly deleting the plugin pidfile when called by a child process (ie. writer, dumper, etc.). ! fix, plugins: when taking exit_gracefully(), if the process is marked as 'is_forked', just exit and don't perform extra ops in exit_all() or exit_plugin(). ! fix, plugins: re-evaluate dynamic tables/files name if *_refresh_time is different than *_history period. ! fix, SQL plugins: a missing 'AND' was making SQL statements related to src_host_coords and dst_host_coords fail. ! fix, GeoIPv2: if no match is returned by libmaxminddb, return O1 code (Other Country) instead of a null value. ! fix, flow_to_rd_map: mpls_vpn_id was not working when maps_index was enabled. Also partly re-written mpls_vpn_id handler. ! fix, nfprobe plugin: serialize_bin() function introduced for correct serialization of custom primitives defined with 'raw' semantics. ! fix, PostgreSQL plugin: testing for presence of PQlibVersion() in libpq to prevent compiling issues (ie. on CentOS 6). ! fix, MySQL plugin: including mysql_version.h to compile successfully against newer MariaDB releases. ! fix, nDPI classification: send log message if 'class' primitive is selected but nDPI is not compiled in; also updated code to follow API changes in versions >= 2.6 of the library. Dropped support for versions < 2.4. ! fix, sfprobe plugin: added (and documented) conditional for optional export of classification info. ! fix, aggregate_primitives: field_type is now also allowed for pmacctd and uaccd daemons so that it can be used for NetFlow v9/IPFIX export (nfprobe plugin) purposes. ! fix, pre_tag_map: if no 'ip' keyword is specified, an entry of the map gets recirculated in order to be set for both v4 and v6 maps. If a 'set_label' is also specified, it was causing a SEGV. Now the label is correctly copied in case of recirculation. ! fix, zmq_common.c: added option for non-blocking p_zmq_send_bin() as otherwise program would block in case of no consumers (main use-case: flow replication over ZeroMQ queues); as a result, a generous hwm value was added on both sides of these queues. ! fix, zmq_common.c: ZAP socket moved inside thread to prevent failed assert() when compiling with gcc7/gcc8. Also a single user/password auto-generated combination is used for all plugins. ! fix, signals.c: SIGUSR1 handler for nfacctd and nfacctd is changed to syncronous in order to prevent race conditions. Also, in pmacctd, upon sending SIGUSR1, stats were not printed when reading packets from a pcap_interfaaces_map. ! fix, plugin_cmn_json.c: if leaving protocols numerical (ie. proto, tunnel_proto primitives), convert them to string-represented numbers for data consistency for consumers. ! fix, util.c: open_output_file(), if file exists and it's a FIFO then set O_NONBLOCK when opening. ! fix, pretag.c: pretag_index_report() was reporting incorrect info of the hash structure built for the maps_index feature. Its format was has also changed to be better parseable. ! fix, compile time warnings: several warnings were addressed including but not restricted to -Wformat ones. Also an annotation was added to the Log function to inform the compiler it's a printf-style function, allowing it to give warnings for argument mismatches. - --enable-ipv6 configure script switch has been deprecated and, as a result, IPv6 support was made mandatory. - BGP daemon: removed unused pathlimit field from bgp_attr structure. - pmacct client: removed deprecated SYM field from from formatted and CSV headers. 1.7.2 -- 26-11-2018 + nfacctd, sfacctd: added Kafka broker among the options to receive NetFlow/IPFIX, sFlow data from. Host, port and topic should all be specified along with an optional config file to pass to librdkafka. + nfacctd, sfacctd, pmtelemetryd: added ZeroMQ queue among the options to receive NetFlow/IPFIX, sFlow or Streaming Telemetry data from. An IP address and port should be specified. + nfacctd, sfacctd: added sampling_direction to the set of supported primitives, valid values being ingress, egress and unknown. + nfacctd, sfacctd: stats, ie. amount of NetFlow/IPFIX or sFlow packets received per router, are now available when in tee mode. Stats can be retrieved via a SIGUSR1 UNIX signal. + pcap_savefile_replay: a feature to replay content for the specified amounf of time when reading from a pcap_savefile. + pre_tag_map: added several new keys: src_net and dst_net (to tag on source and destination IP prefixes respectively), bgp_nexthop (to tag on BGP nexthop) and nat_event. + BGP daemon: added bgp_lrgcomm_pattern feature to filter large BGP communities (in addition to existing equivalent knobs to filter on standard and extended communities). + BMP, Streaming Telemetry daemons: msglog_file and dump_file config directives now offer $bmp_router, $bmp_router_port, $telemetry_node and $telemetry_node_port variables. + BGP, BMP, Streaming Telemetry daemons: added BGP, BMP and Streaming Telemetry exporter TCP/UDP port as variable for dump/log filenames (to better support NAT traversal scenarios). + BGP, BMP daemons: added message sequencing to both BGP and BMP dumps (bgp_table_dump_*, bmp_dump_*). If dumping and logging are enabled in parallel then sequencing the dumps allows for check pointing at regular time intervals. + BMP daemon: implemented draft-hsmit-bmp-extensible-routemon-msgs for a tlv-based encoding of route-monitoring messages with a new message type. + Streaming Telemetry daemon: added sample decoders for gRPC / GPB for Cisco and Huawei platforms, written in Python. Telemetry data is decoded using vendor-supplied proto files and output in JSON format in a ZeroMQ queue - suitable for ingestion in pmtelemetryd. Docs and sample code is available in the telemetry/ directory. This is all in addition to TCP/UDP transports and JSON encoding supported natively in pmtelemetryd. + kafka plugin: introduced support for Confluent Schema Registry via libserdes. A registry can be supplied via kafka_avro_schema_registry config directive; the schema is generated automatically. The feature enables validation of data passed through a Kafka broker and uses Avro encoding. + kafka plugin: added $in_iface key (input interface) to the set of variables supported by kafka_partition_key. Extremely useful when coupled to $peer_src_ip in some scenarios. + print, IMT plugins: separator for CSV format can now be space (\s) or tab (\t). + tee plugin: added Kafka broker among the emitters. kafka_broker and kafka_topic knobs are now available in the tee_receivers map and a tee_kafka_config_file directive allows to define a file with config to pass to librdkafka. + tee plugin: added ZeroMQ queue among the emitters. zmq_address knob defines the queue IP address and port to emit to. + tee plugin: introducing support for complex pre_tag_map when doing replication of NetFlow/IPFIX (sFlow replication had already this). With this feature flows are individually evaluated against supplied filters (input interface, BGP next-hop, etc.) and (not) replicated accordingly. + GeoIP v2: added support for latitude and longitude primitives via src_host_coords and dst_host_coords knobs. This is in addition to existing country and pocode supports. + files_uid, files_gid: now also user and group strings are accepted. This is in addition to user and group IDs. ! fix, nfacctd: NF_evaluate_flow_type() improved to not detect Cisco ASA flows (ie. those including initiator and responder octets) as events. Also improved sanity checking of received NetFlow v9/IPFIX data and options templates and reviwed modulo functions and improved template hashing. ! fix, BGP, BMP, Streaming Telemetry daemons: improved log sequencing by handling counter wrap-up more gracefully. Also a log sequencing API was developed to improve code re-use. ! fix, BGP daemon: added check for duplicate Router-IDs at BGP OPEN parsing time. If a duplicate is detected, the session BGP OPENing of the new session is dropped. ! fix, BGP daemon: ADD-PATH capability was checked only in the first AFI/SAFI and was being set in the reply for last AFI/SAFI RECEIVE(1) if first included SEND(2) or SEND-RECEIVE(3). Thanks to Markus Weber ( @FvDxxx ) for his patch. ! fix, BGP daemon: upon route lookup, don't perform ADD-PATH logics if no PATH-ID (even if ADD-PATH capability is announced by the peer). Thanks to Camilo Cardona ( @jccardonar ) for his support solving the issue. ! fix, BGP daemon: graceful handling of invalid AS-PATH segment types (ie. AS-PATH in BGP UPDATE inconsistent with capabilities passed in BGP OPEN) in order to avoid SEGVs. ! fix, pmtelemetryd: improved support for UDP timeouts. Also reviewed natively supported encodings: removed zjson and GPB was moved to pre- processors (with samples available in telemetry/decoders directory). ! fix, pmtelemetryd: no dump_init / dump_close events sequencing since all messages are sequenced anyway (consistency with other daemons). ! fix, kafka_common.c: now destroying both config and topic config as part of p_kafka_close() in order to avoid memory leaks. Also, port is omitted from broker string if not passed to p_kafka_set_broker(). And finally output queue length checks in p_kafka_check_outq_len() have been relaxed (to counter temporary hickups that need more patience). ! fix, kafka plugin: kafka_partition default was zero (that is, a valid partition number) instead of -1 (RD_KAFKA_PARTITION_UA or unassigned) which allows librdkafka to attach a partitioner. ! fix, SQL plugins: sql_table_schema is honoured even if sql_table_name is non-dynamic. This is to cover cases where the table is rotated externally. ! fix, mysql plugin: my_bool replaced with bool. The plugin now does compile against MySQL 8.0. Also added inclusion of stdbool.h as on some systems bool is not defined. Improved overall probing for MySQL headers. ! fix, pgsql plugin: sql_recovery_backup_host was not being honoured. PG_create_backend() now composes a proper conn_string. ! fix, print plugin: increase successful queries number, QN, only if the output file was successfully opened. ! fix, zmq_common.c: moved ZAP socket initialization inside the ZAP handler. See: https://github.com/zeromq/libzmq/issues/3313 . ! fix, util.c: length checks in handle_dynname_internal_strings() were reviewed. Existings were not working in absence of starting/trailing non-variable strings. ! fix, util.c: use lockf() instead of more problematic flock(). Thanks to Yuri Lachin ( @yuyutime ) and Miki Takata ( @mikiT ) for their support. ! fix, util.c: in compose_timestamp() pad usecs and use "%ld" since time fields are signed longs. Thanks to @raymondrussell for the patch. ! fix, ndpi_util.c: a protocol bitmask is now set in order to increase match rate. Patch is courtesy by @rsolsn. ! fix, compile time warnings: several warnings were addressed including but not restricted to -Wreturn-time, -Wunused-variable, implicit func declarations, -Wformat-extra-args, -Wunused-label, -Wunused-value, -Wunused-function, sbrk calls, -Wpointer-to-int-cast, -Wparentheses and -Wint-to-pointer-cast. ! fix, dangerous uninitialized values: net_aggr.c, pmacct.c: in merge() argument with non-NULL attribute could be passed NULL; bmp_msg.c: in bmp_process_msg_route_monitor() bdata.tstamp could be uninitialized; sfprobe_plugin.c: calloc() return value (possibly null) was not being checked; sflow_agent.c: uninitialized ret value in sfl_agent_init() could lead to undefined bind() error behaviour. ! fix, thread_pool.c: reviewed logics in deallocate_thread_pool() and solved a minor memory leak in allocate_thread_pool(). - pmacctd: removed support for FDDI :) - nfacctd: discontinued support for NetFlow v1, v7 and v8 collection and replication. - pre_tag_map: matching on 'sampling_rate' is not supported anymore as a sampling_rate primitive is now available; the 'return' feature to return matched data before completing the map workflow has started being obsoleted (retired from docs but still available). - plugin_pipe_check_core_pid: deprecating feature given RabbitMQ and Kafka are not supported anymore for internal message delivery. - tee plugin: obsoleted tee_dissect_send_full_pkt knob, entire packets are now replicated only if no pre_tag_map or a simple pre_tag_map is defined. - nfprobe plugin: removed support for NetFlow v1 export. 1.7.1 -- 06-05-2018 + pmbgpd: introduced a BGP x-connect feature meant to map BGP peers (ie. PE routers) to BGP collectors (ie. nfacctd, sfacctd) via a standalone BGP daemon (pmbgpd). The aim is to facilitate operations when re-sizing/re-balancing the collection infrastructure without impacting (ie. re-configuring) BGP peers. bgp_daemon_xconnect_map expects full pathname to a file where cross-connects are defined; mapping works only against the IP source address and not the BGP Router ID, only 1:1 relationships can be formed (ie. this is about cross-connecting, not replication) and only one session per BGP peer is supported (ie. multiple BGP agents are running on the same IP address or NAT traversal scenarios are not supported [yet]). A sample map is provided in 'examples/bgp_xconnects.map.example'. + pmbgpd: introduced a BGP Looking Glass server allowing to perform queries, ie. lookup of IP addresses/prefixes or get the list of BGP peers, against available BGP RIBs. The server is asyncronous and uses ZeroMQ as transport layer to serve incoming queries. Sample C/Python LG clients are available in 'examples/lg'. A sample LG server config is available in QUICKSTART. Request/Reply Looking Glass formats are documented in 'docs/LOOKING_GLASS_FORMAT'. + pmacctd: a single daemon can now listen for traffic on multiple interfaces via a polling mechanism. This can be configured via a pcap_interfaces_map feature (interface/pcap_interface can still be used for backward compatiblity to listen on a single interface). The map allows to define also ifindex mapping and capturing direction on a per-interface basis. The map can be reloaded at runtime via a USR2 signal and a sample map is in examples/pcap_interfaces.map.example. + Kafka plugin: dynamic partitioning via kafka_partition_dynamic and kafka_partition_key knobs is introduced. The Kafka topic can contain variables, ie. $peer_src_ip, $src_host, $dst_port, $tag, etc., which are all computed when data is purged to the backend. This feature is in addition to the existing kafka_partition feature which allows to rely on the built-in Kafka partitioning to assign data statically to one partition or rely dynamically on the default partitioner. The feature is courtesy by Corentin Neau / Codethink ( @weyfonk ). + Introduced rfc3339 formatted timestamps: in logs, ie. UTC timezone represented as yyyy-MM-ddTHH:mm:ss(.ss)Z; for aggregation primitives the timestamps_rfc3339 knob can be used to enable this feature (left disabled by default for backward compatibility). + timestamps_utc: new knob to decode timestamps to UTC timezone even if the Operating System is set to a different timezone. On the goods of running a system set to UTC please read Q18 of FAQS. + sfacctd: implemented mpls_label_top, mpls_label_bottom and mpls_stack_depth primitives decoded from sFlow flow sample headers. Thanks to David Barroso ( @dbarrosop ) for his support. + nfacctd: added support for IEs 130 (exporterIPv4Address) and 131 (exporterIPv6Address) when passed as part of NetFlow v9/IPFIX option packets (these IEs were already supported when passed in flow data). Also added support for IE 351 (dataLinkFrameSection) which carries the initial portion of a sampled raw packet headers (a-la sFlow). This was tested working against a Cisco NCS 5k platform. + nfprobe plugin: added a new nfprobe_dont_cache knob allowing to disable caching and summarisation of flows (essentially letting the NetFlow/IPFIX probe behave like a sFlow probe). + nfprobe plugin: added support for MPLS_LABEL_1, NetFlow v9/IPFIX IE 70; improved support for BGP next-hop IE 18 and 63. Also support for IE 130/131 vi NetFlow v9/IPFIX Options was added. + sfprobe plugin: added sfprobe_source_ip knob to define the local IP address from which sFlow datagrams are exported; improved support for BGP next-hop. + nfacctd, sfacctd, BGP, BMP, Streaming Telemetry daemons: on Linux, if supported, use SO_REUSEPORT for the listening socket (added to existing SO_REUSEADDR option). + nfacctd, sfacctd: introduced new 'export_proto_sysid' primitive to give visibility to NetFlow v5/v8 engine_id / NetFlow v9 source ID / IPFIX Obs Domain ID / sFlow agentSubID. + nfacctd, sfacctd: extended nDPI support to NetFlow v9/IPFIX packets with IE 315 (dataLinkFrameSection) and sFlow v5 packets with header section. + nfacctd, sfacctd: extended custom primitives definition framework, aggregate_primitives, to NetFlow v9/IPFIX packets with IE 315 (dataLinkFrameSection) and sFlow v5 sampled headers section. + nfacctd, sfacctd: added per-collector packets and bytes counts to stats emitted via SIGUSR1. Also the output was made more formal (so to be more easily parsed) and is documented in the UPGRADE notes. + nfacctd, pmacctd, sfacctd: pcap_savefile_delay feature introduced to sleep for the supplied amount of seconds before playing a given pcap_savefile. Useful, for example, to let BGP/BMP sessions come up so that routing data is available for correlation when processing data in the trace. + Kafka plugin: configuring statistics.interval.ms to a positive value in a kafka_config_file makes now librdkafka log plenty of internal metrics. + BGP daemon: added support for Extended BGP Administrative Shutdown Communication (draft-snijders-idr-rfc8203bis-00). + BMP daemon: added support for draft-ietf-grow-bmp-adj-rib-out-01 and draft-ietf-grow-bmp-loc-rib-01. As a result of that, Route Monitor log messages now contain indication of is_out and is_filtered. + BMP daemon: added support for stats reports 9, 10, 11, 12 and 13 and descriptions for the different Peer Types and and Peer Down reasons. Finally, indication of is_post is now making to Route Monitor log messages. + plugin_pipe_zmq: introduced plugin_pipe_zmq_hwm (high water mark) knob to control the maximum amount of messages than can be stored in the ZeroMQ queue. + [ns]facctd_allow_file: the map is now made reloadable at runtime via SIGUSR2 and accepts IPv4/IPv6 prefixes increasing its scale (before it was only accepting individual IP addresses). + pmacctd: added support for IPv6, MPLS for DLT_LINUX_SLL captures. Thanks to David Barroso ( @dbarrosop ) for his support. + uacctd: added a global 'direction' knob to give visibility of data capturing direction, ie. in/out. Useful for pre_tag_map use. + MySQL plugin: added sql_port knob in order to specify non-default ports for connecting to the database. Patch is courtesy by Vadim Tkachenko ( @vadimtk ). ! fix, plugins: getppid() parent process health check improved so to work in Docker environments not assuming anymore parent PID is 1. Patch is courtesy by Hidde van der Heide ( @hvanderheide ). ! fix, plugins: imposing a budget for received messages (100) so to preserve fairness of other operations (ie. time keeping, bucketing, reloading maps, etc.) and prevent starvations. ! fix, plugins: retry when zmq_getsockopt() for ZMQ_EVENTS returns EINTR. Thanks to Wouter de Jong for his support solving the issue. ! fix, plugins: when executing triggers, the first argument passed to execv() should be the path to the invoked executable to prevent execv(3) to fail and return EFAULT on OpenBSD. Patch is courtesy by @higgsd. ! fix, BGP daemon: improved support of multiple capabilities per optional parameter in the OPEN message. Also add-path capability is now advertised if neighbor supports send/receive (previously it was sent back on send only) of such capability. Thanks to Radu Anghel ( @cozonac ) for his support. ! fix, BGP daemon: upon route lookup, don't perform ADD-PATH logics if no PATH-ID (even if ADD-PATH capability is announced by the peer). Thanks to Camilo Cardona ( @jccardonar ) for his support solving the issue. ! fix, BGP daemon: wrong type 2 32-bit ASN Route Distinguisher was defined in network.h. Thanks to Thomas Graf for reporting the issue. ! fix, BGP, BMP daemons: lookup of BGP-LU entries is now performed against the correct RIB. ! fix, BMP daemon: the BMP thread is now made mutually exclusive with the BGP one (until an use-case needs to run them both). This is to potentially prevent BGP and BMP information to interfere with each other when correlated. Also the 'bmp' keyword was added for *_as and *_net config directives (ie. nfacctd_as, nfacctd_net). Thanks to Juan Camilo Cardona ( @jccardonar ) for his support. ! fix, BMP daemon: improved correlation of BMP data with traffic data by supporting a replication use-case (the BMP exporter is a route -server rather than an actual Edge Router) upon lookup. Thanks to Juan Camilo Cardona ( @jccardonar ) for his support. ! fix, BMP daemon: in bgp_peer_cmp() and bgp_peer_host_addr_cmp() the comparison function has been changed from generic memcmp() to a more specific host_addr_cmp() as paddings were giving issues. Thanks to Juan Camilo Cardona ( @jccardonar ) for reporting the issue. ! fix, BMP daemon: a pm_tdestroy call in bmp_peer_close() was leading to SEGV under certain conditions by not NULL'ing all pointers. Thanks to Juan Camilo Cardona ( @jccardonar ) for reporting the issue. ! fix, nfacctd: prevent time calculations to underflow in cases in which sysUptime < first or last flow switched timestamps in NetFlow v5. Patch is courtesy by David Steinn Geirsson ( @dsgwork ). ! fix, nfacctd: in the context of aggregate_primitives, now enforcing terminating the zero when decoding variable-length IEs when applying string semantics. ! fix, nfprobe: changed ifIndex fields from u_int16_t to u_int32_t in order to prevent overflows and aligning to the rest of structs. ! fix, MySQL plugin: minor code revisions to restore compiling against MariaDB 10.2. ! fix, sql_common.c: increased read_SQLquery_from_file() buffer size so that sql_table_schema can be fed with longer CREATE TABLE statements. ! fix, print, SQL plugins: post_tag, post_tag2 support was added to sql_table and print_output_file. Also for Kafka, RabbitMQ plugins kafka_topic and amqp_routing_key variables support was harmonized with print and SQL plugins (ie. $pre_tag renamed to $tag), see UPGRADE notes. ! fix, SQL plugins: sql_startup_delay was not being honored when sql_trigger_exec was defined without a sql_trigger_time resulting in empty environment variables being passed to the triggered script. Thanks to Johannes Maybaum for his support resolving the issue. ! fix, pkt_handlers.c: tmp_asa_bi_flow value was ignored when applied to a specific plugin. ! fix, util.c: when data timestamp is not available, dynamic file and table names variables were populated with a 1-Jan-1970 date. Now the current timestamp is used instead as last resort. Patch is courtesy by Ivan F. Martinez ( @ivanfmartinez ). ! fix, addr.c: host_addr_mask_sa_cmp() and str_to_addr_mask() network mask computation for IPv6 addresses was wrong. allow_file feature was affected. ! fix, build system: several patches committed to the build system to simplify libraries probing, make sure to bail out upon error. Also now a minimum required version is imposed to almost all libraries. - --enable-threads / --disable-threads: removed the configure switch that was allowing to compile pmacct even when no pthreads library was available on a system. From now on support for threads is mandatory. - BGP daemon: offline code, ie. bgp_daemon_offline_* config directives, has been deprecated in favor of other approaches, ie. BGP Looking Glass and BGP Xconnects. - pkt_len_distrib: the primitive, which was meant to bucket packet / flow / sample lengths in a distribution has been obsoleted. 1.7.0 -- 21-10-2017 + ZeroMQ integration: by defining plugin_pipe_zmq to 'true', ZeroMQ is used for queueing between the Core Process and plugins. This is in alternative to the home-grown circular queue implementation (ie. plugin_pipe_size). plugin_pipe_zmq_profile can be set to one value of { micro, small, medium, large, xlarge } and allows to select among a few standard buffering profiles without having to fiddle with plugin_buffer_size. How to compile, install and operate ZeroMQ is documented in the "Internal buffering and queueing" section of the QUICKSTART document. + nDPI integration: enables packet classification, replacing existing L7-layer project integration, and is available for pmacctd and uacctd. The feature, once nDPI is compiled in, is simply enabled by specifying 'class' as part of the aggregation method. How to compile install and operate nDPI is documented in the "Quickstart guide to packet classification" section of the QUICKSTART document. + nfacctd: introduced nfacctd_templates_file so that NetFlow v9/IPFIX templates can be cached to disk to limit the amount of lost packets due to unknown templates when nfacctd (re)starts. The implementation is courtesy by Codethink Ltd. + nfacctd: introduced support for PEN on IPFIX option templates. This is in addition to already supported PEN for data templates. Thanks to Gilad Zamoshinski ( @zamog ) for his support. + sfacctd: introduced new aggregation primitives (tunnel_src_host, tunnel_dst_host, tunnel_proto, tunnel_tos) to support inner L3 layers. Thanks to Kaname Nishizuka ( @__kaname__ ) for his support. + nfacctd, sfacctd: pcap_savefile and pcap_savefile_wait were ported from pmacctd. They allow to process NetFlow/IPFIX and sFlow data from previously captured packets; these also ease some debugging by not having to resort anymore to tcpreplay for most cases. + pmacctd, sfacctd: nfacctd_time_new feature has been ported so, when historical accounting is enabled, to allow to choose among capture time and time of receipt at the collector for time-binning. + nfacctd: added support for NetFlow v9/IPFIX field types #130/#131, respectively the IPv4/IPv6 address of the element exporter. + nfacctd: introduced nfacctd_disable_opt_scope_check: mainly a work around to implementations not encoding NetFlow v9/IPIFX option scope correctly, this knob allows to disable option scope checking. Thanks to Gilad Zamoshinski ( @zamog ) for his support. + pre_tag_map: added 'source_id' key for tagging on NetFlow v9/IPFIX source_id field. Added also 'fwdstatus' for tagging on NetFlow v9/ IPFIX information element #89: this implementation is courtesy by Emil Palm ( @mrevilme ). + tee plugin: tagging is now possible on NetFlow v5-v8 engine_type/ engine_id, NetFlow v9/IPFIX source_id and sFlow AgentId. + tee plugin: added support for 'src_port' in tee_receivers map. When in non-transparent replication mode, use the specified UDP port to send data to receiver(s). This is in addition to tee_source_ip, which allows to set a configured IP address as source. + networks_no_mask_if_zero: a new knob so that IP prefixes with zero mask - that is, unknown ones or those hitting a default route - are not masked. The feature applies to *_net aggregation primitives and makes sure individual IP addresses belonging to unknown IP prefixes are not zeroed out. + networks_file: hooked up networks_file_no_lpm feature to peer and origin ASNs and (BGP) next-hop fields. + pmacctd: added support for calling pcap_set_protocol() if supported by libpcap. Patch is courtesy by Lennert Buytenhek ( @buytenh ). + pmbgpd, pmbmpd, pmtelemetryd: added a few CL options to ease output of BGP, BMP and Streaming Telemetry data, for example: -o supplies a b[gm]p_daemon_msglog_file, -O supplies a b[gm]p_dump_file and -i supplies b[gm]p_dump_refresh_time. + kafka plugin: in the examples section, added a Kafka consumer script using the performing confluent-kafka-python module. ! fix, BGP daemon: segfault with add-path enabled peers as per issue #128. Patch is courtesy by Markus Weber ( @FvDxxx ). ! fix, print plugin: do not update link to latest file if cause of purging is a safe action (ie. cache space is finished. Thanks to Camilo Cardona ( @jccardonar ) for reporting the issue. Also, for the same reason, do not execute triggers (ie. print_trigger_exec). ! fix, nfacctd: improved IP protocol check in NF_evaluate_flow_type() A missing length check was causing, under certain conditions, some flows to be marked as IPv6. Many thanks to Yann Belin for his support resolving the issue. ! fix, print and SQL plugins: optimized the cases when the dynamic filename/table has to be re-evaluated. This results in purge speed gains when the dynamic part is time-related and nfacctd_time_new is set to true. ! fix, bgp_daemon_md5_file: if the server socket is AF_INET and the compared peer address in MD5 file is AF_INET6 (v4-mapped v6), pass it through ipv4_mapped_to_ipv4(). Also if the server socket is AF_INET6 and the compared peer addess in MD5 file is AF_INET, pass it through ipv4_to_ipv4_mapped(). Thanks to Paul Mabey for reporting the issue. ! fix, nfacctd: improved length checks in resolve_vlen_template() to prevent SEGVs. Thanks to Josh Suhr and Levi Mason for their support. ! fix, nfacctd: flow stitching, improved flow end time checks. Thanks to Fabio Bindi ( @FabioLiv ) for his support resolving the issue. ! fix, amqp_common.c: amqp_persistent_msg now declares the RabbitMQ exchange as durable in addition to marking messages as persistent; this is related to issue #148. ! fix, nfacctd: added flowset count check to existing length checks for NetFlow v9/IPFIX datagrams. This is to avoid logs flooding in case of padding. Thanks to Steffen Plotner for reporting the issue. ! fix, BGP daemon: when dumping BGP data at regular time intervals, dump_close message contained wrongly formatted timestamp. Thanks to Yuri Lachin for reporting the issue. ! fix, MySQL plugin: if --enable-ipv6 and sql_num_hosts set to true, use INET6_ATON for both v4 and v6 addresses. Thanks to Guy Lowe ( @gunkaaa ) for reporting the issue and his support resolving it. ! fix, 'flows' primitive: it has been wired to sFlow so to count Flow Samples received. This is to support Q21 in FAQS document. ! fix, BGP daemon: Extended Communities value was printed with %d (signed) format string instead of %u (unsigned), causing issue on large values. ! fix, aggregate_primitives: improved support of 'u_int' semantics for 8 bytes integers. This is in addition to already supported 1, 2 and 4 bytes integers. ! fix, pidfile: pidfile created by plugin processes was not removed. Thanks to Yuri Lachin for reporting the issue. ! fix, print plugin: checking non-null file descriptor before setvbuf in order to prevent SEGV. Similar checks were added to prevent nulls be input to libavro calls when Apache Avro output is selected. ! fix, SQL plugins: MPLS aggregation primitives were not correctly activated in case sql_optimize_clauses was set to false. ! fix, building system: reviewed minimum requirement for libraries, removed unused m4 macros, split features in plugins (ie. MySQL) and supports (ie. JSON). ! fix, sql_history: it now correctly honors periods expressed is 's' seconds. ! fix, BGP daemon: rewritten bgp_peer_print() to be thread safe. ! fix, pretag.h: addressed compiler warning on 32-bit architectures, integer constant is too large for "long" type. Thanks to Stephen Clark ( @sclark46 ) for reporting the issue. - MongoDB plugin: it is being discontinued since the old Mongo API is not supported anymore and there has never been enough push from the community to transition to the new/current API (which would require a rewrite of most of the plugin). In this phase-1 the existing MongoDB plugin is still available using 'plugins: mongodb_legacy' in the configuration. - Packet classification basing on the L7-filter project is being discontinued (ie. 'classifiers' directive). This is being replaced by an implementation basing on the nDPI project. As part of this also the sql_aggressive_classification knob has been discontinued. - tee_receiver was part of the original implementation of the tee plugin, allowing to forward to a single target and hence requiring multiple plugins instantiated, one per target. Since 0.14.3 this directive was effectively outdated by tee_receivers. - tmp_net_own_field: the knob has been discontinued and was allowing to revert to backward compatible behaviour of IP prefixes (ie. src_net) being written in the same field as IP addresses (ie. src_host). - tmp_comms_same_field: the knob has been discontinued and was allowing to revert to backward compatible behaviour of BGP communities (standard and extended) being writeen all in the same field. - plugin_pipe_amqp and plugin_pipe_kafka features were meant as an alternative to the homegrown queue solution for internal messaging, ie. passing data from the Core Process to Plugins, and are being discontinued. They are being replaced by a new implementation, plugin_pipe_zmq, basing on ZeroMQ. - plugin_pipe_backlog was allowing to keep an artificial backlog of data in the Core Process so to maximise bypass poll() syscalls in plugins. If home-grown queueing is found limiting, instead of falling back to such strategies, ZeroMQ queueing should be used. - pmacctd: deprecated support for legacy link layers: FDDI, Token Ring and HDLC. 1.6.2 -- 21-04-2017 + BGP, BMP daemons: introduced support for BGP Large Communities IETF draft (draft-ietf-idr-large-community). Large Communities are stored in a variable-length field. Thanks to Job Snijders ( @job ) for his support. + BGP daemon: implemented draft-ietf-idr-shutdown. The draft defines a mechanism to transmit a short freeform UTF-8 message as part of a Cease NOTIFICATION message to inform the peer why the BGP session is being shutdown or reset. Thanks to Job Snijders ( @job ) for his support. + tee plugin, pre_tag_map: introduced support for inspetion of specific flow primitives and selective replication over them. The primitives supported are: input and output interfaces, source and destination MAC addresses, VLAN ID. The feature is now limited to sFlow v5 only. Thanks to Nick Hilliard and Barry O'Donovan for their support. + Added src_host_pocode and dst_host_pocode primitives, pocode being a compact and (de-)aggregatable (easy to identify districts, cities, metro areas, etc.) geographical representation, based on the Maxmind v2 City Database. Thanks to Jerred Horsman for his support. + Kafka support: introduced support for user-defined (librdkafka) config file via the new *_kafka_config_file config directives. Full pathname to a file containing directives to configure librdkafka is expected. All knobs whose values are string, integer, boolean are supported. + AMQP, Kafka plugins: introduced new directives kafka_avro_schema_topic, amqp_avro_schema_routing_key to transmit Apache Avro schemas at regular time intervals. The routing key/topic can overlap with the one used to send actual data. + AMQP, Kafka plugins: introduced support for start/stop markers when encoding is set to Avro (ie. 'kafka_output: avro'); also Avro schema is now embedded in a JSON envelope when sending it via a topic/routing key (ie. kafka_avro_schema_topic). + print plugin: introduced new config directive avro_schema_output_file to save the Apache Avro schema in a separate file (it was only possible to have it combined at the beginning of the data file). + BGP daemon: introduced a new bgp_daemon_as config directive to set a LocalAS which could be different from the remote peer one. This is to establish an eBGP session instead of a iBGP one (default). + flow_to_rd_map: introduced support for mpls_vpn_id. In NetFlow/IPFIX this is compared against Field Types #234 and #235. + sfacctd: introduced support for sFlow v2/v4 counter samples (generic, ethernet, vlan). This is in addition to existing support for sFlow v5 counters. + BGP, BMP and Streming Telemetry daemons: added writer_id field when writing to Kafka and/or RabbitMQ. The field reports the configured core_proc_name and the actual PID of the writer process (so, while being able to correlate writes to the same daemon, it's also possible to distinguish among overlapping writes). + amqp, kafka, print plugins: harmonized JSON output to the above: added event_type field, writer_id field with plugin name and PID. + BGP, BMP daemons: added AFI, SAFI information to log and dump outputs; also show VPN Label if SAFI is MPLS VPN. + pmbgpd, pmbmpd: added logics to bypass building RIBs if only logging BGP/BMP data real-time. + BMP daemon: added BMP peer TCP port to log and dump outputs (for NAT traversal scenarios). Contextually, multiple TCP sessions per IP are now supported for the same reason. + SQL plugins: ported (from print, etc. plugins) the 1.6.1 re-working of the max_writers feature. + uacctd: use current time when we don't have a timestamp from netlink. We only get a timestamp when there is a timestamp in the skb. Notably, locally generated packets don't get a timestamp. The patch is courtesy by Vincent Bernat ( @vincentbernat ). + build system: added configure options for partial linking of binaries with any selection/combination of IPv4/IPv6 accounting daemons, BGP daemon, BMP daemon and Streaming Telemetry daemon possible. By default all are compiled in. + BMP daemon: internal code changes to pass additional info from BMP per-peer header to bgp_parse_update_msg(). Goal is to expose further info, ie. pre- vs post- policy, when logging or dumping BMP info. ! fix, BGP daemon: introduced parsing of IPv6 MPLS VPN (vpnv6) NLRIs. Thanks to Alberto Santos ( @m4ccbr ) for reporting the issue. ! fix, BGP daemon: upon doing routes lookup, now correctly honouring the case of BGP-LU (SAFI_MPLS_LABEL). ! fix, BGP daemon: send BGP NOTIFICATION out in case of known failures in bgp_parse_msg(). ! fix, kafka_partition, *_kafka_partition: default value changed from 0 (partition zero) to -1 (RD_KAFKA_PARTITION_UA, partition unassigned). Thanks to Johan van den Dorpe ( @johanek ) for his support. ! fix, pre_tag_map: removed constraint for 'ip' keyword for nfacctd and sfacctd maps. While this is equivalent syntax to specifying rules with 'ip=0.0.0.0/0', it allows for map indexing (maps_index: true). ! fix, bgp_agent_map: improved sanity check against bgp_ip for IPv6 addresses (ie. an issue appeared for the case of '::1' where the first 64 bits are zeroed out). Thanks to Charlie Smurthwaite ( @catphish ) for reporting the issue. ! fix, maps_index: indexing now correctly works for IPv6 pre_tag_map entries. That is, those where 'ip', the IP address of the NetFlow/ IPFIX/sFlow exporter, is an IPv6 address. ! fix, pre_tag_map: if mpls_vpn_rd matching condition is specified and maps_index is enabled, PT_map_index_fdata_mpls_vpn_rd_handler() now picks the right (and expected) info. ! fix, pkt_handlers.c: improved definition and condition to free() in bgp_ext_handler() in order to prevent SEGVs. Thanks to Paul Mabey for his support. ! fix, kafka_common.c: removed waiting time from p_kafka_set_topic(). Added docs advicing to create in advance Kafka topics. ! fix, sfacctd, sfprobe: tag and tag2 are now correctly re-defined as 64 bits long. ! fix, sfprobe plugin, sfacctd: tags and class primitives are now being encoded/decoded using enterprise #43874, legit, instead of #8800, that was squatted back in the times. See issue #71 on GiHub for more info. ! fix, sfacctd: lengthCheck() + skipBytes() were producing an incorrect jump in case of unknown flow samples. Replaced by skipBytesAndCheck(). Thanks to Elisa Jasinska ( @fooelisa ) for her support. ! fix, pretag_handlers.c: in bgp_agent_map added case for 'vlan and ...' filter values. ! fix, BGP daemon: multiple issues of partial visibility of the stored RIBs and SEGVs when bgp_table_per_peer_buckets was not left default: don't mess with bms->table_per_peer_buckets given the multi-threaded scenario. Thanks to Dan Berger ( @dfberger ) for his support. ! fix, BGP, BMP daemons: bgp_process_withdraw() function init aligned to bgp_process_update() in order to prevent SEGVs. Thanks to Yuri Lachin for his support. ! fix, bgp_msg.c: Route Distinguisher was stored and printed incorrectly when of type RD_TYPE_IP. Thanks to Alberto Santos ( @m4ccbr ) for reporting the issue. ! fix, bgp_logdump.c: p_kafka_set_topic() was being wrongly applied to an amqp_host structure (instead of a kafka_host structure). Thanks to Corentin Neau ( @weyfonk ) for reporting the issue. ! fix, BGP daemon: improved BGP next-hop setting and comparison in cases of MP_REACH_NLRI and MPLS VPNs. Many thanks to both Catalin Petrescu ( @cpmarvin ) and Alberto Santos ( @m4ccbr ) for their support. ! fix, pmbgpd, pmbmpd: pidfile was not written even if configured. Thanks to Aaron Glenn ( @aaglenn ) for reporting the issue. ! fix, tee plugin: tee_max_receiver_pools is now correctly honoured and debug message shows the replicatd protocol, ie. NetFlow/IPFIX vs sFlow. ! AMQP, Kafka plugins: separate JSON objects, newline separated, are preferred to JSON arrays when buffering of output is enabled (ie. kafka_multi_values) and output is set to JSON. This is due to quicker serialisation performance shown by the Jansson library. ! build system: switched to enable IPv6 support by default (while the --disable-ipv6 knob can be used to reverse the behaviour). Patch is courtesy by Elisa Jasinska ( @fooelisa ). ! build system: given visibility, ie. via -V CL option, into compile options enabled by default (ie. IPv6, threads, 64bit counters, etc.). ! fix, nfprobe: free expired records when exporting to an unavailable collector in order to prevent a memory leak. Patch is courtersy by Vladimir Kunschikov ( @kunschikov ). ! fix, AMQP plugin: set content type to binary in case of Apache Avro output. ! fix, AMQP, Kafka plugins: optimized amqp_avro_schema_routing_key and kafka_avro_schema_topic. Avro schema is built only once at startup. ! fix, cfg.c: improved parsing of config key-values where squared brakets appear in the value part. Thanks to Brad Hein ( @regulatre ) for reporting the issue. Also, detection of duplicates among plugin and core process names was improved. ! fix, misc: compiler warnings: fix up missing includes and prototypes; the patch is courtesy by Tim LaBerge ( @tlaberge ). ! kafka_consumer.py, amqp_receiver.py: Kafka, RabbitMQ consumer example scripts have been greatly expanded to support posting to a REST API or to a new Kafka topic, including some stats. Also conversion of multiple newline-separated JSON objects to a JSON array has been added. Misc bugs were fixed. 1.6.1 -- 31-10-2016 + Introduced pmbgpd daemon: a stand-alone BGP collector daemon; acts as a passive neighbor and maintains per-peer RIBs; can log real-time and/or dump at regular time-intervals BGP data to configured backends. + Introduced pmbmpd daemon: a stand-alone BMP collector daemon; can log real-time and/or dump at regular time-intervals BMP and BGP data to configured backends. + Introduced Apache Avro as part of print, AMQP and Kafka output: Apache Avro is a data serialization system providing rich data structures, a compact, fast, binary data format, a container file to store persistent data, remote procedure call (RPC) and simple integration with dynamic languages. The implementation is courtesy by Codethink Ltd. + as_path, std_comm and ext_comm primitives: along with their src counter parts, ie. src_as_path etc., have been re-worked to a variagle-length internal representation which will lead, when using BGP primitives, to memory savings of up to 50% compared to previous releases. + std_comm, ext_comm primitives: primitives are de-coupled so that they are not multiplexed anymore in the same field, on output. Added a tmp_comms_same_field config directive for backward compatibility. + nfacctd: added support for repeated NetFlow v9/IPFIX field types. Also flowStartDeltaMicroseconds (IE #158) and flowEndDeltaMicroseconds (#159) are now supported for timestamping. + kafka plugin: it is now possible to specify -1 (RD_KAFKA_RTITION_UA) as part of the kafka_partition config directive. Also, introduced support for Kafka partition keys via kafka_partition_key and equivalent config directives. + kafka plugin: kafka_broker_host directive now allows to specify multiple brokers, ie. "broker1:10000,broker2". The feature relies on capabilities of underlying rd_kafka_brokers_add(). + tee, nfprobe, sfprobe plugins: introduced Kafka support for internal pipe and buffering, ie. plugin_pipe_kafka. This is in addition to the existing support for homegrown internal buffering and RabbitMQ. + tee plugin: introduced support for variable-length buffers which reduces CPU utilization. + print, MongoDB, AMQP and Kafka plugins: re-worked max_writers feature to not rely anymore on waitpid() inside signal handlers as it was failing on some OS versions (and could not be reproduced on others). Thanks to Janet Sullivan for her support. + bgp_follow_nexthop_external: introduced feature to return, when true, the next-hop from the routing table of the last node part of the supplied IP prefix(es) as value for the 'peer_ip_dst' primitive. When false, default, it returns the IP address of the last node part of the bgp_follow_nexthop config key. + pmtelemetryd: added initial support for GPB. Input GPB data is currently base64'd in the telemetry_data field of the daemon output JSON object. + pmtelemetryd: Added telemetry statistics. For each peer, track the number of packets received, how many bytes are pulled off the wire, and the resulting message payload. Dump these counts in logdump. Patch is courtesy by Tim LaBerge. + amqp_markers, kafka_markers: added start/end markers feature to AMQP and Kafka plugins output same as for the print plugin (print_markers). + pre_tag_map: 'direction' keyword now applies to sFlow too: it does expect values 0 (ingress direction) or 1 (egress direction), just like before. In sFlow v2/v4/v5 this returns a positive match if: 1) source_id equals to input interface and this 'direction' key is set to '0' or 2) source_id equals to output interface and this 'direction' key is set to '1'. + bgp_agent_map: introduced support for input and output interfaces. This is relevant to VPN scenarios. + tmp_asa_bi_flow hack: bi-flows use two counters to report counters, ie. bytes and packets, in forward and reverse directions. This hack (ab)uses the packets field in order to store the extra bytes counter. ! fix, nfacctd: debugging NetFlow v9/IPFIX templates, added original field type number to the output when the field is known and its description is presented. ! fix, Jansson: added JSON_PRESERVE_ORDER flag to json_dumps() to give output consistency across runs. ! fix, kafka_common.c: added rd_kafka_message_destroy() to p_kafka_consume_ _data() to prevent memory leaks. Thanks to Paul Mabey for his support solving the issue. ! fix, kafka_common.c: p_kafka_set_topic() now gives it some time for the topic to get (auto) created, if needed. ! fix, print plugin: improved check for when to print table title (csv, formatted). Either 1) print_output_file_append is set to false or 2) print_output_file_append is set to true and file is to be created. ! fix, print_markers: start marker is now printed also in the case where print_output_file_append is set to true. Also, markers are now printed as a JSON object, if output is set to JSON. ! fix, pkt_handlers.c: removed l3_proto checks from NF_peer_dst_ip_handler() for cases where a v6 flows has a v4 BGP next-hop (ie. vpnv6) ! fix, pre_tag_map: removed 32 chars length limit from set_label statement. ! fix, custom primitives: names are now interpreted as case-insensitive. Patch is courtesy by Corentin Neau. ! fix, BGP, BMP and Streaming Telemetry: if reopening [bgp, bmp, telemetry]_ daemon_msglog_file via SIGHUP, reset reload flag. ! fix, BGP, BMP and Streaming Telemetry: removed gettimeofday() from bgp_ peer_dump_init() and bgp_peer_dump_close() in order to maintain a single timestamp for a full dump event. Thanks to Tim LaBerge for his support. ! fix, BGP, BMP and Streaming Telemetry: output log and dump messages went through a general review to improve information consistency and usability. Message formats are now documented in docs/MSGLOG_DUMP_FORMATS so to more easily track future changes. ! fix, pmtelemetryd: avoiding un-necessary spawn of a default plugin if none is defined. ! fix, pmtelemetryd: Mask SIGCHLD during socket IO. If we happen to be blocked in recv() while a log dump happens, recv() will fail with EINTR. This is to mask SIGCHLD during socket IO and restores the original mask after the IO completes. Patch is courtesy by Tim LaBerge. ! fix, build system: misc improvements made to the build system introduced in 1.6.0. Thanks to Vincent Bernat for his support in this area. ! fix, compiler warnings: ongoing effort to suppress warning messages when compiling. Thanks to Tim LaBerge, Matin Mitchell for their contributions. 1.6.0 -- 07-06-2016 + Streaming telemetry daemon: quoting Cisco IOS-XR Telemetry Configuration Guide at the time of this writing: "Streaming telemetry [ .. ] data can be used for analysis and troubleshooting purposes to maintain the health of the network. This is achieved by leveraging the capabilities of machine-to-machine communication. [ .. ]" Streming telemetry support comes in two flavours: 1) a telemetry thread can be started in existing daemons, ie. sFlow, NetFlow/IPFIX, etc. for the purpose of data correlation and 2) a new daemon pmtelemetryd for standalone consumpton of data. Streaming network telemetry data can be logged real-time and/or dumped at regular time intervals to flat-files, RabbitMQ or Kafka brokers. + BMP daemon: introduced support for Route Monitoring messages. RM messages "provide an initial dump of all routes received from a peer as well as an ongoing mechanism that sends the incremental routes advertised and withdrawn by a peer to the monitoring station". Like for BMP events, RM messages can be logged real-time and/or dumped at regular time intervals to flat-files, RabbiMQ and Kafka brokers. RM messages are also saved in a RIB structure for IP prefix lookup. + uacctd: ULOG support switched to NFLOG, the newer and L3 independent Linux packet logging framework. One of the key advantages of NFLOG is support for IPv4 and IPv6 (whereas ULOG was restricted to IPv4 only). The code has been contributed by Vincent Bernat ( @vincentbernat ). + build system: it was modernized so not to rely on specific and old versions of automake and autoconf, as it was the case until 1.5. Among the things, pkg-config and libtool are leveraged and an autogen.sh script is generated. The code has been contributed by Vincent Bernat ( @vincentbernat ). + sfacctd: RabbitMQ and Kafka support was introduced to real-time log and/ or dump at regular time intervals of sFlow counters. This is in addition to existing support for flat-files. + maps_index: several improvements were carried out in the area of indexing of maps: optimizations to pretag_index_fill() and pretag_index_lookup() to improve lookup speeds; optimized id_entry structure, ie. by splitting key and non-key parts, and hashing key in order to consume less memory; added duplicate entry detection (cause of sudden index destruction); pretag_index_destroy() destroys hash keys for each index entry, solving a memory leak issue. Thanks to Job Snijders ( @job ) for his support. + Introduced 'export_proto_seqno' aggregation primitive to report on sequence number of the export protocol (ie. NetFlow, sFlow, IPFIX). This feature may enable more advanced offline analysis of packet loss, out of orders, etc. over time windows than basic online analytics provided by the daemons. + log.c: logging moved from standard output (stdout) to standard error (stderr) so to not conflict with stdout printing of statistics (print plugin). Thanks to Jim Westfall ( @jwestfall69 ) for his support. + print plugin: introduced a new print_output_lock_file config directive to lock standard output (stdout) output so to prevent multiple processes (instances of the same print plugin or different instances of print plugin) overlap output. Thanks to Jim Westfall ( @jwestfall69 ) for his support. + pkt_handlers.c: euristics in NetFlow v9/IPFIX VLAN handler were improved for the case of flows in egress direction. Also IP protocol checks were removed for UDP/TCP ports and TCP flags in case the export protocol is NetFlow v9/IPFIX. Thanks to Alexander Ponamarchuk for his support. ! Code refactoring: improved re-usability of much of the BGP code (so to make it possible to use it as a library for some BMP daemon features, ie. Route Monitoring messages support); consolidated functions to handle log and print plugin output files; improved log messages to always include process name and type. ! fix, bpf_filter.c: issue compiling against libpcap 1.7.x; introduced a check for existing bpf_filter() in libpcap in order to prevent namespace conflicts. ! fix, tmp_net_own_field default value changed to true. This knob can be still switched to false for this release but is going to be removed soon. ! fix, cfg.c, cfg_handlers.c, pmacct.c: some configuration directives and pmacct CL parameters requiring string parsing, ie. -T -O -c, are now passed through tolower(). ! fix, MongoDB plugin: removed version check around mongo_create_index() and now defaulting to latest MongoDB C legacy driver API. This is due to some versioning issue in the driver. ! fix, timestamp_arrival: primitive was reporting incorrect results (ie. always zero) if timestamp_start or timestamp_end were not also specified as part of the same aggregation method. Many thanks to Vincent Morel for reporting the issue. ! fix, thread stack: a value of 0, default, leaves the stack size to the system default or pmacct minimum (8192000) if system default is too low. Some systems may throw an error if the defined size is not a multiple of the system page size. ! fix, nfacctd: improved NetFlow v9/IPFIX parsing. Added new length checks and fixed some existing checks. Thanks to Robert Wuttke ( @Benocs ) for his support. ! fix, pretag_handlers.c: BPAS_map_bgp_nexthop_handler() and BPAS_map_bgp_ peer_dst_as_handler() were not setting a func_type. ! fix, JSON support: Jansson 2.2 does not have json_object_update_missing() function which was introduced in 2.3. This is not provided as part of a jansson.c file and compiled in conditionally, if needed. Jansson 2.2 is still shipped along by some recent OS releases. Thanks to Vincent Bernat ( @vincentbernat ) for contributing the patch. ! fix, log.c: use a format string when calling syslog(). Passing directly a potentially uncontrolled string could crash the program if the string contains formatting parameters. Thanks to Vincent Bernat ( @vincentbernat ) for contributing the patch. ! fix, sfacctd.c: default value for config.sfacctd_counter_max_nodes was set after sf_cnt_link_misc_structs(). Thanks to Robin Douine for his support resolving the issue. ! fix, sfacctd.c: timestamp was consistently being reported as null in sFlow counters output. Thanks to Robin Douine for his support resolving the issue. ! fix, SQL plugins: $SQL_HISTORY_BASETIME environment variable was reporting a wrong value (next basetime) in the sql_trigger_exec script. Thanks to Rain Nõmm for reporting the issue. ! fix, pretag.c: in pretag_index_fill(), replaced memcpy() with hash_dup_key() also a missing res_fdata initialization in pretag_index_lookup() was solved; these issues were originating false negatives upon lookup. Thanks to Rain Nõmm fo his suppor. ! fix, ISIS daemon: hash_* functions renamed into isis_hash_* to avoid name space clashes with their BGP daemon counter-parts. ! fix, kafka_common.c: rd_kafka_conf_set_log_cb moved to p_kafka_init_host() due to crashes seen in p_kafka_connect_to_produce(). Thanks to Paul Mabey for his support resolving the issue. ! fix, bgp_lookup.c: bgp_node_match_* were not returning any match in bgp_follow_nexthop_lookup(). Thanks to Tim Jackson ( @jackson-tim ) for his support resolving the issue. ! fix, sql_common.c: crashes observed when nfacctd_stitching was set to true and nfacctd_time_new was set to false. Thanks to Jaroslav Jiráse ( @jjirasek ) for his support solving the issue. - SQL plugins: sql_recovery_logfile feature was removed from the code due to lack of support and interest. Along with it, also pmmyplay and pmpgplay tools have been removed. - pre_tag_map: removed support for mpls_pw_id due to lack of interest. 1.5.3 -- 14-01-2016 + Introduced the Kafka plugin: Apache Kafka is publish-subscribe messaging rethought as a distributed commit log. Its qualities being: fast, scalable, durable and distributed by design. pmacct Kafka plugin is designed to send aggregated network traffic data, in JSON format, through a Kafka broker to 3rd party applications. + Introduced Kafka support to BGP and BMP daemons, in both their msglog and dump flavors (ie. see [bgp|bmp]_daemon_msglog_kafka_broker_host and [bgp_table|bmp]_dump_kafka_broker_host and companion config directives). + Introduced support for a Kafka broker to be used for queueing and data exchange between Core Process and plugins. plugin_pipe_kafka directive, along with all other plugin_pipe_kafka_* directives, can be set globally or apply on a per plugin basis - similarly to what was done for RabbitMQ (ie. plugin_pipe_amqp). Support is currently restricted only to print plugin. + Added a new timestamp_arrival primitive to expose NetFlow/IPFIX records observation time (ie. arrival at the collector), in addition to flows start and end times (timestamp_start and timestamp_end respectively). + plugin_pipe_amqp: feature extended to the plugins missing it: nfprobe, sfprobe and tee. + Introduced bgp_table_dump_latest_file: defines the full pathname to pointer(s) to latest file(s). Update of the latest pointer is done evaluating files modification time. Many thanks to Juan Camilo Cardona ( @jccardonar ) for proposing the feature. + Introduced pmacctd_nonroot config directive to allow to run pmacctd from a user with non root privileges. This can be desirable on systems supporting a tool like setcap, ie. 'setcap "cap_net_raw,cap_net_admin=ep" /path/to/pmacctd', to assign specific system capabilities to unprivileged users. Patch is courtesy by Laurent Oudot ( @loudot-tehtris ). + Introduced plugin_pipe_check_core_pid: when enabled (default), validates the sender of data at the plugin side. Useful when plugin_pipe_amqp or plugin_pipe_kafka are enabled and hence a broker sits between the daemon Core Process and the Plugins. + A new debug_internal_msg config directive to specifically enable debug of internal messaging between Core process and plugins. ! bgp_table_dump_refresh_time, bmp_dump_refresh_time: max allowed value raised to 86400 from 3600. ! [n|s]facctd_as_new renamed [n|s]facctd_as; improved input checks to all *_as (ie. nfacctd_as) and *_net (ie. nfacctd_net) config directives. ! pkt_handlers.c: NF_sampling_rate_handler(), SF_sampling_rate_handler() now perform a renormalization check at last (instead of at first) so to report the case of unknown (0) sampling rate. ! plugin_pipe_amqp_routing_key: default value changed to '$core_proc_name- $plugin_name-$plugin_type'. Also, increased flexibility for customizing the key with the use of variables (values computed at startup). ! Improved amqp_receiver.py example with CL arguments and better exception handling. Also removed file amqp_receiver_trace.py, example is now merged in amqp_receiver.py. ! fix, BGP daemon: several code optimizations and a few starving conditions fixed. Thanks to Markus Weber ( @FvDxxx ) for his peer index round-robin patch; thanks also to Job Snijders ( @job ) for his extensive support in this area. ! fix, BMP daemon: greatly improved message parsing and segment reassembly; RabbitMQ broker support found broken; several code optimizations are also included. ! fix, bgp_table.c: bgp_table_top(), added input check to prevent crashes in cases table contains no routes. ! fix, networks_file: missing atoi() for networks_cache_entries. Patch is courtesy by Markus Weber ( @FvDxxx ). ! fix, plugin_pipe_amqp_routing_key: check introduced to prevent multiple plugins to bind to the same RabbitMQ exchange, routing key combination. Thanks to Jerred Horsman for reporting the issue. ! fix, MongoDB plugin: added a custom oid fuzz generator to prevent concurrent inserts to fail; switched from deprecated mongo_connect() to mongo_client(); added MONGO_CONTINUE_ON_ERROR flag to mongo_insert_batch along with more verbose error reporting. Patches are all courtesy by Russell Heilling ( @xchewtoyx ). ! fix, nl.c: increments made too early after introduction of MAX_GTP_TRIALS Affected: pmacctd processing of GTP in releases 1.5.x. Patch is courtesy by TANAKA Masayuki ( @tanakamasayuki ). ! fix, pkt_handlers.c: improved case for no SAMPLER_ID, ALU & IPFIX in NF_sampling_rate_handler() on par with NF_counters_renormalize_handler(). ! fix, SQL scripts: always use "DROP TABLE IF EXISTS" for both PostgreSQL and SQLite. Pathes are courtesy by Vincent Bernat ( @vincentbernat ). ! fix, plugin_hooks.c: if p_amqp_publish_binary() calls were done while a sleeper thread was launched, a memory corruption was observed. ! fix, util.c: mkdir() calls in mkdir_multilevel() now default to mode 777 instead of 700; this allows more play with files_umask (by default 077). Thanks to Ruben Laban for reporting the issue. ! fix, BMP daemon: solved a build issue under MacOS X. Path is courtesy by Junpei YOSHINO ( @junpei-yoshino ). ! fix, util.c: self-defined Malloc() can allocate more than 4GB of memory; function is also now renamed pm_malloc(). ! fix, PostgreSQL plugin: upon purge, call sql_query() only if status of the entry is SQL_CACHE_COMMITTED. Thanks to Harry Foster ( @harryfoster ) for his support resolving the issue. ! fix, building system: link pfring before pcap to prevend failures when linking. Patch is courtesy by @matthewsf . ! fix, plugin_common.c: memory leak discovered when pending queries queue was involved (ie. cases where print_refresh_time > print_history). Thanks to Edward Henigin for reporting the issue. 1.5.2 -- 07-09-2015 + Introduced support for a RabbitMQ broker to be used for queueing and data exchange between Core Process and plugins. This is in alternative to the home-grown circular queue implementation. plugin_pipe_amqp directive, along with all other plugin_pipe_amqp_* directives, can be set globally or apply on a per plugin basis (ie. it is a valid scenario, if multiple plugins are instantiated, that some make use of home-grown queueing, while others use RabbitMQ based queueing). + Introducting support for Maximind GeoIP v2 (libmaxminddb) library: if pmacct is compiled with --enable-geoipv2, this defines full pathname to a Maxmind GeoIP database v2 (libmaxminddb) Only the binary database format is supported (ie. it is not possible to load distinct CSVs for IPv4 and IPv6 addresses). + Introduced infrastructure for sFlow counters and support specifically for generic, ethernet and vlan counters. Counters are exported in JSON format to files, specified via sfacctd_counter_file. The supplied filename can contain as variable the sFlow agent IP address. + Introduced a new thread_stack config directive to allow to modify the thread stack size. Natanael Copa reported that some libc implementations, ie. musl libc, may set a stack size that is too small by default. + Introduced networks_file_no_lpm feature: it applies when aggregation method includes src_net and/or dst_net and nfacctd_net (or equivalents) and/or nfacctd_as_new (or equivalents) are set to longest (or fallback): an IP prefix defined as part of the supplied networks_file wins always, even if it's not longest. + tee plugin: added support for (non-)transparent IPv6 replication [further QA required] + plugin_common.c, sql_common.c: added log message to estimate base cache memory usage. + print, AMQP, MongoDB plugins; sfacctd, BGP, BMP daemons: introducing timestamps_since_epoch to write timestamps in 'since Epoch' format. + nfacctd: flow bytes counter can now be sourced via element ID #352 (layer2OctetDeltaCount) in addition to element ID's already supported. Thanks to Jonathan Thorpe for his support. + Introducing proc_priority: redefines the process scheduling priority, equivalent to using the 'nice' tool. Each daemon process, ie. core, plugins, etc., can define a different priority. ! fix, BMP daemon: improved preliminar checks in bmp_log_msg() and added missing SIGHUP signal handling to reload bmp_daemon_msglog_file files. ! fix, bgp_logdump.c: under certain configuration conditions call to both write_and_free_json() and write_and_free_json_amqp() was leading to SEGV. Thanks to Yuriy Lachin for reporting the issue. ! fix, BGP daemon: improved BGP dump output: more accurate timestamping of dump_init, dump_close events. dump_close now mentions amount of entries and tables dumped. Thanks to Yuriy Lachin for brainstorming around this. ! fix, cfg.c: raised amount of allowed config lines from 256 to 8K. ! fix, print/AMQP/MongoDB plugins: SEGV observed when IPFIX vlen variables were stored in the pending_queries_queue structure (ie. as a result of a time mismatch among the IPFIX exporter and the collector box). ! fix, vlen primitives: when 'raw' semantics was selected, print_hex() was returning wrong hex string length (one char short). As a consequence occasionally some extra dirty chars were seen at the end of the converted string. ! fix, vlen primitives: memory leak verified in print/AMQP/MongoDB plugins. ! fix, print, MongoDB & AMQP plugins: dirty values printed as part of the 'proto' under certain conditions. Thanks to Rene Stoutjesdijk for his support resolving the issue. ! fix, amqp_common.c: amqp_exchange_declare() call changed so to address the change of rabbitmq-c API for support of auto_delete & internal for exchange.declare. Backward compatibility with rabbitmq-c <= 0.5.2 is also taken care of. Thanks to Brent Van Dussen for reporting the issue. ! fix, compiling on recent FreeBSD: solved some errors catched by the -Wall compiler flag. Thanks to Stephen Fulton for reporting the issue. Most of the patch is courtesy by Mike Bowie. ! fix, print/AMQP/MongoDB plugins: enforcing cleanup of malloc()ed structs part of entries added to the pending queue, ie. because seen as future entries due to a mismatch of the collector clock with the one of NetFlow/ IPFIX exporter(s). This may have lead to data inconsistencies. ! fix, amqp_common.c: Content type was only specified for messages published when the amqp_persistent_msg configuration option is specified. This info should always be applied to describe the payload of the message. Patch is courtesy by Will Dowling. ! fix, amqp_plugin.c: generate an error on compile if --enable-rabbitmq is specified without --enable-jansson. It's clear in the documentation that both are required for AMQP support, but if built without jansson it will silently not publish messages to AMQP. Patch is courtesy by Will Dowling. ! fix, amqp_common.c: modified the content type to "application/json" in line with RFC4627. Patch is courtesy by Will Dowling. ! fix, setsockopt(): u_int64_t pipe_size vars changed to int, in line with typical OS buffer limits (Linux, Solaris). Introduced check supplied pipe size values are not bigger than INT_MAX. Many thanks to Markus Weber for reporting the issue. ! fix, nl.c: removed pretag_free_label() from pcap_cb() and ensuring init of pptrs. Under certain conditions SEGVs could be noticed. ! fix, flow stitching: when print/AMQP/MongoDB plugins were making use of the pending queries queue, ie. to compensate for time offsets/flows in the future, the stitching feature could potentially lead to SEGV due to unsettled pointers. ! fix, pgsql plugin: SEGV were noticed when insert/update queries to the PostgreSQL database were returning different than PGRES_COMMAND_OK, hence triggering the reprocess mechanism. Thanks very much to Alan Turower for his support. ! fix, improved logging of elements received/sent at buffering point between core process and plugins. Also added explicit start/end purge log message for cases in which there is no data to purge. ! fix, signals.c: ignore_falling_child() now logs if a child process exited with abnormal conditions; this is useful to track writer processes (created by plugins) are terminated by a signal, ie. SEGV. This is already the case for plugins themselves, with the Core Process reporting a simlar log message in case of abnormal exit. Thanks very much to Rene Stoutjesdijk for his support. ! fix, preprocess-data.h: added supported functions minf, minb, minbpp and minppf to non SQL plugins. Thanks to Jared Deyo for reporting the issue. ! fix, nfprobe_plugin.c: IP protocol was not set up correctly for IPv6 traffic in NetFlow v9/IPFIX. Thanks to Gabriel Vermeulen his support solving the issue. 1.5.1 -- 21-02-2015 + BMP daemon: BMP, BGP Monitoring Protocol, can be used to monitor BGP sessions. The current implementation is base on the draft-ietf-grow-bmp-07 IETF draft. The daemon currently supports BMP events and stats only, ie. initiation, termination, peer up, peer down and stats reports messages. Route Monitoring is future (upcoming) work but routes can be currently sourced via the BGP daemon thread (best path only or ADD-PATH), making the two daemons complementary. The daemon enables to write BMP messages to files or AMQP queues, real-time (msglog) or at regular time intervals (dump) and is a separate thread in the NetFlow (nfacctd) or sFlow (sfacctd) collectors. + tmp_net_own_field directive is introduced to record both individual source and destination IP addresses and their IP prefix (nets) as part of the same aggregation method. While this should become default behaviour, a knob for backward-compatibility is made available for all 1.5 until the next major release. + Introduced nfacctd_stitching and equivalents (ie. sfacctd_stitching): when set to true, given an aggregation method, two new non-key fields are added to the aggregate upon purging data to the backend: timestamp_min is the timestamp of the first element contributing to a certain aggregate and timestamp_max is the timestamp of the last element. In case the export protocol provides time references, ie. NetFlow/IPFIX, these are used; if not the current time (hence time of arrival to the collector) is used instead. + Introduced amqp_routing_key_rr feature to perform round-robin load- balancing over a set of routing keys. This is in addition to existing, and more involved, functionality of tag-based load-balancing. + Introduced amqp_multi_values feature: this is same feature in concept as sql_multi_values (see docs). The value is the amount of elements to pack in each JSON array. + Introduced amqp_vhost and companion (ie. bgp_daemon_msglog_amqp_vhost) configuration directives to define the AMQP/RabbitMQ server virtual host. + BGP daemon: bgp_daemon_id now allows to define the BGP Router-ID disjoint from the bgp_daemon_ip definition. Thanks to Bela Toros for his patch. + tee plugin: introduced tee_ipprec feature to color replicated packets, both in transparent and non-transparent modes. Useful, especially when in transparent mode and replicating to hosts in different subnets, to verify which packets are coming from the replicator. + tee plugin: plugin-kernel send buffer size is now configurable via a new config directive tee_pipe_size. Improved logging of send() failures. + nfacctd: introduced support for IPFIX sampling/renormalization using element IDs: #302 (selectorId), #305 (samplingPacketInterval) and #306 (samplingPacketSpace). Many thanks to Rene Stoutjesdijk for his support. + nfacctd: added also support for VLAN ID for NetFlow v9/IPFIX via element type #243 (it was already supported via elements #58 and #59). Support was also added for 802.1p/CoS via element #244. + nfacctd: added native support for NetFlow v9/IPFIX IE #252 and #253 as part of existing primitives in_iface and out_iface (additional check). + pre_tag_map: introduced 'cvlan primitive. In NetFlow v9 and IPFIX this is compared against IE #245. The primitive also supports map indexing. + Introduced pre_tag_label_filter to filter on the 'label' primitive in a similar way how the existing pre_tag_filter feature works against the 'tag' primitive. Null label values (ie. unlabelled data) can be matched using the 'null' keyword. Negations are allowed by pre-pending a minus sign to the label value. + IMT plugin: introduced '-i' command-line option to pmacct client tool: it shows last time (in seconds) statistis were cleared via 'pmacct -e'. + print, MongoDB & AMQP plugins: sql_startup_delay feature ported to these plugins. ! sql_num_hosts: the feature has been improved to support IPv6 addresses. Pre-requisite is definition of INET6_ATON() function in the RDBMS, which is the case for MySQL >= 5.6.3. In SQLite such function has to be defined manually. ! nfacctd: improved NF_evaluate_flow_type() euristics to reckon NetFlow/ IPFIX event (NAT, Firewall, etc.) vs traffic (flows) records. ! fix, GeoIP: spit log notification (warning) in case GeoIP_open() returns null pointer. ! fix, IMT plugin: pmacct client -M and -N queries were failing to report results on exact matches. Affected: 1.5.0. Thanks to Xavier Vitard for reporting the issue. ! fix, pkt_handlers.c: missing else in NF_src_host_handler() was causing IPv6 prefix being copied instead of IPv6 address against NetFlow v9 recs containing both info. ! fix, uacctd: informational log message now shows the correct group the daemon is bound to. Thanks to Marco Marzetti for reporting the issue. ! fix, nfv9_template.c: missing byte conversion while decoding templates was causing SEGV under certain conditions. Thanks to Sergio Bellini for reporting the issue. 1.5.0 -- 28-08-2014 + Introduced bgp_daemon_msglog_file config directive to enable streamed logging of BGP messages/events. Each log entry features a time reference, BGP peer IP address, event type and a sequence number (to order events when time reference is not granular enough). BGP UPDATE messages also contain full prefix and BGP attributes information. Example given in QUICKSTART file, chapter XIIf. + Introduced dump of BGP tables at regular time intervals. The filename, which can include variables, is set by bgp_table_dump_file directive. The output format, currently only JSON, can be set in future via the bgp_table_dump_output directive. The time interval between dumps can be set via the bgp_table_dump_refresh_time directive. Example given in QUICKSTART file, chapter XIIf. + Introduced support for internally variable-length primitives (likely candidates are strings). Introduced also the 'label' primitive which is a variable-length string equivalent of tag and tag2 primitives. Its value are set via a 'set_label' statement in a pre_tag_map (see examples/ pretag.map.example). If, ie. as a result of JEQ's in a pre_tag_map, multiple 'set_label' are applied, then default operation is append labels and separate by a comma. + pmacct project has been assigned PEN #43874. nfprobe plugin: tag, tag2, label primitives are now encoded in IPFIX making use of the pmacct PEN. + Ported preprocess feature to print, MongoDB and AMQP plugins. Preprocess allows to process aggregates (via a comma-separated list of conditionals and checks) while purging data to the backend thus resulting in a powerful selection tier. minp, minb, minf, minbpp, minppf checks have been currently ported. As a result of the porting a new set of config directives are added, ie. print_preprocess and print_preprocess_type. + print, MongoDB & AMQP plugins: if data (start/base) time is greater than commit time then place in pending queue and after purging event re-insert in cache. Concept ported from SQL plugins. + MySQL, PostgreSQL plugins: sql_locking_style now supports keyword "none" to disable locking. This method can help in certain cases, for example when grants over the whole database (requirement for "table" locking in MySQL) is not available. + util.c: open_logfile() now calls mkdir_multilevel() to allow building intermediate directory levels, if not existing. This brings all log files in line with capabilities of print_output_file directive. + Introduced [u|pm]acctd_flow_tcp_lifetime to defines how long a TCP flow could remain inactive. This is in addition to [u|pm]acctd_flow_lifetime that allows to define the same for generic, ie. non-TCP, flows. Thanks to Stathis Gkotsis for his support. + Introducing nfacctd_account_options: if set to true account for NetFlow/ IPFIX option records as well as flow ones. pre_tag_map offers sample_type value of 'option' now to split option data records from flow ones. + nfprobe plugin: support for custom-defined primitives has been introduced in line with other plugins. With such feature it will be possible to augment NetFlow v9/IPFIX records with custom fields (in IPFIX also PENs are supported). + Built a minimal API, for internal use only, around AMQP. Goal is to make re-use of the same AMQP structures for different purposes (logging, BGP daemon dumps, AMQP plugin, etc.). ! fix, BGP daemon: introduced bgp_peer_info_delete() to delete/free BGP info after a BGP peer disconnects. ! fix, print, AMQP, memory plguins: when selecting JSON output, jansson library json_decref() is used in place of free() to free up memory allocated by JSON objects. Using free() was originating memory leaks. ! fix, AMQP plugin: in line with other plugins QN (query number or in case of AMQP messagess number) in log messages now reflects the real number of messages sent to the RabbitMQ message exchange and not just all messages in the queue. Thanks to Gabriel Snook for reporting the issue. ! fix, IMT plugin: memory leak due to missed calls to free_extra_allocs() in case all extras.off_* were null. Thanks to Tim Jackson for his support resolving the issue. ! fix, pmacctd: if reading from a pcap_savefile, introduce a short usleep() after each buffer worth of data so to give time plugins to process/cache it. ! fix, SQL plugins: SQL handler types now include primitives registry index ! fix, print, AMQP & MongoDB plugins: added free() for empty_pcust allocs ! fix, plugin hooks: improved checks to prevent the last buffer on a pipe to plugins (plugin_pipe_size) could go partly out of bounds. ! fix, nfacctd: improved handling of IPFIX vlen records. ! fix, nfprobe: SEGV if custom primitives are defined but array structure is not allocated. ! fix, nfprobe: wrong length was calculated in IPv6 templates for fields with PEN != 0. ! fix, plugin_common.c: declared struct pkt_data in P_cache_insert_pending to be pointed by prim_ptrs. primptrs_set_all_from_chained_cache() is now safe if prim_ptrs is null. ! fix, nfprobe: tackled the case of coexisting 1) PEN and non-PEN custom primitives and 2) variable and fixed custom primitives. ! fix, plugin_common.c: declared struct pkt_data in P_cache_insert_pending to be pointed by prim_ptrs. primptrs_set_all_from_chained_cache() is now safe if prim_ptrs is null. ! fix, lofging: selected configuration file is now logged. cfg_file is passed through realpath() in order to always log the absolute path. ! fix, print, MongoDB & AMQP plugins: pm_setproctitle() invoked upon forking writer processes in alignment with SQL plugins. ! fix, pmacct client: it's now possible to query and wildcard on primitives internally allocated over what_to_count_2 registry. 1.5.0rc3 -- 18-04-2014 + BGP daemon: support for BGP ADD-PATH capability draft-ietf-idr-add-paths has been introduced, useful to advertise known paths when BGP multi-path is enabled in a network. The correct BGP info is linked to traffic data using BGP next-hop (or IP next-hop if use_ip_next_hop is set to true) as selector among the paths available. + pre_tag_map: de-globalized the feature so that, while Pre-Tagging is evaluated in the Core Process, each plugin can be defined a own/local pre_tag_map. + maps_row_len: directive introduced to define the maximum length of map (ie. pre_tag_map) rows. The default value is suitable for most scenarios, though tuning it could be required either to save on memory or to allow for longer entries (ie. filters). + Introduced use_ip_next_hop config directive: when IP prefix aggregation (ie. nfacctd_net) is set to 'netflow', 'sflow' or 'fallback' populate 'peer_dst_ip' field from NetFlow/sFlow IP next hop field if BGP next-hop is not available. + AMQP plugin: implemented persistent messaging via amqp_persistent_msg configuration directive so to protect against RabbitMQ restarts. Feature is courtesy by Nick Douma. + pmacct in-memory plugin client: -T option now supports how many entries to show via ',[<# how many>]' argument syntax. + nfprobe plugin: take BGP next-hop from a defined networks_file. This is in addition to existing feature to take BGP next-hop from a BGP feed. + Set of *_proc_name configuration directives renamed to core_proc_name. Value of core_proc_name is now applied to logging functions and process title. + Re-implemented reverse BGP lookup based primitives, src_as_path src_med src_std_comm src_ext_comm and src_local_pref, in print, MongoDB and AMQP plugins. Primitives have also been re-documented. + pre_tag_map: set_tag and set_tag2 can now be auto-increasing values, ie. "set_tag=1++": "1" being the selected floor value at startup and "++" instructs to increase the tag value at every pre_tag_map iteration. Many thanks to Brent Van Dussen and Gabriel Snook for their support. + Added support for NetFlow v9/IPFIX source/destination IPv4/IPv6 prefixes encoded as flow types: #44, #45, #169 and #170. + [sql|print|mongo|amqp]_history and sql_trigger_time can now be specified also in seconds, ie. as '300' or '300s' alternatively to '5m'. This is to ease syncronization of these values against refresh time to the backend, ie. sql_refresh_time. + Added post_tag2 configuration directive to set tag2 similarly to what post_tag does. + SQL plugins: agent_id, agent_id2 fields renamed to tag, tag2. Issued SQL table schema #9 for agent_id backward compatibility. Renaming agent_id2 to tag2 is going to be disruptive to existing deployments instead. UPGRADE doc updated. + print, MongoDB, AMQP plugins: added [print|mongo|amqp]_max_writers set of configuration directives to port from SQL plugins the idea of max number of concurrent writer processes the plugin is allowed to start. + util.c: comments can now start with a '#' symbol in addition to existing '!'. ! fix, BGP daemon: removed a non-contextual BGP message length check. Same check is already done in the part handling payload reassembly. ! fix, BGP daemon: MP_REACH_NLRI not assumed to be anymore at the end of a route announcement. ! fix, MySQL plugin: added linking of pmacct code against -lstdc++ and -lrt if MySQL plugin is enabled, pre-requisite for MySQL 5.6. Many thanks to Stefano Birmani for reporting the issue. ! fix, sql_common.c: memory leak affecting AS-PATH and BGP communities. Version 1.5.0rc2 affected. Thanks to Brent Van Dussen for his support solving the issue. ! fix, MongoDB plugin: timestamp_start, timestamp_end moved from timestamp type, reserved for internal use, to date. ! fix, print, memory, MongoDB, AMQP plugins: if no AS_PATH information is available an empty string, ie. "", is placed as value (instead of former "^$"). Similar stream-lining was done for communities. Many thanks to Brent Van Dussen and Elisa Jasinska for reporting the issue. ! fix, AMQP, MongoDB plugins: increased default refresh time to 60 secs, up from 10 and in line with SQL plugins value. ! fix, nfprobe plugin: IPv6 source/destination masks passed as IE #29 and #30 and not anymore as their IPv4 counterparts. ! fix, pmacct.c: clibuf variable now malloc'd at runtime so to not impact the data segment. ! fix, log.c: removed sbrk() calls when logging to Syslog. ! fix, pmacctd: If compiling against PF_RING, check and compile against libnuma and librt which are new requirement since version 5.6.2. Thanks to Joan Juvanteny for reporting the issue. ! fix, net_aggr.c: 'prev' array to keep track of hierarchies of networks was being re-initialized by some compilers. Thanks to Joan Juvanteny for reporting the issue. ! fix, MongoDB, JSON outputs: dst_host_country primitive was not properly shown. Patch is courtesy by Stig Thormodsrud. ! fix, pre_tag_map: a memory leak was found when reloading rules containing 'filter' keywords. Thanks to Matt Jenkins for his support resolving the issue. ! fix, server.c: countered a timing issue to ensure EOF is sent after data. Issue was originated by conjunction of non-blocking socket and multiple CPU cores. Thanks to Juan Camilo Cardona and Joel Ouellette Jr for their support. ! fix, acct.c: added length check to hash_crc32() of custom primitives as selective pmacct IMT client queries, ie. -M and -N, were failing to match entries. Thanks to Joel Ouellette Jr for his support. ! fix, nfacctd: NetFlow v9/IPFIX sampling correlation has been improved by placing system scoped sampling options in a separate table. Such table is queried if no matching sampler ID is found for a given . Sampling-related fields (ie. sampler ID, interval, etc.) are now all supported if 1, 2 or 4 bytes long. ! fix, nfacctd: improved handling of the NAT64 case for NSEL. Thanks to Gregoire Leroy for his support. ! fix, nfacctd, sfacctd and BGP daemon: if IPv6 is enabled, IPv4 mapped is supported and can't obtain an IPv6 socket to listen to, retry with a IPv4 one. 1.5.0rc2 -- 25-12-2013 + nfacctd: introduced support for variable-length IPFIX fields for custom- defined aggregation primitives: 'string' semantics is supported and maximum expected length of the field should be specified as 'len' primitive definition. Also PENs are now supported: field_type can be or :. Finally, 'raw' semantics to print raw data, fixed or variable length in hex format was added. + pmacctd, uacctd: introducing custom-defined aggregation primitives in libpcap and ULOG daemons. A new 'packet_ptr' keyword is supported in the aggregate_primitives map for the task: it defines the base pointer in the packet where to read the primitive value; intuitively, this is to be used in conjunction with 'len'. The supported syntax is: :[]+[]. 'layer' keys are: 'packet', 'mac', 'vlan', 'mpls', 'l3', 'l4', 'payload'. Examples are provided in 'examples/primitives.lst'. + nfacctd: introduced pro rating algorithm if sql_history is enabled and nfacctd_time_new is disabled. Although ideal, the feature is disabled by default for now and can be enabled by setting nfacctd_pro_rating to true. Given a NetFlow/IPFIX flow duration greater than time-bins size as configured by sql_history, bytes/packets counters are proportionally distributed across all time-bins spanned by the flow. Many thanks to Stefano Birmani for his support. + Introducing index_maps: enables indexing of maps to increase lookup speeds on large maps and/or sustained lookup rates. Indexes are automatically defined basing on structure and content of the map, up to a maximum of 8. Indexing of pre_tag_map, bgp_peer_src_as_map, flows_to_rd_map is supported. + BGP daemon: introduced bgp_daemon_interval and bgp_daemon_batch config directives: to prevent massive syncronization of BGP peers to contend resources, BGP sessions are accepted in batches: these define the time interval between any two batches and the amount of BGP peers in each batch respectively. + Introducing historical accounting offset (ie. sql_history_offset) to set an offset to timeslots basetime. If history is set to 30 mins (by default creating 10:00, 10:30, 11:00, etc. time-bins), with an offset of, say, 900 seconds (so 15 mins) it will create 10:15, 10:45, 11:15, etc. time- bins. + print, MongoDB, SQL plugins: improved placement of tuples in the correct table when historical accounting (ie. sql_history) and dynamic table names (ie. sql_table) features are both in use. + print, MongoDB, SQL plugins: dynamic file names (print plugin) and tables (MongoDB and SQL plugins) can now include $peer_src_ip, $tag and $tag2 variables: value is populated using the processed record value for peer_src_ip, tag, tag2 primitives respectively. + print plugin: introduced print_latest_file to point latest filename for print_output_file time-series. Until 1.5.0rc1 selection was automagic. But having introduced variable spool directory structures and primitives- related variables the existing basic scheme of producing pointers had to be phased-out. + IMT plugin: added EOF in the client-server communication so to detect uncompleted messages and print an error message. Thanks to Adam Jacob Muller for his proposal. + Introduced [nf|sf|pm]acctd_pipe size and bgp_daemon_pipe_size config directives to define the size of the kernel socket used read traffic data and for BGP messaging respectively. + pmacctd, uacctd: mpls_top_label, mpls_bottom_label and mpls_stack_depth primitives have been implemented. + pmacctd, uacctd: GTP tunnel handler now supports inspection of GTPv1. + pre_tag_map: results of evaluation of pre_tag_map, in case of a positive match, overrides any tags passed by nfprobe/sfprobe plugins via NetFlow/ sFlow export. + pre_tag_map: stack keyword now supports logical or operator (A | B) in addition to sum (A + B). + pre_tag_map: introduced 'mpls_pw_id' keyword to match the signalled MPLS L2 VPNs Pseudowire ID. In NetFlow v9/IPFIX this is compared against IE #249; in sFlow v5 this is compared against vll_vc_id field, extended MPLS VC object. + Introduced log notifications facility: allows to note down specific log notifications have been sent so to prevent excessive repetitive output. ! fix, plugin_hooks.c: plugin_buffer_size variables are bumped to u_int64_t ! fix, plugin_hooks.c: improved protection of internal pmacct buffering (plugin_buffer_size, plugin_pipe_size) from inconsistencies: buffer is now also invalidated by the core process upon first writing into it. Thanks to Chris Wilson for his support. ! fix, plugin_hooks.c: a simple default value for plugin_pipe_size and plugin_buffer_size is now picked if none is supplied. This is to get around tricky estimates. 1.5.0rc1 release affected. ! fix, ll.c: ntohl() done against a char pointer instead of u_int32_t one in MPLS handler was causing incorrect parsing of labels. Thanks to Marco Marzetti for his support. ! fix, net_aggr.c: IPv6 networks debug messages now report correctly net and mask information. Also IPv6 prefix to peer source/destination ASN was crashing due to an incorrect pointer. Finally applying masks to IPv6 addresses was not done correctly. Thanks to Brent Van Dussen for reporting the issue. ! fix, classifiers: slightly optimized search_class_id_status_table() and added warning message if the amount of classifiers exceeds configured number of classifier_table_num (by default 256). ! fix, pre_tag_map: if a JEQ can be resolved into multiple labels, stop to the first occurrence. ! fix, nfacctd, sfacctd: IPv6 was not being correctly reported due to a re-definition of NF9_FTYPE_IPV6. 1.5.0rc1 release affected. Thanks to Andrew Boey for reporting the issue. ! fix, nfacctd: when historical accounting is enabled, ie. sql_history, not assume anymore start and end timestamps to be of the same kind (ie. field type #150/#151, #152/#153, etc.). ! fix, BGP daemon: default BGP RouterID used if supplied bgp_daemon_ip is "0.0.0.0" or "::" ! fix, BGP daemon: the socket opened to accept BGP peerings is restricted to che core process (ie. closed upon instantiating the plugins). Thanks to Olivier Benghozi for reporting the issue. ! fix, BGP daemon: memory leak detected accepting vpnv4 and vpnv6 routes. Thanks to Olivier Benghozi for his support solving the issue. ! fix, BGP daemon: compiling the package without IPv6 support and sending ipv6 AF was resulting in a buffer overrun. Thanks to Joel Krauska for his support resolving the issue. ! fix, IMT plugin: when gracefully exiting, ie. via a SIGINT signal, delete the pipe file in place for communicating with the pmacct IMT client tool. ! fix, print, MongoDB, AMQP plugins: saved_basetime variable initialized to basetime value. This prevents P_eval_historical_acct() to consume much resources during the first time-bin, if historical accounting is enabled (ie. print_history). 1.5.0rc1 release affected. ! fix, print, MongoDB and SQL plugins: purge function is escaped if there are no elements on the queue to process. ! fix, AMQP plugin: removed amqp_set_socket() call so to be able to compile against rabbitmq-c >= 0.4.1 ! fix, MongoDB plugin: change of API between C driver version 0.8 and 0.7 affected mongo_create_index(). MongoDB C driver version test introduced. Thanks to Maarten Bollen for reporting the issue. ! fix, print plugin: SEGV was received if no print_output_file is specified ie. print to standard output. ! fix, MongoDB: optimized usage of BSON objects array structure. ! fix, MongoDB plugin: brought a few numerical fields, ie. VLAN IDs, CoS, ToS, etc. to integer representation, ie. bson_append_int(), from string one, ie. bson_append_string(). Thanks to Job Snijders for his support. ! fix, MySQL plugin: improved catching condition of sql_multi_value set too little value. Thanks to Chris Wilson for reporting the issue. ! fix, nfprobe plugin: catch ENETUNREACH errors instead of bailing out. Patch is courtesy by Mike Jager. 1.5.0rc1 -- 29-08-2013 + Introducing custom-defined aggregation primitives: primitives are defined via a file pointed by aggregate_primitives config directive. The feature applies to NetFlow v9/IPFIX fields only, and with a pre-defined length. Semantics supported are: 'u_int' (unsigned integer, presented as decimal number), 'hex' (unsigned integer, presented as hexa- decimal number), 'ip' (IP address), 'mac' (MAC address)and 'str' (string). Syntax along with examples are available in the 'examples/primitives.lst' file. + Introducing JSON output in addition to tabular and CSV formats. Suitable for injection in 3rd party tools, JSON has the advantage of being a self- consisting format (ie. compared to CSV does not require a table title). Library leveraged is Jansson, available at: http://www.digip.org/jansson/ + Introducing RabbitMQ/AMQP pmacct plugin to publish network traffic data to message exchanges. Unicast, broadcast, load-balancing scenarios being supported. amqp_routing_key supports dynamic elements, like the value of peer_src_ip and tag primitives or configured post_tag value, enabling selective delivery of data to consumers. Messages are encoded in JSON format. + pre_tag_map (and other maps): 'ip' key, which is compared against the IP address originating NetFlow/IPFIX or the AgentId field in sFlow, can now be an IP prefix, ie. XXX.XXX.XXX.XXX/NN, so to apply tag statements to set of exporters or 0.0.0.0/0 to apply to any exporter. Many thanks to Stefano Birmani for his support. + Re-introducing support for Cisco ASA NSEL export. Previously it was just a hack. Now most of the proper work done for Cisco NEL is being reused: post_nat_src_host (field type #40001), post_nat_dst_host (field type #40002), post_nat_src_port (field type #40003), post_nat_dst_port (field type #40004), fw_event (variant of nat_event, field type #40005) and timestamp_start (observation time in msecs, field type #323). + Introducing MPLS-related aggregation primitives decoded from NetFlow v9/ IPFIX, mpls_label_top mpls_label_bottom and mpls_stack_depth, so to give visibility in export scenarios on egress towards core, MPLS interfaces. + mpls_vpn_rd: primitive value can now be sourced from NetFlow v9/IPFIX field types #234 (ingressVRFID) and #235 (egressVRFID). This is in addition to existing method to source value from a flow_to_rd_map file. + networks_file: AS field can now be defined as "_", Useful also to define (or override) elments of an internal port-to-port traffic matrix. + print plugin: creation of intermediate directory levels is now supported; directories can contain dynamic time-based elements hence the amount of variables in a given pathname was also lifted to 32 from 8. + print plugin: introduced print_history configuration directive, which supports same syntax as, for example, sql_history. When enabled, time- related variables substitution of dynamic print_output_file names are determined using this value instead of print_refresh_time one. + Introducing IP prefix labels, ie. for custom grouping of own IP address space. The feature can be enabled by a --enable-plabel when configuring the package for compiling. Labels can be defined via a networks_file. + mongo_user and mongo_passwd configuration directive have been added in order to support authentication with MongoDB. If both are omitted, for backward compatibility, authentication is disabled; if only one of the two is specified instead, the other is set to its default value. + Introducing mongo_indexes_file config directive to define indexes in collections with dynamic name. If the collection does not exist yet, it is created. Index names are picked by MongoDB. + print plugin: introduced print_output_file_append config directive: if set to true allows the plugin to append to an output file rather than overwrite. + bgp_agent_map: added bgp_port key to lookup a NetFlow agent also against a BGP session port (in addition to BGP session IP address/router ID): it aims to support scenarios where BGP sessions do NAT traverals. + peer_dst_ip (BGP next-hop) can now be inferred by MPLS_TOP_LABEL_ADDR (NetFlow v9/IPFIX field type #47). This field might replace BGP next-hop when NetFlow is exported egress on MPLS-enabled core interfaces. + Introducing [nf|pm|sf|u]acctd_proc_name config directives to define the name of the core process (by default always set to 'default'). This is the equivalent to instantiate named plugins but for the core process. Thanks to Brian Rak for bringing this up. + pre_tag_map: introduced key 'flowset_id' to tag NetFlow v9/IFPIX data records basing on their flowset ID value, part of the flowset header. + pmacct client: introduced '-V' command-line option to verify version, build info and compile options passed to the configure script; also a new -a option now allows to retrieve supported aggregation primitives and their description. + Check for mallopt() has been added at configure time. mallopt() calls are introduced in order to disable glibc malloc() boundary checks. ! flow_to_rd_map replaces iface_to_rd_map, increasing its scope: it is now possible to map couples to BGP/ MPLS VPN Route Distinguishers (RD). This is in addition to existing mapping method basing on . ! fix, nfacctd, sfacctd: Setsocksize() call effectiveness is now verified via a subsequent getsockopt(). If result is different than expected, an informational log message is issued. ! fix, building system: removed stale check for FreeBSD4 and introduced check for BSD systems. If on a BSD system, -DBSD is now passed over to the compiler. ! fix, tee plugin: transparent mode now works on FreeBSD systems. Patch is courtesy by Nikita V. Shirokov. ! fix, peer_dst_ip: uninitialized pointer variable was causing unexpected behaviours. Thanks to Maarten Bollen for his support resolving this. ! fix, IMT plugin: selective queries with -M and -N switches verified not working properly. Thanks to Acipia organization for providing a patch. ! fix, sql_common.c: src_port and dst_port primitives correctly spelled if used in conjunction with BGP primitives. Thanks to Brent Van Dussen and Elisa Jasinska for flagging the issue. ! fix, building system: added library checks in /usr/lib64 for OS's where it is not linked to /lib where required. ! fix, print, MongoDB and AMQP plugins: P_test_zero_elem() obsoleted. Instead, the cache structure 'valid' field is used to commit entries to the backend. ! fix, nfacctd: in NetFlow v9/IPFIX, if no time reference is specified as part of records, fall back to time reference in datagram header. ! fix, MongoDB plugin: mongo_insert_batch() now bails out with MONGO_FAIL if something went wrong while processing elements in the batch and an error message is issued. Typical reason for such condition is batch is too big for the resources, mainly memory, available. Thanks very much to Maarten Bollen for his support. ! fix, cfg_handlers.c: all functions parsing configuration directives, and expecting string arguments, are now calling lower_string() so to act as case insensitive. ! fix, IPv6 & NetFlow exporter IP address: upon enabling IPv6, NetFlow exporter IP addresses were written as IPv4-mapped IPv6 address. This was causing confusion when composing maps since the 'ip' field would change depending on whether IPv6 was enabled or not. This is now fixed and IPv4- mapped IPv6 addresses are now internally translated to plain IPv4 ones. ! fix, nfacctd: NetFlow v9/IPFIX source/destination peer ASN information elements have been found mixed up and are now in proper order. 0.14.3 -- 03-05-2013 + tee plugin: a new tee_receivers configuration directive allows multiple receivers to be defined. Receivers can be optionally grouped, for example for load-balancing (rr, hash) purposes, and attached a list of filters (via tagging). The list is fully reloadable at runtime. + A new pkt_len_distrib aggregation primitive is introduced: it works by defining length distribution bins, ie. "0-999,1000-1499,1500-9000" via the new pkt_len_distrib_bins configuration directive. Maximum amount of bins that can be defined is 255; lengths must be within the range 0-9000. + Introduced NAT primitives to support Cisco NetFlow Event Logging (NEL), for Carrier Grade NAT (CGNAT) scenarios: nat_event, post_nat_src_host, post_nat_dst_host, post_nat_src_port and post_nat_dst_port. Thanks to Simon Lockhart for his input and support developing the feature. + Introduced timestamp primitives (to msec resolution) to support generic logging functions: timestamp_start, timestamp_end (timestamp_end being currently applicable only to traffic flows). These primitives must not be confused with existing sql_history timestamps which are meant for the opposite function instead, temporal aggregation. + networks_file: introduced support for (BGP) next-hop (peer_dst_ip) in addition to existing fields. Improved debug output. Also introduced a new networks_file_filter feature to make networks_file work as a filter in addition to its resolver functionality: if set to true net and host values not belonging to defined networks are zeroed out. See UPGRADE document for backward compatibility. + BGP daemon: added support for IPv6 NLRI and IPv6 BGP next-hop elements for rfc4364 BGP/MPLS Virtual Private Networks. + MongoDB plugin: introduced mongo_insert_batch directive to define the amount of elements to be inserted per batch - allowing the plugin to scale better. Thanks for the strong support to Michiel Muhlenbaumer and Job Snijders. + pre_tag_map: 'set_qos' feature introduced: matching network traffic is set 'tos' primitive to the specified value. This is useful if collecting ingress NetFlow/IPFIX at both trusted and untrusted borders, allowing to selectively override ToS values at untrusted ones. For consistency, pre_tag_map keys id and id2 have been renamed to set_tag and set_tag2; legacy jargon is still supported for backward compatibility. + sfacctd: improved support for L2 accounting, ethernet length is being committed as packet length; this information gets replaced by any length information will come from upper layers, if any is reported. Thanks to Daniel Swarbrick for his support. + nfacctd: introduced nfacctd_peer_as directive to value peer_src_as and peer_dst_as primitives from NetFlow/IPFIX export src_as and dst_as values respectively (ie. as a result of a "ip flow-export .. peer-as" config on the exporter). The directive can be plugin-specific. + print, memory plugins: print_output_separator allows to select separator for CSV outputs. Default comma separator is generally fine except for BGP AS-SET representation. ! Building sub-system: two popular configure switches, --enable-threads and --enable-64bit, are now set to true by default. ! fix, print & mongodb plugins: added missing cases for src_net and dst_net primitives. Thanks to John Hess for his support. ! fix, SQL plugins: improved handling of fork() calls when return value is -1 (fork failed). Many thanks to Stefano Birmani for his valuable support troubleshooting the issue. ! fix, ISIS daemon: linked list functions got isis_ prefix in order to prevent namespace clashes with other libraries (ie. MySQL) we link against. Thanks to Stefano Birmani for reporting the issue. ! fix, tee plugin: can't bridge AFs when in transparent mode is not fatal error condition anymore to tackle transient interface conditions. Error message is throttled to once per 60 secs. Thanks to Evgeniy Kozhuhovskiy for his support troubleshooting the issue. ! fix, nfacctd: extra length checks introduced when parsing NetFlow v9/ IPFIX options and data template flowsets. Occasional daemon crashes were verified upon receipt of malformed/incomplete template data. ! fix: plugins now bail out with an error message if core process is found dead via a getppid() check. - nfacctd_sql_log feature removed. The same can now be achieved with the use of proper timestamp primitives (see above). 0.14.2 -- 14-01-2013 + pmacct opens to MongoDB, a leading noSQL document-oriented database via a new 'mongodb' plugin. Feature parity is maintained with all existing plugins. The QUICKSTART doc includes a brief section on how to getting started with it. Using MongoDB >= 2.2.0 is recommended; MongoDB C driver is required. + GeoIP lookups support has been introduced: geoip_ipv4 and geoip_ipv6 config directives now allow to load Maxmind IPv4/IPv6 GeoIP database files; two new traffic aggregation primitives are added to support the feature: src_host_country and dst_host_country. Feature implemented against all deamons and all plugins and supports both IPv4 and IPv6. Thanks to Vincent Bernat for his patches and precious support. + networks_file: user-supplied files to define IP networks and their associations to ASNs (optional) has been hooked up to the 'fallback' (longest match wins) setting of [pm|u|sf|nf]acctd_net, [pm|u]acctd_as and [sf|nf]acctd_as_new. Thanks to John Hess for his support. + A new sampling_rate traffic aggregation primitive has been introduced: to report on the sampling rate to be applied to renormalize counters (ie. useful to support troubleshooting of untrusted node exports and hybrid scenarios where a partial sampling_map is supplied). If renorm of counters is enabled (ie. [n|s]facctd_renormalize set to true) then sampling_rate will show as 1 (ie. already renormalized). + sql_table, print_output_file, mongo_table: dynamic table names are now enriched by a $ref variable, populated with the configured value for refresh time, and a $hst variable, populated with the configured value for sql_history (in secs). + Solved the limit of 64 traffic aggregation primitives: the original 64 bits bitmap is now split in a 16 bits index + 48 bits registry with multiple entries (currently 2). cfg_set_aggregate() and, in future, cfg_get_aggregate() functions are meant to safely manipulate the new bitmap structure and detect mistakes in primitives definition. ! fix, print plugin: removed print_output_file limitation to 64 chars. Now maximum filename length is imposed by underlying OS. ! fix, print plugin: primitives are selectively enabled for printing based on 'aggregate' directive. ! fix, print plugin: pointer to latest file been generated is updated at very last in the workflow. ! fix, ip_flow.c: incorrect initialization for IPv6 flow buffer. Thanks to Mike Jager for reporting the issue and providing a patch. ! fix, pre_tag_map: improved matching of pre_tag_map primitives against IPFIX fields. Thanks to Nikita V Shirokov for reporting the issue. ! fix, nfprobe plugin: improved handling of unsuccessful send() calls in order to prevent file descriptors depletion and log failure cause. Patch is courtesy by Mike Jager. ! fix, nfacctd: gracefully handling the case of NetFlow v9/IPFIX flowset length of zero; unproper handling of the condition was causing nfacctd to infinite loop over the packet; patch is courtesy by Mike Jager. ! fix, Setsocksize(): setsockopt() replaces Setsocksize() in certain cases and Setsocksize() fix to len parameter. Patch is courtesy by Vincent Bernat 0.14.1 -- 03-08-2012 + nfacctd: introduced support for IPFIX variable-length IEs (RFC5101), improved support for IPFIX PEN IEs. + nfacctd, sfacctd: positive/negative caching for bgp_agent_map and sampling_map is being introduced. Cache entries are invalidated upon reload of the maps. + bgp_agent_map: resolution of IPv4 NetFlow agents to BGP speakers with IPv6 sessions is now possible. This is to support dual-stack network deployments. Also the keyword 'filter' is introduced and supported values are only 'ip' and 'ip6'. + nfacctd: etype primitive can be populated from IP_PROTOCOL_VERSION, ie. Field Type #60, in addition to ETHERTYPE, ie. Field Type #256. Should both be present the latter has priority over the former. + print plugin: introduced a pointer to the latest filename in the set, ie. in cases when variable filenames are specified. The pointer comes in the shape of a symlink called "-latest". ! fix, pretag_handlers.c: BGP next-hop handlers are now hooked to the longest-match mechanism for destination IP prefix. ! fix, net_aggr.c: defining a networks_file configuration directive in conjunction with --enable-ipv6 was causing a SEGVs. This is now solved. ! fix, uacctd: cache routine is now being called in order to resolve in/out interface ifindexes. Patch is courtesy by Stig Thormodsrud. ! fix, BGP daemon: bgp_neighbors_file now lists also IPv6 BGP peerings. ! fix, sql_common.c: SQL writers due to safe action are now logged with a warning message rather than debug. ! fix, PostgreSQL table schemas: under certain conditions, default definition of stamp_inserted was generating a 'date/time field value out of range: "0000-01-01 00:00:00"' error. Many thanks to Marcello di Leonardo for reporting the issue and providing a fix. ! fix, IS-IS daemon: sockunion_print() function was found not portable and has been removed. ! fix, BGP daemon: memcpy() replaced by ip6_addr_cpy() upon writing to sockaddr_in6 structures. ! fix, EXAMPLES document has been renamed QUICKSTART for disambiguation on filesystems where case-sensitive names are not supported. ! Several code cleanups. Patches are courtesy by Osama Abu Elsorour and Ryan Steinmetz. 0.14.0 -- 11-04-2012 + pmacct now integrates an IS-IS daemon within collectors; the daemon is being run as a parallel thread within the collector core process; a single L2 P2P neighborship, ie. over a GRE tunnel, is supported; it implements P2P Hello, CSNP and PSNP - and does not send any LSP information out. The daemon is currently used for route resolution. It is well suited to several case-studies, popular one being: more specific internal routes are carried within the IGP while they are summarized in BGP crossing cluster boundaries. + A new aggregation primitive 'etype' has been introduced in order to support accounting against the EtherType field of Ethernet frames. The implementation is consistent across all data collection methods and backends. + sfacctd: introduced support for samples generated on ACL matches in Brocade (sFlow sample type: Enterprise: #1991, Format: #1). Thanks to Elisa Jasinska and Brent Van Dussen for their support. + sfacctd, pre_tag_map: introduced sample_type key. In sFlow v2/v4/v5 this is compared against the sample type field. Value is expected in : notation. ! fix, signals.c: ignoring SIGINT and SIGTERM in my_sigint_handler() to prevent multiple calls to fill_pipe_buffer(), condition that can cause pipe buffer overruns. Patch is courtesy by Osama Abu Elsorour. ! fix, pmacctd: tunnel registry now correctly supports multiple tunnel definitions for the same stack level. ! fix, print plugin: cos field now correctly shows up in the format title while CSV format is selected and L2 primitives are enabled. ! fix, util.c: a feof() check has been added to the fread() call in read_SQLquery_from_file(); thanks to Elisa Jasinska and Brent Van Dussen for their support. ! fix, nfprobe: NetFlow output socket is now re-opened after failing send() calls. Thanks to Maurizio Molina for reporting the problem. ! fix, sfacctd: length checks have been imporved while extracting string tokens (ie. AS-PATH and BGP communities) from sFlow Extended Gateway object. Thanks to Duncan Small for his support. 0.14.0rc3 -- 07-12-2011 + BGP daemon: BGP/MPLS VPNs (rfc4364) implemented! This encompasses both RIB storage (ie. virtualization layer) and lookup. bgp_iface_to_rd_map map correlates couples to Route Distinguishers (RDs). RD encapsulation types #0 (2-bytes ASN), #1 (IP address) and #2 (4-bytes ASN) are supported. Examples provided: examples/bgp_iface_to_rd.map and EXAMPLES files. + mpls_vpn_rd aggregation primitive has been added to the set. Also this is being supported key in Pre-Tagging (pre_tag_map). + print plugin: introduced print_output_file feature to write statistics to files. Output is text, formatted or CSV. Filenames can contain time- based variables to make them dynamic. If filename is static instead, content is overwritten over time. + print plugin: introduced print_time_roundoff feature to align time slots nicely, same as per the sql_history_roundoff directive. + print plugin: introduced print_trigger_exec feature to execute custom scripts at each print_refresh_time interval (ie. to process, expire, gzip, etc. files). Feature is in sync with wrap-up of data commit to screen or files. + pmacctd: introduced support for DLT_LOOP link-type (ie. OpenBSD tunnel interfaces). Thanks to Neil Reilly for his support. + uacctd: a cache of ifIndex is introduced. Hash structure with conflict chains and short expiration time (ie. to avoid getting tricked by cooked interfaces devices a-la ppp0). The cache is an effort to gain speed-ups. Implementation is courtesy by Stephen Hemminger, Vyatta. + Logging: introduced syslog-like timestamping when writing directly to files. Also a separate FD per process is used and SIGHUP elicits files reopening: all aimed at letting proper logs rotation by external tools. + Introduced plugin_pipe_backlog configuration directive: it induces a backlog of buffers on the pipe before actually releasing them to the plugin. The strategy helps optimizing inter-process communications, ie. when plugins are quicker processing data than the Core process. ! fix, peer_src_ip primitive: has been disconnected from [ns]facctd_as_new mechanism in order to ensure it's always representing a reference to the NetFlow or sFlow emitter. ! fix, nfprobe: input and output VLAN ID field types have been aligned to RFC3954, which appears to be also retroactively supported by IPFIX. The new field types are #58 and #59 respectively. Thanks to Maurizio Molina for pointing the issue out. ! fix, IMT plugin: fragmentation of the class table over multiple packets to the pmacct IMT client was failing and has been resolved. ! fix, nfprobe: individual flows start and end timestamps are now filled to the msec resolution. Thanks to Daniel Aschwanden for having reported the issue. ! fix, uacctd: NETLINK_NO_ENOBUFS is set to prevent the daemon being reported about ENOBUFS events by the underlying operating system. Works on kernels 2.6.30+. Patch is courtesy by Stephen Hemminger, Vyatta. ! fix, uacctd: get_ifindex() can now return values greater than 2^15. Patch is courtesy by Stephen Hemminger, Vyatta. ! fix, pmacctd, uacctd: case of zero IPv6 payload in conjunction with no IPv6 next header is now supported. Thanks to Quirin Scheitle for having reported the issue. - Support for is_symmetric aggregation primitive is discontinued. 0.14.0rc2 -- 26-08-2011 + sampling_map feature is introduced, allowing definition of static traffic sampling mappings. Content of the map is reloadable at runtime. If a specific router is not defined in the map, the sampling rate advertised by the router itself, if any, is applied. + nfacctd: introduced support for 16 bits SAMPLER_IDs in NetFlow v9/IPFIX; this appears to be the standard length with IOS-XR. + nfacctd: introduced support for (FLOW)_SAMPLING_INTERVAL fields as part of the NetFlow v9/IPFIX data record. This case is not prevented by the RFC although such information is typically exported as part of options. It appears some probes, ie. FlowMon by Invea-Tech, are getting down this way. + nfacctd, sfacctd: nfacctd_as_new and sfacctd_as_new got a new 'fallback' option; when specified, lookup of BGP-related primitives is done against BGP first and, if not successful, against the export protocol. + nfacctd, sfacctd: nfacctd_net and sfacctd_net got a new 'fallback' option that when specified looks up network-related primitives (prefixes, masks) against BGP first and, if not successful, against the export protocol. It gets useful for resolving prefixes advertised only in the IGP. + sql_num_hosts feature is being introduced: defines, in MySQL and SQLite plugins, whether IP addresses should be left numerical (in network bytes ordering) or converted into strings. For backward compatibility, default is to convert them into strings. + print_num_protos and sql_num_protos configuration directives have been introduced to allow to handle IP protocols (ie. tcp, udp) in numerical format. The default, backward compatible, is to look protocol names up. The feature is built against all plugins and can also be activated via the '-u' commandline switch. ! fix, nfacctd: NetFlow v9/IPFIX sampling option parsing now doesn't rely anymore solely on finding a SamplerID field; as an alternative, presence of a sampling interval field is also checked. Also a workaround is being introduced for sampled NetFlow v9 & C7600: if samplerID within a data record is defined and set to zero and no match was possible, then the last samplerID defined is returned. ! nfacctd: (FLOW)_SAMPLING_INTERVAL fields as part of the NetFlow v9/IPFIX data record are now supported also 16-bits long (in addition to 32-bits). ! fix, SQL plugins: sql_create_table() timestamp has been aligned with SQL queries (insert, update, lock); furthermore sql_create_table() is invoked every sql_refresh_time instead of every sql_history. Docs updated. Thanks to Luis Galan for having reported the issue. ! fix, pmacct client: error code when connection is refused on UNIX socket was 0; it has been changed to 1 to reflect the error condition. Thanks to Mateusz Viste for reporting the issue. ! fix, building system: CFLAGS were not always honoured. Patch is courtesy of Etienne Champetier ! fix, ll.c: empty return value was causing compiler with certain flags to complain about the issue. Patch is courtesy of Ryan Steinmetz. 0.14.0rc1 -- 31-03-2011 + IPFIX (IETF IP Flow Information Export protocol) replication and collector capabilities have been introduced as part of nfacctd, the NetFlow accounting daemon of the pmacct package. + nfprobe plugin: initial IPFIX export implementation. This is called via a 'nfprobe_version: 10' configuration directive. pmacctd, the promiscuous mode accounting daemon, and uacctd, the ULOG accounting daemon, both part of the pmacct package are now supported. + Oracle's BrekeleyDB 11gR2 offers a perfect combination of technologies by including an SQL API that is fully compatible with SQLite. As a result pmacct now opens to BerkeleyDB 5.x via its SQLite3 plugin. + sfacctd: BGP-related traffic primitives (AS Path, local preference, communities, etc.) are now read from sFlow Extended Gateway object if sfacctd_as_new is set to false (default). + nfacctd, sfacctd: source and destination peer ASNs are now read from NetFlow or sFlow data if [ns]facctd_as_new is set to false (default). + nfacctd: introduced support for NetFlow v9/IPFIX source and destination peer ASN field types 128 and 129. The support is enabled at runtime by setting to 'false' (default) the 'nfacctd_as_new' directive. + sfacctd: f_agent now points sFlow Agent ID instead of source IP address; among the other things, this allows to compare BGP source IP address/BGP Router-ID against the sFlow Agent ID. + PostgreSQL plugin: 'sql_delimiter' config directive being introduced: if sql_use_copy is true, uses the supplied character as delimiter.Useful in cases where the default delimiter is part of any of the supplied strings. + pmacct client: introduced support for Comma-Separated Values (CSV) output in addition to formatted-text. A -O commandline switch allows to enable the feature. ! fix, MySQL/PostgreSQL/SQLite3 plugins: insert of data into the database can get arbitrarily delayed under low traffic conditions. Many Thanks to Elisa Jasinska and Brent Van Dussen for their great support in solving the issue. ! fix, BGP daemon: multiple BGP capabilities per capability announcement were not supported - breaking compliancy with RFC5492. The issue was only verified against a OpenBGPd speaker. Patch is courtesy of Manuel Guesdon. ! fix, initial effort made to document uacctd, the ULOG accounting daemon 0.12.5 -- 28-12-2010 + nfacctd: introduced support for NAT L3/L4 field values via xlate_src and xlate_dst configuration directives. Implementation follows IPFIX standard for IPv4 and IPv6 (field types 225, 226, 227, 228, 281 and 282). + nfacctd: Cisco ASA NetFlow v9 NSEL field types 40001, 40002, 40003, 40004 and IPFIX/Cisco ASA NetFlow v9 NSEL msecs absolute timestamps field types 152, 153 and 323 have been added. + nfacctd: introduced support for 'new' TCP/UDP source/destination ports (field types 180, 181, 182, 183), as per IPFIX standard, basing on the L4 protocol value (if any is specified as part of the export; otherwise assume L4 is not TCP/UDP). + nfacctd, nfprobe: introduced support for application classification via NetFlow v9 field type #95 (application ID) and application name table option. This feature aligns with Cisco NBAR-NetFlow v9 integration feature. + nfacctd: introduced support for egress bytes and packet counters (field types 23, 24) basing on the direction value (if any is specified as part of the export; otherwise assume ingress as per RFC3954). + nfprobe: egress IPv4/IPv6 NetFlow v9 templates have been introduced; compatibility with Cisco (no use of OUT_BYTES, OUT_OUT_PACKETS) taken into account. + nfacctd: added support for egress datalink NetFlow v9 fields basing on direction field. + nfacctd, sfacctd: aggregate_filter can now filter against TCP flags; also, [ns]facctd_net directive can now be specified per-plugin. + BGP daemon: introduced support for IPv6 transport of BGP messaging. + BGP daemon: BGP peer information is now linked into the status table for caching purposes. This optimization results in good CPU savings in bigger deployments. ! fix, nfacctd, sfacctd: daemons were crashing on OpenBSD platform upon setting an aggregate_filter configuration directive. Patch is courtesy of Manuel Pata. ! fix, xflow_status.c: status entries were not properly linked to the hash conflict chain resulting in a memory leak. However the maximum number of table entries set by default was preventing the structure to grow undefinitely. ! fix, sql_common.c: increased buffer size available for sql_table_schema from 1KB to 8KB. Thanks to Michiel Muhlenbaumer his support. ! fix, bgp_agent_map has been improved to allow mapping of NetFlow/sFlow agents making use of IPv6 transport to either a) IPv4 transport address of BGP sessions or b) 32-bit BGP Router IDs. Mapping to IPv6 addresses is however not (yet) possible. ! fix, nfprobe: encoding of NetFlow v9 option scope has been improved; nfprobe source IPv4/IPv6 address, if specified via nfprobe_source_ip directive, is now being written. ! fix, util.c: string copies in trim_spaces(), trim_all_spaces() and strip_quotes() have been rewritten more safely. Patch is courtesy of Dmitry Koplovich. ! fix, sfacctd: interface format is now merged back into interface value fields so to ease keeping track of discards (and discard reasons) and multicast fanout. ! fix, MySQL, SQLite3 plugins: sql table version 8 issued to provide common naming convention when mapping primitives to database fields among the supported RDBMS base. Thanks to Chris Wilson for his support. ! fix, pmacct client: numeric variables output converted to unsigned from signed. ! fix, nfacctd_net, sfacctd_net: default value changed from null (and related error message) to 'netflow' for nfacctd_net and 'sflow' for sfacctd_net. ! fix, nfacctd, sfacctd: aggregate_filter was not catching L2 primitives (VLAN, MAC addresses) when performing egress measurements. 0.12.4 -- 01-10-2010 + BGP daemon: a new memory model is introduced by which IP prefixes are being shared among the BGP peers RIBs - leading to consistent memory savings whenever multiple BGP peers export full tables due to the almost total overlap of information. Longest match nature of IP lookups required to raise BGP peer awareness of the lookup algorithm. Updated INTERNALS document to support estimation of the memory footprint of the daemon. + BGP daemon: a new bgp_table_peer_buckets configuration directive is introduced: per-peer routing information is attached to IP prefixes and now hashed onto buckets with conflict chains. This parameter sets the number of buckets of such hash structure; the value is directly related to the number of expected BGP peers, should never exceed such amount and is best set to 1/10 of the expected number of peers. + nfprobe: support has been added to export direction field (NetFlow v9 field type #61); its value, 0=ingress 1=egress, is determined via nfprobe_direction configuration directive. + nfacctd: introduced support for Cisco ASA bytes counter, NetFlow v9 field type #85. Thanks to Ralf Reinartz for his support. + nfacctd: improved flow recognition heuristics for cases in which IPv4/IPv6/input/output data are combined within the same NetFlow v9 template. Thanks to Carsten Schoene for his support. ! fix, BGP daemon: bgp_nexthop_followup was not working correctly if pointed to a non-existing next-hop. ! fix, nfv9_template.c: ignoring unsupported NetFlow v9 field types; improved template logging. Thanks to Ralf Reinartz for his support. ! fix, print plugin: support for interfaces and network masks has been added. Numeric variables output converted to unsigned from signed. 0.12.3 -- 28-07-2010 + 'cos' aggregation primitive has been implemented providing support for 802.1p priority. Collection is supported via sFlow, libpcap and ULOG; export is supported via sFlow. + BGP daemon: TCP MD5 signature implemented. New 'bgp_daemon_md5_file' configuration directive is being added for the purpose of defining peers and their respective MD5 keys, one per line, in CSV format. The map is reloadable at runtime: existing MD5 keys are removed via setsockopt(), new ones are installed as per the newly supplied map. Sample map added in 'examples/bgp_md5.lst.example'. + BGP daemon: added support for RFC3107 (SAFI=4 label information) to enable receipt of labeled IPv4/IPv6 unicast prefixes. + nfprobe, sfprobe: introduced the concept of traffic direction. As a result, [ns]fprobe_direction and [ns]fprobe_ifindex configuration directives have been implemented. + [ns]fprobe_direction defines traffic direction. It can be statically defined via 'in' or 'out' keywords; values can also be dynamically determined through a pre_tag_map (1=input, 2=output) by means of 'tag' and 'tag2' keywords. + [ns]fprobe_ifindex either statically associate an interface index (ifIndex) to a given [ns]fprobe plugin or semi-dynamically via lookups against a pre_tag_map by means of 'tag' and 'tag2' keywords. + sfprobe: sfprobe_ifspeed configuration directive is introduced and aimed at statically associating an interface speed to an sfprobe plugin. + sfprobe: Switch Extension Header support added. Enabler for this development was support for 'cos' and in/out direction. Whereas VLAN information was already supported as an aggregation primitive. + sfprobe: added support for Counter Samples for multiple interfaces. Sampling function has been brought to the plugin so that Counter Samples can be populated with real bytes/packets traffic levels. ! nfprobe, sfprobe: send buffer size is now aligned to plugin_pipe_size, if specified, providing a way to tune buffers in case of sustained exports. ! fix, addr.c: pm_ntohll() and pm_htonll() routines rewritten. These are aimed at changing byte ordering of 64-bit variables. ! fix, BGP daemon: support for IPv6 global address/link-local address next-hops as part of MP_REACH_NLRI parsing. ! fix, cfg_handlers.c: bgp_daemon and bgp_daemon_msglog parsing was not correct, ie. enabled if specified as 'false'. Thanks to Brent Van Dussen for reporting the issue. ! fix, bgp.c: found a CPU hog issue caused by missing cleanup of the select() descriptors vector. ! fix, pmacct.c: in_iface/out_iface did erroneously fall inside a section protected by the "--disable-l2" switch. Thanks to Brent Van Dussen for reporting the issue. 0.12.2 -- 27-05-2010 + A new 'tee' plugin is introduced bringing both NetFlow and sFlow replication capabilities to pmacct. It supports transparent mode (tee_transparent), coarse-grained filtering capabilities via the Pre-Tagging infrastructure. Quickstart guide is included as part of the EXAMPLES file (chapter XII). + nfprobe, sfprobe: introduced support for export of the BGP next-hop information. Source data selection for BGP next-hop is being linked to [pmacctd_as|uacctd_as] configuration directive. Hence it must be set to 'bgp' in order for this feature to work. + nfprobe, sfprobe, BGP daemon: new set of features (nfprobe_ipprec, sfprobe_ipprec, bgp_daemon_ipprec) allows to mark self-originated sFlow, NetFlow and BGP datagrams with the supplied IP precedence value. + peer_src_ip (IP address of the NetFlow emitter, agent ID of the sFlow emitter) and peer_dst_ip (BGP next-hop) can now be filled from NetFlow/sFlow protocols data other than BGP. To activate the feature nfacctd_as_new/sfacctd_as_new have to be 'false' (default value), 'true' or 'file'. + print plugin: introduced support for Comma-Separated Values (CSV) output in addition to formatted-text. A new print_output feature allows to switch between the two. + pmacctd: improved 802.1ad support. While recursing, outer VLAN is always reported as value of the 'vlan' primitive. ! fix, pmacctd: 802.1p was kept integral part of the 'vlan' value. Now a 0x0FFF mask is applied in order to return only the VLAN ID. ! fix, pkt_handlers.c: added trailing '\0' symbol when truncating AS-PATH and BGP community strings due to length constraints. ! fix, sql_common.c: maximum SQL writers warning message was never reached unless a recovery method is specifited. Thanks to Sergio Charpinel Jr for reporting the issue. ! fix, MySQL and PostgreSQL plugins: PGRES_TUPLES_OK (PostgreSQL) and errno 1050 (MySQL) are now considered valid return codes when dynamic tables are involved (ie. sql_table_schema). Thanks to Sergio Charpinel Jr for his support. ! fix, BGP daemon: pkt_bgp_primitives struct has been explicitely 64-bit aligned. Mis-alignment was causing crashes when buffering was enabled (plugin_buffer_size). Verified on Solaris/sparc. 0.12.1 -- 07-04-2010 + Input/output interfaces (SNMP indexes) have now been implemented natively; it's therefore not required anymore to pass through the (Pre-)tag infrastructure. As a result two aggregation primitives are being introduced: 'in_iface' and 'out_iface'. + Support for source/destination IP prefix masks is introduced via two new aggregation primitives: src_mask and dst_mask. These are populated as defined by the [nf|sf|pm|u]acctd_net directive: NetFlow/sFlow protocols, BGP, Network files (networks_file) or static (networks_mask) being valid data sources. + A generic tunnel inspection infrastructure has been developed to benefit both pmacctd and uacctd daemons. Handlers are defined via configuration file. Once enabled daemons will account basing upon tunnelled headers rather than the envelope. Currently the only supported tunnel protocol is GTP, the GPRS tunnelling protocol (which can be configured as: "tunnel_0: gtp, "). Up to 8 different tunnel stacks and up to 4 tunnel layers per stack are supported. First matching stack, first matching layer wins. + uacctd: support for the MAC layer has been added for the Netlink/ ULOG Linux packet capturing framework. + 'nfprobe_source_ip' feature introduced: it allows to select the IPv4/IPv6 address to be used to export NetFlow datagrams to the collector. + nfprobe, sfprobe: network masks are now exported via NetFlow and sFlow. 'pmacctd_net' and its equivalent directives define how to populate src_mask and dst_mask values. ! cleanup, nfprobe/sfprobe: data source for 'src_as' and 'dst_as' primitives is now expected to be always explicitely defined (in line with how 'src_net' and 'dst_net' primitives work). See the UPGRADE doc for the (limited) backward compatibility impact. ! Updated SQL documentation: sql/README.iface guides on 'in_iface' and 'out_iface' primitives; sql/README.mask guides on 'src_mask' and 'dst_mask' primitives; sql/README.is_symmetric guides on 'is_symmetric' primitive. ! fix, nfacctd.h: source and destination network masks were twisted in the NetFlow v5 export structure definition. Affected releases are: 0.12.0rc4 and 0.12.0. ! fix, nfprobe_plugin.c: l2_to_flowrec() was missing some variable declaration when the package was configured for compilation with --disable-l2. Thanks to Brent Van Dussen for reporting the issue. ! fix, bgp.c: bgp_attr_munge_as4path() return code was not defined for some cases. This was causing some BGP messages to be marked as malformed. ! fix, sfprobe: a dummy MAC layer was created whenever this was not included as part of the captured packet. This behaviour has been changed and header protocol is now set to 11 (IPv4) or 12 (IPv6) accordingly. Thanks to Neil McKee for pointing the issue. ! workaround, building sub-system: PF_RING enabled libpcap was not recognized due to missing of pcap_dispatch(). This is now fixed. 0.12.0 -- 16-02-2010 + 'is_symmetric' aggregation primitive has been implemented: aimed at easing detection of asymmetric traffic. It's based on rule definitions supplied in a 'bgp_is_symmetric_map' map, reloadable at runtime. + A new 'bgp_daemon_allow_file' configuration directive allows to specify IP addresses that can establish a BGP session with the collector's BGP thread. Many thanks to Erik van der Burg for contributing the idea. + 'nfacctd_ext_sampling_rate' and 'sfacctd_ext_sampling_rate' are introduced: they flag the daemon that captured traffic is being sampled. Useful to tackle corner cases, ie. the sampling rate reported by the NetFlow/sFlow agent is missing or incorrect. + The 'bgp_follow_nexthop' feature has been extended so that extra IPv4/IPv6 prefixes can be supplied. Up to 32 IP prefixes are now supported and a warning message is generated whenever a supplied string fails parsing. + Pre-Tagging: implemented 'src_local_pref' and 'src_comms' keys. These allow tagging based on source IP prefix local_pref (sourced from either a map or BGP, ie. 'bgp_src_local_pref_type: map', 'bgp_src_local_pref_type: bgp') and standard BGP communities. + Pre-Tagging: 'src_peer_as' key was extended in order to match on BGP-sourced data (bgp_peer_src_as_type: bgp). + Pre-Tagging: introduced 'comms' key to tag basing on up to 16 standard BGP communities attached to the destination IP prefix. The lookup is done against the BGP RIB of the exporting router. Comparisons can be done in either match-any or match-all fashion; xidDocumentation and examples updated. ! fix, util.c: load_allow_file(), empty allow file was granting a connection to everybody being confused with a 'no map' condition. Now this case is properly recognized and correctly translates in a reject all clause. ! fix, sql_common.c: log of NetFlow micro-flows to a SQL database (nfacctd_sql_log directive) was not correctly getting committed to the backend, when sql_history was disabled. ! fix, mysql|pgsql|sqlite_plugin.c: 'flows' aggregation primitive was not suitable to mix-and-match with BGP related primitives (ie. peer_dst_as, etc.) due to an incorrect check. Many thanks to Zenon Mousmoulas for the bug report. ! fix, pretag_handlers.c: tagging against NetFlow v9 4-bytes in/out interfaces was not working properly. Thanks to Zenon Mousmoulas for reporting the issue. 0.12.0rc4 -- 21-12-2009 + BGP-related source primitives are introduced, namely: src_as_path, src_std_comm, src_ext_comm, src_local_pref and src_med. These add to peer_src_as which was already implemented. All can be resolved via reverse BGP lookups; peer_src_as, src_local_pref and src_med can also be resolved via lookup maps which support checks like: bgp_nexthop (RPF), peer_dst_as (RPF), input interface and source MAC address. Many thanks to Zenon Mousmoulas and GRNET for their fruitful cooperation. + Memory structures to store BGP-related primitives have been optimized. Memory is now allocated only for primitives part of the selected aggregation profile ('aggregate' config directive). + A new 'bgp_follow_nexthop' configuration directive is introduced to follow the BGP next-hop up to the edge of the routing domain. This is particularly aimed at networks not running MPLS, where hop-by-hop routing is in place. + Lookup maps for BGP-related source primitives (bgp_src_med_map, bgp_peer_src_as_map, bgp_src_local_pref_map): result of check(s) can now be the keyword 'bgp', ie. 'id=bgp' which triggers a BGP lookup. This is thought to handle exceptions to static mapping. + A new 'bgp_peer_as_skip_subas' configuration directive is being introduced. When computing peer_src_as and peer_dst_as, returns the first ASN which is not part of a BGP confederation; if only confederated ASNs are on the AS-Path, the first one is returned instead. + Pre-Tagging: support has been introduced for NetFlow v9 traffic direction (ingress/egress). + Network masks part of NetFlow/sFlow export protocols can now be used to compute src_net, dst_net and sum_net primitives. As a result a set of directives [nfacctd|sfacctd|pmacctd|uacctd]_net allows to globally select the method to resolve such primitives, valid values being: netflow, sflow, file (networks_file), mask (networks_mask) and bgp (bgp_daemon). + uacctd: introduced support for input/output interfaces, fetched via NetLink/ULOG API; interfaces are available for Pre-Tagging, and inclusion in NetFlow and sFlow exports. The implementation is courtesy of Stig Thormodsrud. + nfprobe, sfprobe: new [nfprobe|sfprobe]_peer_as option to set source/destination ASNs, part of the NetFlow and sFlow exports, to the peer-AS rather than origin-AS. This feature depends on a working BGP daemon thread setup. ! A few resource leaks were detected and fixed. Patch is courtesy of Eric Sesterhenn. ! bgp/bgp.c: thread concurrency was detected upon daemon startup under certain conditions. As a solution the BGP thread is being granted a time advantage over the traffic collector thread. ! bgp/bgp.c: fixed a security issue which could have allowed a malicious user to disrupt established working BGP sessions by exploiting the implemented concept of BGP session replenishment; this has been secured by a check against the session holdtime. Many thanks to Erik van der Burg for spotting the issue. ! bgp/bgp.c: BGP listener socket now sets SO_REUSEADDR option for quicker turn around times while stopping/starting the daemon. ! net_aggr.c: default route (0.0.0.0/0) was considered invalid; this is now fixed. 0.12.0rc3 -- 28-10-2009 + Support for NetFlow v9 sampling via Option templates and data is introduced; this is twofold: a) 'nfacctd_renormalize' configuration directive is now able to renormalize NetFlow v9 data on-the-fly by performing Option templates management; b) 'nfprobe', the NetFlow probe plugin, is able to flag sampling rate (either internal or external) when exporting flows to the collector. + '[pm|u]acctd_ext_sampling_rate' directives are introduced to support external sampling rate scenarios: packet selection is performed by the underlying packect capturing framework, ie. ULOG, PF_RING. Making the daemon aware of the sampling rate, allows to renormalize or export such information via NetFlow or sFlow. + pmacctd: the IPv4/IPv6 fragment handler engine was reviewed to make it sampling-friendly. The new code hooks get enabled when external sampling (pmacctd_ext_sampling_rate) is defined. + A new 'uacctd' daemon is added to the set; it is based on the Netlink ULOG packet capturing framework; this implies it works only on Linux and can be optionally enabled when compling by defining the '--enable-ulog' switch. The implementation is fully orthogonal with the existing feature set. Thanks very much to: A.O. Prokofiev for contributing the original idea and code; Stig Thormodsrud for his support and review. + The 'tag2' primitive is introduced. Its aim is to support traffic matrix scenarios by giving a second field dedicated to tag traffic. In a pre_tag_map this can be employed via the 'id2' key. See examples in the 'examples/pretag.map.example' document. SQL plugins write 'tag2' content in the 'agent_id2' field. Read 'sql/README.agent_id2' document for reference. + Some new directives to control and re-define file attributes written by the pmacct daemons, expecially when launched with increased priviledges, are introduced: file_umask, files_uid, files_gid. Files to which these apply include, ie. pidfile, logfile and BGP neighbors file. ! fix, bgp/bgp.c: upon reaching bgp_daemon_max_peers threshold, logs were flooded by warnings even when messages were coming from a previously accepted BGP neighbor. Warnings are now sent only when a new BGP connection is refused. ! fix, nfprobe/netflow9.c: tags (pre_tag_map, post_tag) were set per pair of flows, not respecting their uni-directional nature. It was generating hiding of some tags. ! fix, nfprobe/netflow9.c: templates were (wrongly) not being included in the count of flows sent in NetFlow v9 datagrams. While this was not generating any issues with parsing flows, it was originating visualization issues in Wireshark. ! fix, SQL plugins: CPU hitting 100% has been determined when sql_history is disabled but sql_history_roundoff is defined. Thanks to Charlie Allom for reporting the issue. ! fix, sfacctd.c: input and output interfaces (non-expaneded format) were not correcly decoded creating issues to Pre- tagging. Thanks to Jussi Sjostrom for reporting the issue. 0.12.0rc2 -- 09-09-2009 + BGP daemon thread has been tied up with both the NetFlow and sFlow probe plugins, nfprobe and sfprobe, allowing to encode dynamic ASN information (src_as, dst_as) instead of reading it from text files. This finds special applicability within open-source router solutions. + 'bgp_stdcomm_pattern_to_asn' feature is introduced: filters BGP standard communities against the supplied pattern. The first matching community is split using the ':' symbol. The first part is mapped onto the peer AS field while the second is mapped onto the origin AS field. The aim is to deal with prefixes on the own address space. Ie. BGP standard community XXXXX:YYYYY is mapped as: Peer-AS=XXXXX, Origin-AS=YYYYY. + 'bgp_neighbors_file' feature is introduced: writes a list of the BGP neighbors in the established state to the specified file. This gets particularly useful for automation purposes (ie. auto-discovery of devices to poll via SNMP). + 'bgp_stdcomm_pattern' feature was improved by supporting the regex '.' symbol which can be used to wildcard a pre-defined number of characters, ie. '65534:64...' will match community values in the range 64000-64999 only. + SQL preprocess layer: removed dependency between actions and checks. Overral logics was reviewed to act more consistently with recently introduced SQL cache entry status field. + SQL common layer: poll() timeout is now calculated adaptively for increased deadline precision. + sql_startup_delay feature functionality was improved in order to let it work as a sliding window to match NetFlow setups in which a) mainain original flow timestamps and b) enable the sql_dont_try_update feature is required. ! DST (Daylight Saving Time) support introduced to sql_history and sql_refresh_time directives. Thanks to for reporting the issue. ! fix, pmacctd.c: initial sfprobe plugin checks were disabling IP fragments handler. This was causing pmacctd to crash under certain conditions. Thanks to Stig Thormodsrud for having reported the issue. ! fix, nfprobe, netflow5.c: missing htons() call while encoding src_as primitive. ! fix, BGP thread, bgp_aspath.c: estimated AS-PATH length was not enough for 32-bit ASNs. String length per-ASN increased from 5 to 10 chars. ! Documentation update, EXAMPLES: how to establish a local BGP peering between pmacctd and Quagga 0.99.14 for NetFlow and sFlow probe purposes. ! fix, print_status_table(): SEGV was showing up while trying to retrieve xFlow statistics by sending a SIGUSR1 signal and a collector IP address was not configured. ! ip_flow.[c|h]: code cleanup. 0.12.0rc1 -- 01-08-2009 + a BGP daemon thread has been integrated in both the NetFlow and sFlow collectors, nfacctd and sfacctd. It maintains per- peer RIBs and supports MP-BGP (IPv4, IPv6) and 32-bit ASNs. As a result the following configuration directives are being introduced: bgp_daemon, bgp_daemon_ip, bgp_daemon_max_peers, bgp_daemon_port and bgp_daemon_msglog. For a quick-start and implementation notes refer to EXAMPLES document and detailed configuration directives description in CONFIG-KEYS. + A new set of BGP-related aggregation primitives are now supported by the "aggregate" directive: std_comm, ext_comm, as_path, peer_src_ip, peer_dst_ip, peer_src_as, peer_dst_as, med, local_pref. A few extra directives are being introduced to support (filter, map, cut down, etc.) some primitives: bgp_peer_src_as_type, bgp_peer_src_as_map, bgp_aspath_radius, bgp_stdcomm_pattern and bgp_extcomm_pattern. + nfacctd_as_new supports a new value "bgp". It is meant to populate src_as and dst_as primitives by looking up source and destination IP prefixes against the NetFlow (or sFlow) agent RIB. + A new sql_table_type directive is introduced: by combining it with sql_table_version, defines one of the standard BGP tables. + Two new directives have been developed to support scenarios where NetFlow (or sFlow) agents are not running BGP or have default-only or partial views: bgp_follow_default and bgp_agent_map. + 4-bytes ASNs are now supported: including NetFlow and sFlow collectors, NetFlow and sFlow probes, networks_file to map prefixes to ASNs. The new BGP daemon implementation is, of course, fully compliant. + Pre-Tagging: the ID is now a 32-bit unsigned value (it was 16-bit). As a result, there valid tags can be in the range 1-4294967295 and maps can now express the resulting ID as an IPv4 address (ie. bgp_agent_map). + Pre-tagging: support for 32-bit input/output interfaces is now available. ! fix, sql_common.c: read_SQLquery_from_file() was returning a random value, regardless of the successful result. Patch has been provided provided by Giedrius Liubavicius ! fix, pmacct.c: when unused, source/destination IP address fields were presented as NULL values. This is now replaced with a '0' value to improve output parsing. ! Standard major release compilation check-pointing: thanks very much to Manuel Pata and Tobias Lott for their strong support with OpenBSD and FreeBSD respectively. 0.11.6 -- 07-04-2009 + Introduced support for tag ranges into the 'pre_tag_filter' configuration directive (ie. '10-20' matches traffic tagged in the range 10..20). This works both in addition to and in combination with negations. + Tcpdump-style filters, ie. 'aggregate_filter', now support indexing within a packet, ie. 'ether[12:2]', to allow a more flexible separation of the traffic. + Introduced support for descriptions in networks definition files pointed by the 'networks_file' configuration directive. Thanks to Karl O. Pinc for contributing the patch. ! fix, pmacctd: libpcap DLT_LINUX_SLL type is not defined in older versions of the library. It was preventing successful compilation of pmacct on OpenBSD. This has been fixed by defining internally to pmacct all DLT types in use. Thanks to Karl O. Pinc for his support. ! fix, IPv6 networks_file, load_networks6(): wrong masks were applied to IPv6 networks due to dirty temporary buffers for storing IPv6 addresses and masks. Short '::' IPv6 format is currently not supported. Thanks to Robert Blechinger for flagging the issue. ! fix, pretag.c: Pre-Tagging infrastructure was SEGV'ing after having been instructed to reload via a SIGHUP signal. Patch is courtesy of Denis Cavrois and the Acipia development team. ! fix, sfacctd, nfacctd: Assign16() was not handling correctly 2-bytes EtherType values (ie. 0x86dd, 0x8847) in 802.1Q tags. As a result 'aggregate_filter' was not able to correctly match IPv6-related filters. Thanks to Axel Apitz for reporting the issue. ! fix, xflow_status.c: a cosmetic bug was displaying sequence numbers without applying previous increment. This definitely will help troubleshooting and debugging. ! fix, sfacctd, sfv245_check_status(): AF of the sFlow agent is now explicitely defined: when IPv6 is enabled the remote peer address can be reported as IPv4-mapped IPv6 address. This was causing warning messages to report the wrong sFlow agent IP address. Thanks to Axel Apitz for reporting the issue. ! fix, IMT plugin was crashing upon receipt of a classification table request (WANT_CLASS_TABLE) when stream classification was actually disabled. ! fix, pmacct.c: classifier index was not brought back to zero by the pmacct client. This was preventing the client to show correct stream classification when it was feeded with multiple queries. The fix is courtesy of Fabio Cairo. ! fix, MySQL plugin: upon enabling of the 'nfacctd_sql_log' directive, 'stamp_updated' field was incorrectly reported as '0000-00-00 00:00:00' due to wrong field formatting. Thanks to Brett D'Arcy for reporting and patching the issue. ! Initial effort to clean the code up by strcpy() calls. Thanks to Karl O. Pinc for taking such initiative. 0.11.5 -- 21-07-2008 + SQL UPDATE queries code has been rewritten for increased flexibility. The SET statement is now a vector and part of it has been shifted into the sql_compose_static_set() routine in the common SQL layer. + A new sql_locking_style directive is now supported in the MySQL plugin. To exploit it, an underlying InnoDB table is mandatory. Thanks to Matt Gillespie for his tests. + Support for Endace DAG cards is now available; this has been tested against libDAG 3.0.0. Many thanks to Robert Blechinger for his extensive support. + pmacctd, the Linux Cooked device (DLT_LINUX_SLL) handler has been enhanced by supporting 'src_mac' and 'vlan' aggregation primitives. ! fix, xflow_status.c: NetFlow/sFlow collector's IP address is being rewritten as 0.0.0.0 when NULL. Was causing SEGVs on Solaris/sparc. ! fix, server.c: WANT_RESET is copied in order to avoid losing it when handling long queries and need to fragment the reply. Thanks very much to Ruben Laban for his support. ! fix, MySQL plugin: the table name is now escaped in order to not conflict with reserved words, if one of those is selected. Thanks to Marcel Hecko for reporting the bug. ! An extra security check is being introduced in sfacctd as an unsupported extension sent over by a Foundry Bigiron 4000 kit was causing SEGV issues. Many Thanks to Michael Hoffrath for the strong support provided. ! fix, 'nfprobe' plugin: AS numbers were not correctly exported to the collector when pmacctd was in use. Patch is courtesy of Emerson Pinter. ! fix, 'nfprobe' plugin: MACs were not properly encapsulated resulting in wrong addresses being exported through NetFlow v9. The patch is courtesy of Alexander Bergolth. ! fix, buffers holding MAC address strings throughout the code had not enough space to store the trailing zero. The patch is courtesy of Alexander Bergolth. ! fix, logfile FD was not correctly passed onto active plugins. The patch is courtesy of Denis Cavrois. ! Missing field type 60 in NetFlow v9 IPv6 flows, was leading nfacctd to incorrect flow type selection (IPv4). An additional check on the source IP address has now been included to infer IPv6 flows. RFC3954 mandates such field type to be present for IPv6 flows. The issue has been verified against a Cisco 7600 w/ RSP720. Many thanks to Robert Blechinger for his extensive support. 0.11.4 -- 25-04-2007 + support for TCP flags has been introduced. Flags are ORed on a per-aggregate basis (same as what NetFlow does on a per-flow basis). The 'aggregate' directive now supports the 'tcpflags' keyword. SQL tables v7 have also been introduced in order to support the feature inside the SQL plugins. + 'nfacctd_sql_log' directive is being introduced. In nfacctd, it makes SQL plugins to use a) NetFlow's First Switched value as "stamp_inserted" timestamp and b) Last Switched value as "stamp_updated" timestamp. Then, a) by not aggregating flows and b) not making use of timeslots, this directive allows to log singular flows in the SQL database. + sfprobe and nfprobe plugins are now able to propagate tags to remote collectors through sFlow v5 and NetFlow v9 protocols. The 'tag' key must be appended to sfprobe/nfprobe 'aggregate' config directives. + pmacct memory client is now able to output either TopN bytes, flows or packets statistics. The feature is enabled by a new '-T' commandline switch. + The Pre-Tagging map is now dynamically allocated and a new 'pre_tag_map_entries' config directive allows to set the size of the map. Its default value (384) should be suitable for most common scenarios. ! Bugfix in nfprobe plugin: struct cb_ctxt was not initialized thus causing the application to exit prematurely (thinking it finished available memory). Thanks to Elio Eraseo for fixing the issue. ! Some misplaced defines were preventing 0.11.3 code to compile smoothly on OpenBSD boxes. Thanks to Dmitry Moshkov for fixing it. ! Bugfix in SQL handlers, MY_count_ip_proto_handler(): an array boundary was not properly checked and could cause the daemon to SEGV receiving certain packets. Thanks to Dmitry Frolov for debugging and fixing the issue. ! NF_counters_renormalize_handler() renormalizes sampled NetFlow v5 flows. It now checks whether a positive Sampling Rate value is defined rather than looking for the Sampling Mode. It makes the feature working on Juniper routers. Thanks once again to Inge Bjornvall Arnesen. 0.11.3 -- 31-01-2007 + 'aggregate_filter' directive now supports multiple pcap-style filters, comma separated. This, in turn, allows to bind up to 128 filters to each activated plugin. + nfacctd and sfacctd turn-back time when restarting the daemon has been significantly improved by both creating new listening sockets with SO_REUSEADDR option and disassociating them first thing on receiving SIGINT signal. + A new threaded version of pmacctd stream classification engine is being introduced. Code status is experimental and disabled by default; it could be enabled by providing --enable-threads at configure time. Many thanks to Francois Deppierraz and Eneo Tecnologia for contributing this useful piece of code. + A new 'flow_handling_threads' configuration directive allows to set the number of threads of the stream classification engine, by default 10. + A couple new '[ns]facctd_disable_checks' config directives aim to disable health checks over incoming NetFlow/sFlow streams (ie. in cases of non-standard vendor's implementations). Many thanks to Andrey Chernomyrdin for his patch. ! sfv245_check_status() was running checks (ie. verify sequence numbers) using sender's IP address. More correctly, it has to look at the Agent Address field included in sFlow datagrams. Many thanks to Juraj Sucik for spotting the issue. ! nfprobe plugin was not compiling properly in conjunction with --disable-l2 configure switch. Many thanks to Inge Bjornvall Arnesen for submitting the patch. ! sfacctd: fixed a bug which was preventing 'aggregate_filter' to match values properly in src_port, dst_port, ip proto and tos fields. Thanks to Chris Fletcher for spotting the issue. ! SQL cache: fixed a bug preventing safe actions to take place correctly. It has arisen in version 0.11.2 and hadn't severe impact. 0.11.2 -- 28-11-2006 + 'sql_max_writers' configuration directive is being introduced: sets the maximum number of concurrent writer processes the SQL plugin can fire, allowing the daemon to degrade gracefully in case of major database unavailibility. + 'sql_history_since_epoch' is being introduced: enables the use of timestamps (stamp_inserted, stamp_updated) in the standard seconds since the Epoch format as an alternative to the default date-time format. + 'sql_aggressive_classification' behaviour is changed: simpler more effective. It now operates by delaying cache-to-DB purge of unknown traffic streams - which would still have chances to be correctly classified - for a few 'sql_refresh_time' slots. The old mechanism was making use of negative UPDATE queries. + The way SQL writer processes are spawned by the SQL plugin has slightly changed in order to better exploit fork()'s copy-on- write behaviour: the writer now is mostly read-only while the plugin does most write operations before spawning the writer. ! The list of environment variables passed to the SQL triggers, 'sql_trigger_exec', has been updated. ! Fixed a bug related to sequence number checks for NetFlow v5 datagrams. Thanks very much to Peter Nixon for reporting it. 0.11.1 -- 25-10-2006 + PostgreSQL plugin: 'sql_use_copy' configuration directive has been introduced; instructs the plugin to build non-UPDATE SQL queries using COPY (in place of INSERT). While providing same functionalities of INSERT, COPY is more efficient. It requires 'sql_dont_try_update' to be enabled. Thanks to Arturas Lapiene for his support during the development. + nfprobe plugin: support for IPv4 ToS/DSCP, IPv6 CoS and MPLS top-most label has been introduced. ! Some alignment issues concerning both pkt_extras structure and Core process to Plugins memory rings have been fixed. Daemons are now reported to be running ok on MIPS/SPARC architectures. Many thanks to Michal Krzysztofowicz for his strong support. ! sfprobe plugin: a maximum default limit of 256 bytes is set on packet payload copy when building Flow Samples in pmacctd (ie. if capturing full packets through libpcap, we don't want them to be entirely copied into sFlow datagrams). ! Sanity checks now take place when processing 'sql_refresh_time' values and error messages are thrown out. ! Fixes have been committed to IPv6 code in xflow_status.c as it was not compiling properly on both Solaris and IRIX. 0.11.0 -- 27-09-2006 + NetFlow v5 sampling and renormalization are now supported: a) 'nfacctd' is able to renormalize bytes/packets counters and apply Pre-Tagging basing on the sampling rate specified in the datagram; b) 'sampling_rate' config key applies to 'nfprobe' plugin which is now able to generate sampling informations. + 'nfacctd' and 'sfacctd' are now able to give out informations about the status of active NetFlow/sFlow streams in terms of good/bad/missing datagrams. Whenever an anomaly happens (ie. missing or bad packets) a detailed message is logged; overral reports are logged by sending SIGUSR1 signals to the daemon. + 'logfile' configuration directive is introduced: it allows to log directly to custom files. This adds to console and syslog logging options. ! Old renormalization structure, renorm_table, has been dropped; the new one, which applies to both NetFlow and sFlow, is tied into the brand new xflow_status_table structure. ! When 'nfacctd_as_new' was not in use, NetFlow v5 src_as/dst_as values were erroneously swapped. Thanks to Thomas Stegbauer for reporting the bug. ! Incorrect timeout value for poll() has been fixed in 'sfprobe' plugin. It was leading the plugin to take too much resources. ! 'nfprobe' plugin was inserting jumps while generating sequence numbers. ! 'nfprobe' plugin behaviour in handling 'networks_file' content has been changed and now equals 'sfprobe': IP addresses which are not belonging to known networks/ASNs are no longer zeroed. ! 'sfprobe' was not generating correct sample_pool values. 0.11.0rc3 -- 30-08-2006 + 'sfprobe' plugin can now transport packet/flow classification tags inside sFlow v5 datagrams. Then, such tags can be read by the sFlow collector, sfacctd. + 'sfprobe' plugin is able to encapsulate basic Extended Gateway informations (src_as, dst_as) into sFlow v5 datagrams starting from a Networks File - networks_file configuration directive. + 'nfprobe' now supports network data coming from libpcap/tcpdump style savefile ('pcap_savefile', -I). + pmacctd is now able to capture packets from DLT_NULL, which is BSD loopback encapsulation link type. Thanks to Gert Burger for his support. + Sampling layer has been improved: it's now able to sample flows from NetFlow datagrams (not only packets arriving through sFlow or libpcap); 'sfprobe' sampling layer has been tied into this mechanism and as a result, 'sfprobe_sampling_rate' is now an alias for 'sampling_rate' and its default value is 1 (ie. no sampling). This change will benefit 'sfprobe' in terms of better efficiency. + A new 'pmacctd_flow_buffer_buckets' directive defines the number of buckets of the Flow Buffer. This value has to scale to higher power of 2 accordingly to the link traffic rate and is useful when packet classification is enabled. Many thanks for testing, debugging and support go to Steve Cliffe. + A new 'sql_locking_style' directive allows to choose among two types of locking: "table" (default) and "row". More details are in the CONFIG-KEYS document. "row" locking has to be considered as experimental. Many thanks go to Aaron Glenn and Peter Nixon for their close support, work and thoughts. ! IPv6 support is now working; it was broken in 0.11.0rc2; thanks to Nigel Roberts for signalling and fixing the issue. ! Fixed a few issues concerning the building system and related to the introduction of some new subtrees. Thanks to Kirill Ponomarew and Peter Nixon for signalling them. ! Fixed some signal()-related issues when running the package under DragonflyBSD. Being fork of FreeBSD 4.x, it needs same cautions. Thanks to Aaron Glenn for his support. 0.11.0rc2 -- 08-08-2006 + 'nfprobe' plugin can now transport packet/flow classification tags inside NetFlow v9 datagrams, using custom field type 200. Then, such tags can be read by the NetFlow collector, nfacctd. + 'nfprobe' plugin has now ability to select a Engine Type/Engine ID through a newly introduced 'nfprobe_engine' config directive. It will mainly allow a collector to distinguish between distinct probe instances originating from the same IP address. + 'nfprobe' plugin now can automagically select different NetFlow v9 template IDs, useful when multiple 'nfprobe' plugins run as part of the same daemon instance. + 'sfprobe' plugin is now able to redistribute NetFlow flows into sFlow samples. This adds to sFlow -> sFlow and libpcap -> sFlow. + A new data structure to pass extended data to specific plugins has been added. It is placed on the ring, next to pkt_data. It is meant to pass extra data to plugins and, same time, avoiding to inflate the main data structure. ! Wrong arguments were injected into a recently introduced Log() call in plugin_hooks.c; it's now fixed: under certain conditions, this was generating SEGV at startup while using 'sfprobe' plugin. ! Updated documentation; examples and quickstart guides for using pmacct as both emitter and collector of NetFlow and sFlow have been added. - Hooks to compile pmacct the no-mmap() style have been removed. 0.11.0rc1 -- 20-07-2006 + pmacct DAEMONS ARE NOW ABLE TO CREATE AND EXPORT NETFLOW PACKETS: a new 'nfprobe' plugin is available and allows to create NetFlow v1/v5/v9 datagrams and export them to a IPv4/IPv6 collector. The work is based on softflowd 0.9.7 software. A set of configuration directives allows to tune timeouts (nfprobe_timeouts), cache size (nfprobe_maxflows), collector parameters (nfprobe_receiver), TTL value (nfprobe_hoplimit) and NetFlow version of the datagrams to be exported (nfprobe_version). Many thanks to Ivan A. Beveridge, Peter Nixon and Sven Anderson for their support and thoughts and to Damien Miller, author of softflowd. + pmacct DAEMONS ARE NOW ABLE TO CREATE AND EXPORT SFLOW PACKETS: a new 'sfprobe' plugin is available and allows to create sFlow v5 datagrams and export them to a IPv4 collector. The work is based on InMon sFlow Agent 5.6 software. A set of configuration directives allows to tune sampling rate (sfprobe_sampling_rate), sFlow agent IP address (sfprobe_agentip), collector parameters (sfprobe_receiver) and agentSubId value (sfprobe_agentsubid). Many thanks to InMon for their software and Ivan A. Beveridge for his support. ! An incorrect pointer to the received packet was preventing Pre- Tagging filters to work correctly against DLT_LINUX_SLL links. Many thanks to Zhuang Yuyao for reporting the issue. ! Proper checks on protocol number were missing in pmacct client program, allowing to look further the bounds of the _protocols array. Many thanks to Denis N. Voituk for patching the issue. 0.10.3 -- 21-06-2006 + New Pre-Tagging key 'label': mark the rule with label's value. Labels don't need to be unique: when jumping, the first matching label wins. + New Pre-Tagging key 'jeq': Jump on EQual. Jumps to the supplied label in case of rule match. Before jumping, the tagged flow is returned to active plugins, as it happens for any regular match (set return=false to change this). In case of multiple matches for a signle flow, plugins showing 'tag' key inside 'aggregate' directive will receive each tagged copy; plugins not receiving tags will still receive unique copy of the flow. sFlow and NetFlow are usually uni-directional, ie. ingress-only or egress-only (to avoid duplicates). Meaningful application of JEQs is tagging flows two times: by incoming interface and by outgoing one. Only forward jumps are allowed. "next" is reserved label and causes to jump to the next rule. Many thanks to Aaron Glenn for brainstormings about this point. + New Pre-Tagging key 'return': if set to 'true' (which is default behaviour) returns the current packet/flow to active plugins, in case of match. If switched to 'false', it will prevent this to happen. It might be thought either as an extra filtering layer (bound to explicit Pre-Tagging rules) or (also in conjunction with 'stack') as a way to add flexibility to JEQs. + New Pre-Tagging key 'stack': actually '+' (ie. sum symbol) is the unique supported value. This key makes sense only if JEQs are in use. When matching, accumulate IDs, using the specified operator/ function. For example, usually =. By setting 'stack=+' you will be able to get =. ! Pre-Tagging table now supports a maximum of 384 rules. Because of the newly introduced flow alteration features, tables are no longer internally re-ordered. However, IPv4 and IPv6 stacks are still segregated each other. 0.10.2 -- 16-05-2006 + A new '-l' option is supported by pmacct client tool: it allows to enable locking of the memory table explicitely, when serving the requested operation. + Pre-Tagging infrastructure is now featuring negations for almost all supported keys with the exclusion of id, ip and filter. To negate, the '-' (minus symbol) need to be prepended; eg.: id=X ip=Y in=-1 means tag with X, data received from Net/sFlow agent with IP address Y and not coming from interface 1. + pre_tag_filter config directive is now featuring same negation capabilities as Pre-Tagging infrastructure. + Q16 added to FAQS document: a sum of tips for running smoothly SQL tables. Many thanks to Wim Kerkhoff and Sven Anderson for bringing up the points. 0.10.1 -- 18-04-2006 + AS numbers and IP addresses are no more multiplexed into the same field. This ends the limitation of being unable to have both data types in the same table (which could be useful for troubleshooting purposes, for example). A new SQL table version, v6, is introduced in order to support this new data model in all SQL plugins. ! Minor fixes to PostgreSQL table schemas, v2 to v5: a) the 'vlan' field was erroneously missing from primary keys, slowing down INSERT and UPDATE queries; b) primary keys were identified as 'acct_pk', thus not allowing multiple tables of different version to share the same database; now constraint name is: 'acct_vX_pk', with X being the version number. Many thanks to Sven Anderson for catching the a) ! An alignment issue has been catched when the etheraddr_string() gets called from count_src|dst_mac_handlers() in sql_handlers.c This seems to be closely connected to a similar trouble catched by Daniel Streicher on x86_64 recently. ! Fixed an issue with mask_elem() in server.c . Both src|dst_net primitives were not (positively, ie. copied back when required) masked. 0.10.0 -- 22-03-2006 + Collectors (ie. pmacctd) are now compiled exporting full Dynamic Symbol Table. This allows shared object (SO) classifiers to call routines included in the collector code. Moreover, a small set of library functions - specifically aimed to deal smoothly with the classifiers' table - are now included in the collector code: pmct_un|register(), pmct_find_first|last_free(), pmct_isfree(), pmct_get() and pmct_get_num_entries(). For further reading, take a look to README.developers document in classifiers tarball. + Classifiers table, which is the linked-list structure containing all the active classifiers (RE + SO), is now loaded into a shared memory segment, allowing plugins to keep updated about changes to the table. Furthermore, the table is now dynamically allocated at runtime, allowing an arbitrary number of classifiers to be loaded via the new 'classifier_table_num' configuration directive. + Pre-Tagging infrastructure adds two new primitives to tag network traffic: src_as and dst_as, the source and destination Autonomous System Number (ASN). In pmacctd they work against a Network Map ('networks_file' configuration directive). In nfacctd and sfacctd they work against both sFlow/NetFlow ASN fields and Network Maps. Many thanks to Aaron Glenn for his strong support. ! PostgreSQL plugin and pmpgplay no more make use of EXCLUSIVE LOCKS whenever the sql_dont_try_update directive is activated. We assume there is no need for them in a INSERTs-only framework as integrity of data is still guaranteed by transactions. The patch has been contributed by Jamie Wilkinson, many thanks ! ! Commandline switches and a configuration file should cohexist and the formers need to take precedence over the latter, if required. This is a rather standard (and definitely more flexible) approach; before this release they were mutual exclusive. Read UPGRADE notes at this propo. Thanks for the suggestion to Ivan A. Beveridge. ! Some glibc functions (noticeably syslog()) rely upon a rather non- standard "extern char *__progname" pointer. Now, its existence is properly checked at configuration time. On Linux, setproctitle() was causing plugin name/type to get cutted down in messages sent to the syslog facility. Thanks to Karl Latiss for his bug report. ! Solved a bug involving the load of IPv6 entries from Networks Maps. It was causing the count of such entries to be always zero. 0.10.0rc3 -- 01-03-2006 + Aapplication layer (L7) classification capabilities of pmacctd have been improved: shared object (SO) classifiers have been introduced; they are loaded runtime through dlopen(). pmacct offers them support for contexts (informations gathered - by the same classifier - from previous packets either in the same uni-directional flow or in the reverse one), private memory areas and lower layer header pointers, resulting in extra flexibility. Some examples can be found at the webpage: http://www.ba.cnr.it/~paolo/pmacct/classification/ + 'classifier_tentatives' configuration key has been added: it allows to customize the number of tentatives made in order to classify a flow. The default number is five, which has proven to be ok but for certain types of classification it might result restrictive. + 'pmacctd_conntrack_buffer_size' configuration key has been added: it (intuitively) defines the size for the connection tracking buffer. + Support for Token Ring (IEEE 802.5) interfaces has been introduced in pmacctd. Many thanks to Flavio Piccolo for his strong support. + 'savefile_wait' (-W commandline) configuration key has been added: if set to true causes pmacctd to not return but wait to be killed after being finished with the supplied savefile. Useful when pushing data from a tcpdump/ethereal tracefile into a memory table (ie. to build graphs). ! An erroneous replacement of dst with src in mask_elem() was causing queries like "pmacct -c dst_host -M|-N " to return zero counters. Thanks to Ryan Sleevi for signalling the weird behaviour. ! Management of the connection tracking buffer has been changed: now, a successful search frees the matched entry instead of moving it in a chain of stale entries, available for quick reuse. ! Error logging of SQL plugins has been somewhat improved: now, error messages returned by the SQL software are forwarded to sql_db_error() This will definitely allow to exit from the obscure crypticism of some generic error strings. 0.10.0rc2 -- 14-02-2006 + CONNECTION TRACKING modules has been introduced into pmacctd: they are C routines that hint IP address/port couples for upcoming data streams as signalled by one of the parties into the control channel whenever is not possible to go with a RE classificator. Conntrack modules for FTP, SIP and RTSP protocols are included. + 'pidfile' directive way of work has been improved: firstly, whenever a collector shuts down nicely, it now removes its pidfile. Secondly, active plugins now create a pidfile too: it takes the following form: -.. Thanks to Ivan A. Beveridge for sharing his thoughts at this propo. ! Minor fixes to the classification engine: TCP packets with no payload are not considered useful classification tentatives; a new flow can inherit the class of his reverse flow whenever it's still reasonably valid. ! Solved a segmentation fault issue affecting the classificator engine, whenever the 'snaplen' directive was not specified. Thanks to Flavio Piccolo for signalling it. ! Fixed a bug in the PostgreSQL plugin: it appeared in 0.10.0rc1 and was uniquely related to the newly introduced negative UPDATE SQL query. ! INTERNALS has been updated with few notes about the new classification and connection tracking features. 0.10.0rc1 -- 24-01-2006 + PACKET CLASSIFICATION capabilities have been introduced into pmacctd: the implemented approach is fully extensible: classification patterns are based on regular expressions (RE), human-readable, must be placed into a common directory and have a .pat file extension. Many patterns for widespread protocols are available at L7-filter project homepage. To support this feature, a new 'classifiers' configuration directive has been added. It expects full path to a spool directory containing the patterns. + A new 'sql_aggressive_classification' directive has been added aswell: it allows to move unclassified packets even in the case they are no more cached by the SQL plugin. This aggressive policy works by firing negative UPDATE SQL queries that, whenever successful, are followed by positive ones charging the extra packets to their final class. ! Input and Output interface fields (Pre-Tagging) have been set to be 32 bits wide. While NetFlow is ok with 16 bits, some sFlow agents are used to bigger integer values in order to identify their interfaces. The fix is courtesy of Aaron Glenn. Thank you. ! Flow filtering troubles have been noticed while handling MPLS-tagged flows inside NetFlow v9 datagrams. Thanks to Nitzan Tzelniker for his cooperation in solving the issue. ! A new exit_all() routine now handles nicely fatal errors detected by the Core Process, after plugins creation. It avoids leaving orphan plugins after the Core Process shutdown. 0.9.6 -- 27-Dec-2005 + Support for 'sql_multi_values' has been introduced into the new SQLite 3.x plugin. It allows to chain multiple INSERT queries into a single SQL statement. The idea is that inserting many rows at the same time is much faster than using separate single-row statements. ! MySQL plugin fix: AS numbers were sent to the database unquoted while the corresponding field was declared as CHAR. By correctly wrapping AS numbers, a major performance increase (expecially when UPDATE queries are spawned) has been confirmed. Many thanks to Inge Bjørnvall Arnesen for discovering, signalling and solving the issue. ! MySQL plugin fix: multi-values INSERT queries have been optimized by pushing out of the queue purging loop the proper handling for the EOQ event. ! The introduction of the intermidiate SQL layer in the 0.9.5 version choked the dynamic SQL table creation capability. This has been fixed. Thanks to Vitalij Brajchuk for promptly signalling the issue. ! The 'pidfile' configuration key has got incorrectly disabled in both nfacctd and sfacctd. Thanks to Aaron Glenn for signalling the issue. ! The 'daemonize' (-D) configuration key was incorrectly disabling the signal handlers from the Core Process once backgrounded. As a result the daemon was not listening for incoming SIGINTs. Again, many thanks go to Aaron Glenn. 0.9.5 -- 07-Dec-2005 + PMACCT OPENS TO SQLITE 3.x: a fully featured SQLite, version 3.x only, plugin has been introduced; SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL (almost all SQL92) database engine. The plugin is LOCK-based and supports the "recovery mode" via an alternate database action. Expecially suitable for tiny and embedded environments. The plugin can be fired using the keyword 'sqlite3'. See CONFIG-KEYS and EXAMPLES for further informations. + A new SQL layer - common to MySQL, PostgreSQL and SQLite plugins - has been introduced. It's largely callback-based and results in a major architectural change: it sits below the specific SQL code (facing the Core Process's abstraction layer) and will (hopefully) help in reducing potential bugs and will allow for a quick implementation of new SQL plugins. ! A bug concerning the setup of insert callback functions for summed (in + out) IPv6 traffic has been fixed. The issue was affecting all SQL plugins. ! A bug concerning the handling of MPLS labels has been fixed in pmacctd. Many thanks to Gregoire Tourres and Frontier Online for their support. 0.9.4p1 -- 14-Nov-2005 ! Minor bugfix in pretag.c: a wrongly placed memcpy() was preventing the code to be compiled by gcc 2.x . Many thanks to Kirill Ponomarew and Kris Kennaway for signalling the issue. ! Fixed an alignment issue revealed in the query_header structure; it has been noticed only under some circumstances: '--enable-64bit' enabled, 64bit platform and gcc 3.x . Many thanks to Aaron Glenn for his strong support in solving the issue. 0.9.4 -- 08-Nov-2005 + Hot map reload has been introduced. Maps now can be modified and then reloaded without having to stop the daemon. SIGUSR2 has been reserved for this use. The feature applies to Pre-Tagging map (pre_tag_map), Networks map (networks_file) and Ports map (ports_file). It is enabled by default and might be disabled via the new 'refresh_maps' configuration directive. Further details are in CONFIG-KEYS. ! Some major issues have been solved in the processing of libpcap-format savefiles. Some output inconsistencies were caused by a corruption of the pcap file handler; bufferization is now enabled by default and the last buffer is correctly processed. Many thanks go to Amir Plivatsky for his strong support. ! 'sql_table_schema' directive: in read_SQLquery_from_file() the strchr() has been replaced by strrchr() allowing to chain more SQL statements as part of the SQL table creation. This results useful, for example, to do CREATE INDEX after CREATE TABLE. The patch is courtesy of Dmitriy Nikulin. ! SIGTERM signal is now handled properly to ensure a better compatibility of all pmacct daemons under the daemontools framework. The patch is courtesy of David C. Maple. ! Memory plugin: some issues caused by the mix of not compatible compilation parameters have been fixed. Now the pmacct client now correctly returns a warning message if: counters are of different size (32bit vs 64bit) or IP addresses are of different size (IPv4-only vs IPv6-enabled packages). ! Print plugin, few bugfixes: the handling of the data ring shared with the Core Process was not optimal; it has been rewritten. P_exit() routine was not correctly clearing cached data. 0.9.3 -- 11-Oct-2005 + IPv4/IPv6 multicast support has been introduced in the NetFlow (nfacctd) and the sFlow (sfacctd) daemons. A maximum of 20 multicast groups may be joined by a single daemon instance. Groups can be defined by using the two sister configuration keys: nfacctd_mcast_groups and sfacctd_mcast_groups. + sfacctd: a new 'sfacctd_renormalize' config key allows to automatically renormalize byte/packet counters value basing on informations acquired from the sFlow datagram. In particular, it allows to deal with scenarios in which multiple interfaces have been configured at different sampling rates. It also calculates an effective sampling rate which could differ from the configured one - expecially at high rates - because of various losses. Such estimated rate is then used for renormalization purposes. Many thanks go to Arnaud De-Bermingham and Ovanet for the strong support offered during the development. + sfacctd: a new 'sampling_rate' keyword is supported into the Pre-Tagging layer. It allows to tag aggregates - generated from sFlow datagrams - on a sampling rate basis. + setproctitle() calls have been introduced (quite conservatively) and are actually supported on Linux and BSDs. The process title is rewritten in the aim of giving the user more informations about the running processes (that is, it's not intended to be just a cosmetic stuff). ! sql_preprocess tier was suffering a bug: actions (eg. usrf, adjb), even if defined, were totally ignored if no checks were defined aswell. Many thanks to Draschl Clemens for signalling the issue. ! Some minor bugs have been catched around sfacctd and fixed accordingly. Again, many thanks to Arnaud De-Bermingham. 0.9.2 -- 14-Sep-2005 + A new 'usrf' keyword is now supported into the 'sql_preprocess' tier: it allows to apply a generic uniform renormalization factor to counters. Its use is particularly suitable for use in conjunction with uniform sampling methods (for example simple random - e.g. sFlow, 'sampling_rate' directive or simple systematic - e.g. sampled NetFlow by Cisco and Juniper). + A new 'adjb' keyword is now supported into the 'sql_preprocess' tier: it allows to add (or subtract in case of negative value) 'adjb' bytes to the bytes counter. This comes useful when fixed lower (link, llc, etc.) layer sizes need to be included into the bytes counter (as explained by the Q7 in the updated FAQS document). + A new '--enable-64bit' configuration switch allows to compile the package with byte/packet/flow counters of 64bit (instead of the usual 32bit ones). ! The sampling algorithm endorsed by the 'sampling_rate' feature has been enhanced to a simple randomic one (it was a simple systematic). ! Some static memory structures are now declared as constants allowing to save memory space (given the multi-process architecture) and offering an overral better efficiency. The patch is courtesy of Andreas Mohr. Thanks. ! Some noisy compiler warnings have been troubleshooted along with some minor code cleanups; the contribution is from Jamie Wilkinson. Thanks. ! Some unaligned pointer issues have been solved. 0.9.1 -- 16-Aug-2005 + Probabilistic, flow size dependent sampling has been introduced into the 'sql_preprocess' tier via the new 'fss' keyword: it is computed against the bytes counter and returns renormalized results. Aggregates which have collected more than the 'fss' threshold in the last time window are sampled. Those under the threshold are sampled with probability p(bytes). For further details read the CONFIG-KEYS and the paper: - N.G. Duffield, C. Lund, M. Thorup, "Charging from sampled network usage" http://www.research.att.com/~duffield/pubs/DLT01-usage.pdf + Probabilistic sampling under hard resource constraints has been introduced into the 'sql_preprocess' tier via the new 'fsrc' keyword: it is computed against the bytes counter and returns renormalized results. The method selects only 'fsrc' flows from the set of the flows collected during the last time window, providing an unbiasied estimate of the real bytes counter. For further details read the CONFIG-KEYS and the paper: - N.G. Duffield, C. Lund, M. Thorup, "Flow Sampling Under Hard Resource Constraints" http://www.research.att.com/~duffield/pubs/DLT03-constrained.pdf + A new 'networks_mask' configuration directive has been introduced: it allows to specify a network mask - in bits - to be applied apply to src_net and dst_net primitives. The mask is applied before evaluating the content of 'networks_file' (if any). + Added a new signal handler for SIGUSR1 in pmacctd: a 'killall -USR1 pmacctd' now returns a few statistics via either console or syslog; the syslog level reserved for such purpose is the NOTICE. ! sfacctd: an issue regarding non-IP packets has been fixed: some of them (mainly ARPs) were incorrectly reported. Now they are properly filtered out. ! A minor memory leak has been fixed; it was affecting running instances of pmacctd, nfacctd and sfacctd with multiple plugins attached. Now resources are properly recollected. 0.9.0 -- 25-Jul-2005 + PMACCT OPENS TO sFlow: support for the sFlow v2/v4/v5 protocol has been introduced and a new daemon 'sfacctd' has been added. The implementation includes support for BGP, MPLS, VLANs, IPv4, IPv6 along with packet tagging, filtering and aggregation capabilities. 'sfacctd' makes use of Flow Samples exported by a sFlow agent while Counter Samples are skipped and the MIB is ignored. All actually supported backends are available for storage: MySQL, PostgreSQL and In-Memory tables. http://www.sflow.org/products/network.php lists the network equipments supporting the sFlow protocol. + A new commandline option '-L' is now supported by 'nfacctd' and 'sfacctd'; it allows to specify an IPv4/IPv6 address where to bind the daemon. It is the equivalent for the 'nfacctd_ip' and 'sfacctd_ip' configuration directives. ! The NetFlow v9 MPLS stack handler has been fixed; it now also sticks the BoS bit (Bottom of the Stack) to the last processed label. This makes the flow compliant to BPF filters compiled by the newly released libpcap 0.9.3. ! Some Tru64 compilation issues related to the ip_flow.[c|h] files have been solved. ! Some configuration tests have been added; u_intXX_t definitions are tested and fixed (whenever possible, ie. uintXX_t types are available). Particularly useful on Solaris and IRIX platforms. ! Configuration hints for MySQL headers have been enhanced. This will ease the compilation of pmacct against MySQL library either from a precompiled binary distribution or from the FreeBSD ports. Many hhanks for the bug report go to John Von Essen. ! NetFlow v8 source/destination AS handlers have been fixed. 0.8.8 -- 27-Jun-2005 + Added IP flows support in pmacctd (release 0.8.5 has seen its introduction in nfacctd) for both IPv4 and IPv6 handlers. To enable flows accounting, the 'aggregate' directive now supports a new 'flows' keyword. The SQL table v4 has to be used in order to support this feature in both SQL plugins. + A new 'sum_mac' aggregation method has been added (this is in addition to the already consolidated ones: 'sum_host', 'sum_net', 'sum_as', 'sum_port'). Sum is intended to be the total traffic (inbound traffic summed to outbound one) produced by a specific MAC address. + Two new configuration directives have been introduced in order to set an upper bound to the growth of the fragment (default: 4Mb) and flow (default: 16Mb) buffers: 'pmacctd_frag_buffer_size', 'pmacctd_flows_buffer_size'. + A new configuration directive 'pmacctd_flow_lifetime' has been added and defines how long a flow could remain inactive (ie. no packets belonging to such flow are received) before considering it expired (default: 60 secs). This is part of the pmacctd IP flows support. + Console/syslog feedbacks about either generic errors or malformed packets have been greatly enhanced. Along with the cause of the message, now any generated message contains either the plugin name/type or the configuration file that is causing it. ! nfacctd: when IPv6 is enabled (on non-BSD systems) the daemon now listens by default on a IPv6 socket getting rid of the v4-in-v6 mapping feature which helps in receiving NetFlow datagrams from both IPv4 and IPv6 agents. A new configure script switch --enable-v4-mapped is aimed to turn manually on/off the feature. ! Fixed an issue with the SIGCHLD handling routine on FreeBSD 4.x systems. It was causing the sudden creation of zombie processes because of the not correct retirement of exited childs. Many thanks for his bug report and strong support go to John Von Essen. ! Fixed an endianess issue regarding Solaris/x86 platforms caused by not proper preprocessor tests. Many thanks to Imre Csatlos for his bug report. ! Fixed the default schema for the PostgreSQL table v4. The 'flows' field was lacking of the 'DEFAULT 0' modifier; it was causing some troubles expecially when such tables were used in conjunction with the 'sql_optimize_clauses' directive. Many thanks for his bug report and strong support go to Anik Rahman. 0.8.7 -- 14-Jun-2005 + pmacctd: MPLS support has been introduced. MPLS (on ethernet and ppp links) and MPLS-over-VLAN (ethernet only) packets are now supported and passed to upper layer routines. Filtering and tagging (Pre-Tagging) packets basing on MPLS labels is also supported. Recent libpcap is required (ie, CVS versions >= 06-06-2005 are highly adviceable because of the support for MPLS label hierarchies like "mpls 100000 and mpls 1024" that will match packets with an outer label of 100000 and an inner label of 1024). + nfacctd: VLAN and MAC addresses support for NetFlow v9 has been introduced. Each of them is mapped to its respective primitive (vlan, src_mac, dst_mac); filtering and tagging (Pre-Tagging) IPv4/IPv6 flows basing on them is also supported. + nfacctd: filtering and tagging (Pre-Tagging) IPv4/IPv6 flows basing on MPLS labels has been introduced (read the above notes regarding libpcap version requirements). + A new packet capturing size option has been added to pmacctd ('snaplen' configuration directive; '-L' commandline). It allows to change the default portion of the packet captured by the daemon. It results useful to cope with not fixed protocol stacks (ie, the MPLS stack). + pmacctd: CHDLC support has been introduced. IPv4, IPv6 and MPLS packets are supported on this link layer protocol. ! Cleanups have been added to the NetFlow packet processing cycle. They are mainly aimed to ensure that no stale data is read from circular buffers when processing NetFlow v8/v9 packets. ! The NetFlow v9 VLAN handling routine was missing a ntohs() call, resulting in an ncorrect VLAN id on little endian architectures. ! ether_aton()/ether_ntoa() routines were generating segmentation faults on x86_64 architectures. They have been replaced by a new handmade couple: etheraddr_string()/string_etheraddr(). Many thanks to Daniel Streicher for the bug report. 0.8.6 -- 23-May-2005 + The support for dynamic SQL tables has been introduced through the use of the following variables in the 'sql_table' directive: %d (the day of the month), %H (hours using an 24 hours clock), %m (month number), %M (minutes), %w (the day of the week as a decimal number), %W (week number in the current year) and %Y (the current year). This enables, for example, substitutions like the following ones: 'acct_v4_%Y%m%d_%H%M' ==> 'acct_v4_20050519_1500' 'acct_v4_%w' ==> 'acct_v4_05' + A new 'sql_table_schema' configuration directive has been added in order to allow the automatic creation of dynamic tables. It expects as value the full pathname to a file containing the schema to be used for table creation. An example of the schema follows: CREATE TABLE acct_v4_%Y%m%d_%H%M ( ... PostgreSQL/MySQL specific schema ... ); + Support for MySQL multi-values INSERT clauses has been added. Inserting many rows in a single shot has proven to be much faster (many times faster in some cases) than using separate single INSERT statements. A new 'sql_multi_values' configuration directive has been added to enable this feature. Its value is intended to be the size (in bytes) of the multi-values buffer. Out of the box, MySQL >= 4.0.x supports values up to 1024000 (1Mb). Because it does not require any changes on server side, people using MySQL are strongly encouraged to give it a try. + A new '--disable-l2' configure option has been added. It is aimed to compile pmacct without support for Layer-2 stuff: MAC addresses and VLANs. This option - along with some more optimizations to memory structures done in this same release - have produced memory savings up to 25% compared to previous versions. ! Recovery code for PostgreSQL plugin has been slightly revised and fixed. 0.8.5 -- 04-May-2005 + Added IP flows counter support in nfacctd, the NetFlow accounting daemon, in addition to the packets and bytes ones. To enable flows accounting, the 'aggregate' directive now supports a new 'flows' keyword. A new SQL table version, v4, has been also introduced to support this feature in both SQL plugins. + 'sql_preprocess' directive have been strongly improved by the addition of new keywords to handle thresholds. This preprocessing feature is aimed to process aggregates (via a comma-separated list of conditionals and checks) before they are pulled to the DB, thus resulting in a powerful selection tier; whether the check is meet, the aggregate goes on its way to the DB; the new thresholds are: maxp (maximum number of packets), maxb (maximum bytes transferred), minf/maxf (minimum/maximum number of flows), minbpp/maxbbp (minimum/maximum bytes per packet average value), minppf/maxppf (minimum/ maximum packets per flow average value). + Added a new 'sql_preprocess_type' directive; the values allowed are 'any' or 'all', with 'any' as default value. It is intended to be the connective whether 'sql_preprocess' contains multiple checks. 'any' requires that an aggregate has to match just one of the checks in order to be valid; 'all' requires a match against all of the checks instead. + Added the ability to instruct a BPF filter against the ToS field of a NetFlow packet. ! Minor optimizations on the 'sql_preprocess' handler chain. 0.8.4 -- 14-Apr-2005 + Added support for NetFlow v7/v8. The Version 7 (v7) format is exclusively supported by Cisco Catalyst series switches equipped with a NetFlow feature card (NFFC). v7 is not compatible with Cisco routers. The Version 8 (v8) format adds (with respect to older v5/v7 versions) router-based aggregation schemes. + Added the chance to tag packets basing on NetFlow v8 aggregation type field. As the keyword suggests, it will work successfully just when processing NetFlow v8 packets. Useful to split - backend side - data per aggregation type. + pmacct client now is able to ask for the '0' (that is, untagged packets) tag value. Moreover, all 'sum' aggregations (sum_host, sum_net, sum_as, sum_port) can now be associated with both Pre/Post-Tagging. ! Fixed a serious memory leak located in the routines for handling NetFlow v9 templates. While the bug was needing certain conditions to manifest, anyone using NetFlow v9 is strongly encouraged to upgrade to this version. All previous versions were affected. ! Some gcc4 compliance issues have been solved. The source code is known to work fine on amd64 architectures. Thanks very much to Marcelo Goes for his patch. ! Engine Type/Engine ID fields were not correctly evaluated when using NetFlow v5 and Pre-Tagging. The issue has been fixed. ! Long comments in the Ports Definition File were causing some incorrect error messages. However it seems the file were processed correctly. Thanks to Bruno Mattarollo for signalling the issue. ! Minor fix to plugins hooking code. The reception of sparse SIGCHLD signals were causing the poll() to return. The impact was null. The issue has been fixed by ignoring such signals. 0.8.3 -- 29-Mar-2005 + Pre-Tagging capabilities have been further enhanced: captured traffic can be now marked basing on the NetFlow nexthop/BGP nexthop fields. While the old NetFlow versions (v1, v5) carry an unique 'nexthop' field, NetFlow v9 supports them into two distinguished fields. + Packet/flows tagging is now explicit, gaining more flexibility: a new 'tag' keyword has been added to the 'aggregate' directive. It causes the traffic to be actually marked; the 'pre_tag_map' and 'post_tag' directives now just evaluate the tag to be assigned. Read further details about this topic in the UPGRADE document. + The 'pre_tag_filter' directive now accepts 0 (zero) as valid value: we have to remember that zero is not a valid tag; hence, its support allows to split or filter untagged traffic from tagged one. + Documentation has been expanded: a new FAQS entry now describes few and easy tweaks needed to replace the bytes counter type from u_int32_t to u_int64_t throughout the code (provided that the OS supports this type); it's useful in conjunction with the In-Memory plugin while exposed to very sustained traffic loads. A new FAQS entry describes the first efforts aimed to integrate pmacctd with popular flow-tools software by the way of the flow-export tool. A new UPGRADE document has been also created. ! pmacct client was handling counters returned by the '-N' switch as signed integers, which is not correct. The issue has been fixed. Many thanks to Tobias Bengtsson for signalling it. ! Two new routines file_lock()/file_unlock() have replaced the flock() calls because they were preventing the pmacct code to compile on Solaris. Basing over hints collected at configure time, the routines enable either the flock() or fcntl() code. Many thanks to Jan Baumann for signalling and solving the issue. 0.8.2 -- 08-Mar-2005 + Pre-Tagging capabilities have been enhanced: now, a Pre Tag Map allows to mark either packets or flows basing on the outcome of a BPF filter. Because of this new feature, Pre-tagging has been introduced in 'pmacctd' too. Pre-tagging was already allowing 'nfacctd' to translate some NetFlow packet fields (exporting agent IP address, Input/Output interface, Engine type and Engine ID) into an ID (also referred as 'tag'), a small number in the range 1-65535. + A new 'pmacctd_force_frag_handling' configuration directive has been added; it aims to support 'pmacctd' Pre-Tagging operations: whether the BPF filter requires tag assignation based on transport layer primitives (e.g. src port or dst port), this directive ensures the right tag is stamped to fragmented traffic too. + Pre Tag filtering (which can be enabled via 'pre_tag_filter' configuration directive) allows to filter aggregates basing on the previously evaluated ID: whether it matches with at least one of the filter values, the aggregate is delivered to the plugin. It has been enhanced by allowing to assign more tags to a specific plugin. + pmacctd: a new feature to read libpcap savefiles has been added; it can be enabled either via the 'pcap_savefile' configuration directive or the '-I' commandline switch. Files need to be already closed and correctly finalized in order to be read successfully. Many thanks to Rafael Portillo for proposing the idea. + pmacct client tool supports a new 'tag' keyword as value for the '-c' switch: it allows to query the daemon requesting a match against aggregate tags. + pmacct client: the behaviour of the '-N' switch (which makes the client to return a counter onto the screen suitable for data injection in tools like MRTG, Cacti, RRDtool, etc.), has been enhanced: it was already allowing to ask data from the daemon but basing only on exact matches. This concept has now extended, adding both wildcarding of specific fields and partial matches. Furthermore, when multiple requests are encapsulated into a single query, their results are by default splitted (that is, each request has its result); a newly introduced '-S' switch now allows to sum multiple results into a single counter. ! Bugfix: proper checks for the existence of a 'pre_tag_map' file were bypassed under certain conditions; however, this erroneous behaviour was not causing any serious issue. The correct behaviour is to quit and report the problem to the user. ! The sampling rate algorithm has been fixed from a minor issue: it was returning not expected results when 'sampling_rate: 1'. It now works as expected. Thanks to David C. Maple for his extensive support in gaining a better understanding of the problem. 0.8.1p1 -- 22-Feb-2005 ! 'sum_host' and 'sum_net' compound primitives have been fixed in order to work with IPv6 addresses. ! In-Memory Plugin: client queries spotted with both '-r' (reset counters) and '-N' (exact match, print counters only) switches enabled were causing the daemon to crash whether no entries were found. The problem has been fixed. Many thanks to Zach Chambers for signalling the issue. ! In-Memory Plugin: client queries spotted with either '-M' or '-N' switches enabled were failing to match actual data when either 'sum_host', 'sum_net' or 'sum_as' primitives were in use. The issue has been fixed. ! The modulo function applied to NetFlow v9 Template Cache has been enhanced in order to deal correctly with export agents having an IPv6 address. ! Networks/AS definition file: a new check has been added in order to verify whether network prefix/network mask pairs are compatible: if they are not, the mask is applied to the prefix. ! Documentation has been expanded and revised. 0.8.1 -- 25-Jan-2005 + Accounting and aggregation over DSCP, IPv4 ToS field and IPv6 traffic class field have been introduced ('aggregate' directive, 'tos' value): these fields are actually widely used to implement Layer-3 QoS policies by defining new classes of service (most noticeably 'Less than Best Effort' and 'Premium IP'). MySQL and PostgreSQL tables v3 (third version) have been introduced (they contain an additional 4-bytes 'tos' field) to support the new Layer-3 QoS accounting. + nfacctd core process has been slightly optimized: each flow is encapsulated (thus, copied field-by-field) into a BPF-suitable structure only if one or more plugins actually require BPF filtering ('aggregate_filter' directive). Otherwise, if either filtering is not required or all requested filters fail to compile, the copy is skipped. + 'pmacct', pmacct client tool: '-e' commandline option (which meaning is: full memory table erase) now might be supplied in conjunction with other options (thus avoiding the short time delays involved by two consecutive queries, ask-then-erase, which may also lead to small losses). The new implemented mechanism works as follow: queries over actual data (if any) are served before; the table is locked, new aggregates are queued until the erasure finishes (it may take seconds if the table is large enough); the table is unlocked; the queue of aggregates is processed and all normal operations are resumed. Many thanks to Piotr Gackiewicz for the valuable exchange of ideas. ! Bug fixed in nfacctd: source and destination AS numbers were incorrectly read from NetFlow packets. Thanks to Piotr Gackiewicz for his support. ! Bug fixed in pmacct client: while retrieving the whole table content was displaying espected data, asking just for 'dst_as' field was resulting in no results instead. Thanks, once more, to Piotr Gackiewicz. 0.8.0 -- 12-Jan-2005 + PMACCT OPENS TO IPv6: IPv6 support has been introduced in both 'pmacctd' and 'nfacctd' daemons. Because it requires larger memory structures to store its addresses, IPv6 support has been disabled by default. It could be enabled at configure time via '--enable-ipv6' switch. All filtering, tagging and mapping functions already support IPv6 addresses. Some notes about IPv6 and SQL table schema have been dropped into README.IPv6 file, sql section of the tarball. + PMACCT OPENS TO NetFlow v9: support for the template-based Cisco NetFlow v9 export protocol has been added. NetFlow v1/v5 were already supported. 'nfacctd' may now be bound to an IPv6 interface and is able to read both IPv4 and IPv6 data flowsets. A single 'nfacctd' instance may read flows of different versions and coming from multiple exporting agents. Source and destination MAC addresses and VLAN tags are supported in addition to the primitives already supported in v1/v5 (source/destination IP addresses, AS, ports and IP protocol). Templates are cached and refreshed as soon as they are resent by the exporting agent. + Pre Tag map ('pre_tag_map' configuration key), which allows to assign a small integer (ID) to an incoming flow basing on NetFlow auxiliar data, now may apply tags basing also over Engine Type (it provides uniqueness with respect to the routing engine on the exporting device) and Engine ID (it provides uniqueness with respect to the particular line card or VIP on the exporting device) fields. Incoming and Outcoming interfaces were already supported. See 'pretag.map.example' into tarball examples section and CONFIG-KEYS document for further details. + Raw protocol (DLT_RAW) routine has been added; it usually allows to read data from tunnels and sitX devices (used for IPv6-in-IPv4 encapsulation). + Some tests for architecture endianess, CPU type and MMU unaligned memory access capability have been added. A small and rough (yes, they work the hard way) set of unaligned copy functions have been added. They are aimed to be introduced through the code, however first tests over MIPS R10000 and Alpha EV67 (21264A) have shown positive results. ! PPPoE and VLAN layer handling routines have been slightly revised for some additional checks. ! Given the fairly good portability reported from the mmap() code introduced through the whole 0.7.x development stage, the use of shared memory segments is now enabled by default. The configure switch '--enable-mmap' has been replaced by '--disable-mmap'. ! 'pmacct' client tool: because of the IPv6 addresses introduction, separator character for multiple queries (commandline) have been changed to from ':' to ';'. ! 'nfacctd': '-F' commandline switch was listed into available options list, but getopt() stanza was missing, thus returning an invalid option message. Thanks to Chris Koutras for his support in fixing the issue. ! Some variable assignations were causing lvalue errors with gcc 4.0. Thanks to Andreas Jochens for his support in signalling and solving the problem. 0.7.9 -- 21-Dec-2004 + A new data pre-processor has been introduced in both SQL plugins: it allows to filter out data (via conditionals, checks and actions) during a cache-to-DB purging event, before building SQL queries; this way, for example, aggregates which have accounted just a few packets or bytes may be either discarded or saved through the recovery mechanism (if enabled). The small set of preprocessing directives is reported into CONFIG-KEYS document. + Some new environment variables are now available when firing a trigger from SQL plugins: $EFFECTIVE_ELEM_NUMBER reports the effective number of aggregates (that is, excluding those filtered out at preprocessing time) encapsulated in SQL queries; $TOTAL_ELEM_NUMBER reports the total number of aggregates instead. $INSERT_QUERIES_NUMBER and $UPDATE_QUERIES_NUMBER returns respectively the number of aggregates being successfully encapsulated into INSERT and UPDATE queries. $ELAPSED_TIME reports the time took to complete the last purging event. For further details and the list of supported environment variables take a look to TRIGGER_VARS document. + Some additions to both logfile players: a new '-n' switch allows to play N elements; this way, arbitrary portions of the file may be played using '-n' in conjunction with the (already existing) '-o' switch which allows to read the logfile starting at a specified offset. New switches '-H', '-D', '-T', '-U', '-P' have been introduced to override SQL parameters like hostname, DB, table, user and password. The '-t -d' combination (test only, debug) now allows to print over the screen the content of the logfile. + Logfiles size is now limited to a maximum of 2Gb, thus avoiding issues connected to the 32bit declaration of off_t. While many OS implment a solution to the problem, seems there are few chances to solve it in a portable way. When the maximum size is hit the old logfile is rotated appending to its filename a trailing small integer ( in a way similar to logrotate) and a fresh one is started. ! Logfile players: '-s' switch, which was allowing to play one element a time, has been superseded. Its current equivalent is: '-n 1'. ! The file opening algorithm has been slightly changed in SQL plugins: flock() follows shortly the fopen() and all subsequent operations and evaluations are thus strictly serialized. freopen() is avoided. 0.7.8 -- 02-Dec-2004 + Recovery logfile structure has been enhanced. Following the logfile header has been created a new template structure. Templates will avoid the issue of being not able to read old logfiles because of changes to internal data structures. Templates are made of an header and a number of entries, each describing a single field of the following data. Both players, pmmyplay and pmpgplay, are able to parse logfiles basing over the template description. Backward logfile compatibility is broken. + Execcutable triggering mechanism (from SQL plugins) has been enhanced: some status informations (eg. stats of the last purging event) are now passed to the trigged executable in the form of environment variables. The list of supported variables has been summarized into TRIGGER_VARS document. The mechanism allows to spawn executables for post-processsing operations at arbitrary timeframes. + Support for 'temporary' devices (like PPP and maybe PCMCIA cards too) has been introduced. A new configuration directive 'interface_wait' (or '-w' commandline) instructs pmacctd to wait for the listening device to become available. It works both when in startup phase and when already into main loop. A big thanks to Andre Berger for his support. ! ppp_handler() routine, which is in charge to handle PPP packets, have been totally rewritten. Thanks, again, to Andre Berger for his support. ! All link layer handling routines have been revised; some extra checks have been added to overcome issues caused from malicious handcrafted packets. ! Some time handling and timeout issues have been revised into PostgreSQL plugin code. They were affecting only the triggering mechanism. ! Fixed an execv() bug into MY_Exec() and PG_Exec(). It was causing the not correct execution of triggers. Now, a zeroed argv parameter is passed to the function. The problem has been verified on FreeBSD. 0.7.7 -- 16-Nov-2004 + Added two new aggregation primitives: 'src_as' and 'dst_as'. They allow accounting based over Autonomous System number; 'pmacctd' requires AS numbers to be supplied into a 'networks_file' configuration directive (which allows to specify the path to a networks definition file); 'nfacctd' may either look up AS numbers from the networks definition file or read them from each NetFlow flow (this is default). 'nfacctd_as_new' key could be used to switch 'nfacctd' behaviour. + Added some new aggregation modes: 'sum_net', 'sum_as', 'sum_port' ('sum' which is actually an alias for 'sum_host' has been already introduced early). Sum is intended to be the total traffic (that is, inbound plus outbound traffic amounts) for each entry. + Added another aggregation primitive: 'none'. It does not make use of any primitive: it allows to see total bytes and packets transferred through an interface. + The definition of a 'networks_file' enables network lookup: hosts inside defined networks are ok; hosts outside them are 'zeroed'. This behaviour may now also be applied to 'src_host', 'dst_host' and 'sum_host'. Under certain conditions (eg. when using only host/net/as primitives and defined networks comprise all transiting hosts) it may be seen an alternative way to filter data. ! 'frontend'/'backend' PostgreSQL plugin operations have been obsoleted. 'unified'/'typed' operations have been introduced instead. See 'sql_data' description, CONFIG-KEYS document, for further informations. ! Optimizations have been applied to: core process, the newly introduced cache code (see 0.7.6) and in-memory table plugin. ! Fixed some string handling routines: trim_all_spaces(), mark_columns() ! Solved a potential race condition which was affecting write_pid_file() 0.7.6 -- 27-Oct-2004 + Many changes has been introduced on 'pmacct' client side. '-m' switch (which output was suitable as MRTG input) has been obsoleted (though it will continue to work for next few releases). A new '-N' switch has been added: it returns counter value, suitable for integration with either RRDtool or MRTG. + Support for batch queries have also been added into pmacct client. It allows to join up to 4096 requests into a single query. Requests could either be concatenated commandline or read from a file (more details are in FAQS and EXAMPLES). Batch queries allow to handle efficiently high number of requests in a single shot (for example to timely feed data to a large amount of graphs). + Still pmacct client: '-r' switch, which already allows to reset counters for matched entries, now it also applies to group of matches (also referred as partial matches). + New scripts have been added into the examples tree which show how to integrate memory and SQL plugins with RRDtool, MRTG and GNUplot. + Memory plugin (IMT) has been further enhanced; each query from pmacct client is now evaluated and if involves just a short ride through the memory structure, it is served by the plugin itself without spawning a new child process. Batch queries support and reordering of fragmented queries have also been added. + New cache has been introduced in both SQL plugins; its layout is still an hash structure but it now features also chains, allocation, reuse and retirement of chained nodes. It also sports a LRU list of nodes which eases node handling. The new solution avoids the creation of a collision queue, ensuring uniqueness of data placed onto the queries queue. While this already greatly benefits a directive like 'sql_dont_try_update', it also opens new chances for post-processing operations of queries queue. 0.7.5 -- 14-Oct-2004 + Introduced support for the definition of a 'known ports' list, when either 'src_port' or 'dst_port' primitives are in use. Known ports will get written into the backend; unknown ports will be simply zeroed. It could be enabled via 'ports_file' configuration key or '-o' commandline switch. + Introduced support for weekly and monthly counters breakdown; hourly, minutely and daily were already supported. New breakdowns could be enabled via 'w' and 'M' words in 'sql_history' and related configuration keys. + Added a '-i' commandline switch to both 'pmmyplay' and 'pmpgplay' to avoid UPDATE SQL queries and skip directly to INSERT ones. Many thanks to Jamie Wilkinson. ! 'pmmyplay' and 'pmpgplay' code has been optimized and updated; some pieces of locking and transactional code were included into the inner loop. A big thanks goes to Wim Kerkhoff and Jamie Wilkinson. ! Networks aggregation code has been revised and optimized; a direct-mapped cache has been introduced to store (and search) last search results from the networks table. A binary search algorithm, though optimized, over the table has still been preferred over alternative approaches (hash, tries). 0.7.4 -- 30-Sep-2004 + Enhanced packet tagging support; it's now broken in Pre-Tagging and Post-Tagging; Pre-Tagging allows 'nfacctd' to assign an ID to a flow evaluating an arbitrary combination of supported NetFlow packet fields (actually: IP address, Input Interface, Output Interface); the Pre-Tagging map is global; Pre-Tag is applied as soon as each flow is processed; Post-Tagging allows both 'nfacctd' and 'pmacctd' to assign an ID to packets using a supplied value; Post-Tagging could be either global or local to a single plugin (and more plugins may tag differently); Post-Tag is applied as a last action before the packet is sent to the plugin. 'nfacctd_id_map' and 'pmacctd_id' configuration keys are now obsolete; 'pre_tag_map' and 'post_tag' are introduced to replace them. + Added support for Pre-Tag filtering; it allows to filter packets basing on their Pre-Tag value. The filter is evaluated after Pre-Tagging but before Post-Tagging; it adds to BPF filtering support ('aggregate_filter' configuration key); 'pre_tag_filter' configuration key is introduced. + Added support for Packet Sampling; the current implementation bases on a simple systematic algorithm; the new 'sampling_rate' configuration key expects a positive integer value >= 1 which is the ratio of the packets to be sampled (translates in: pick only 1 out of N packets). The key is either global or local (meaning that each plugin could apply different sampling rates). ! Fixed a bug which was causing crashes in both 'pmacctd' and 'nfacctd' when '-r' parameter was specified commandline. Thanks to Ali Nikham for his support. 0.7.3 -- 31-Aug-2004 + Added support for both Netflow 'input interface' and 'output interface' fields. These two fields are contained in each flow record inside a NetFlow packet. It works through ID mapping (read below). + The ID map file syntax has been enhanced to allow greater flexibility in ID assignation to packets; example: 'id=1 ip=192.168.1.1 in=3 out=5'; the above line will cause the 'ID' 1 to be assigned to flows exported by a NetFlow agent (for example a router) which IP address is '192.168.1.1' and transiting from interface '3' to interface '5'. + In-memory table operations have been enhanced when using shared memory; a new reset flag has been added to avoid race conditions. ! Configuration lines are no more limited to some fixed maximum length but are allocated dynamically; this to overcome the need for long configuration lines to declare arbitrary filters and plugin's list. Thanks to Jerry Ji for his support. ! Configuration handlers, which are responsible to parse and validate values for each configuration key, have been rewritten on the way for a better portability. ! Signal handler routines have been changed to better accomodate SysV semantics. ! Fixed shared memory mmap() operations on IRIX and SunOS; a further test checks for either 'MAP_ANON' or 'MAP_ANONYMOUS' definitions; in case of negative outcome, mmap() will use '/dev/zero'. ! Packet handlers have been revised and optimized. ! Some optimizations have been added when using shared memory; write() function has been usually called to signal the arrival of each new packet, through the core process/plugin control channel; now it does so if and only if the plugin, on the other side, is actually blocking over a poll(); because of sequence numbers guarantee, data is directly written into shared memory segment. 0.7.2p1 -- 08-Aug-2004 ! Multiple fixes in plugin's configuration post checks; negative outcome of some checks was leading to clear misbehaviours. Versions affected are >= 0.7.0 . A big thanks goes to Alexandra Walford for her support. 0.7.2 -- 02-Aug-2004 + VLAN accounting has been added. The new 'vlan' keyword is supported as argument of both '-c' commandline switch and 'aggregate' configuration key. + Distributed accounting support has been added. It could be enabled into 'pmacctd' via 'pmacctd_id' configuration key and into 'nfacctd' via the 'nfacctd_id_file' configuration key. While 'pmacctd_id' key expects as value a small integer, 'nfacctd_id_file' expects a path to a file which contains the mapping: 'IP address of the router (exporting Newflow) -> small integer'. This scheme ease tasks such as keeping track of who has generated what data and either cluster or keep disjoint data coming from different sources when using a SQL database as backend. + Introduced SQL table version 2. The SQL schema is the same as existing tables with the following additions: support for distributed accounting; support for VLAN accounting. + Added MAC addresses query capabilties to pmacct client. + Added '-r' commandline switch to pmacct client. It can only be used in conjunction with '-m' or '-M' switches. It allows to reset packet and bytes counters of the retrieved record. ! Exit codes have been fixed in both 'pmacctd' and 'nfacctd'. Thanks to Jerry Ji for his signallation. ! Fixed a problem when retrieving data from memory table: sometimes null data (without any error message) was returned to the client; the problem has been successfully reproduced only on FreeBSD 5.1: after an accept() call, the socket being returned inherits same flags of the listening socket, this case non-blocking flag. Thanks to Nicolas Deffayet for his support. ! Revised PostgreSQL creation script. 0.7.1 -- 14-Jul-2004 + Added shared memory implementation; core process, now, could push data into a shared memory segment and then signal arrival of new data to the plugin. Shared memory support could be enabled via '--enable-mmap' switch at configuration time. + Strongly enhanced gathering capabilities of pmacct client; pmacct client is used to fetch data from memory plugin; it is, now, able to ask exact or partial matches via '-M' switch and return a readable listing output. MRTG export capabilities, full table fetch and table status query are still supported. + Introduced SQL table versioning. It could be enabled via 'sql_table_version' configuration switch. It will enable to build new SQL tables (for example adding new aggregation methods) while allowing who is not interested in new setups to work with old tables. + Added checks for packet capture type; informations acquired are later used for better handling pcap interface. ! Fixed some issues concerning pmacctd VLAN and PPPOE code. ! Fixed a mmap() issue on Tru64 systems. ! Fixed some minor poll() misbehaviours in MySQL, PgSQL and print plugins; they were not correctly handled. 0.7.0p1 -- 13-Jul-2004 ! Fixes in cache code; affects MySQL, PgSQL and print plugins. 0.7.0 -- 01-Jul-2004 + PMACCT OPENS TO NETFLOW: a new network daemon, nfacctd, is introduced: nfacctd listens for Netflow V1/V5 packets; is able to apply BPF filters and to aggregate packets; it's then able to either save data in a memory table, MySQL or PostgreSQL database or simply output packets on the screen. It can read timestamps from Netflow packets in msecs, seconds or ignore them generating new timestamps; a simple allow table mechanism allows to silently discard Netflow packets not generated by a list of trusted hosts. + Strongly enhanced IP fragmentation handling in pmacctd. + Added new checks into the building systems; new hints when it searches for libraries and headers; initial tests for C compilers capabilities have been added. + Works to let pmacct run on IRIX platforms continue; some issues with MipsPRO compiler have been solved; added proper compilation flags/hints. SIGCHLD is now properly handled and child processes are correctly retired. (a thank for his support goes to Joerg Behrens) + First, timidous, introduction of mmap() calls in memory plugin; they need to be enabled with '--enable-mmap' flag at configure time. ! Fixed a potential deadlock issue in PostgreSQL plugin; changed locking mechanism. (a big thank to Wim Kerkhoff) ! Fixed an issue concerning networks aggregation on Tru64 systems. 0.6.4p1 -- 01-Jun-2004 ! Fixed an issue with cache aliasing in MySQL and PostgreSQL plugins. Other plugins are not affected; this potential issue affects only version 0.6.4, not previous ones. Anyone using these plugins with 0.6.4 is strongly encouraged to upgrade to 0.6.4p1. 0.6.4 -- 27-May-2004 + Added chance to launch executables from both SQL plugins at arbitrary time intervals to ease data post-processing tasks. Two new keys are available: 'sql_trigger_exec' and 'sql_trigger_time'. If any interval is supplied the specified executable is triggered every time data is purged from the cache. + Added a new 'print' plugin. Enabling it, data is pulled at regular intervals to stdout in a way similar to cflowd's 'flow-print'. tool. New config keys are 'print_refresh_time', 'print_cache_entries' and 'print_markers'. This last key enables the print of start/end markers each time the cache is purged. + Added 'sql_dont_try_update' switch to avoid UPDATE queries to the DB and skip directly to INSERT ones. Performance gains has been noticed when UPDATEs are not necessary (eg. when using timeslots to break up counters and sql_history = sql_refresh_time). Thanks to Jamie Wilkinson. + Optimized use of transactions in PostgreSQL plugin; in the new scheme is built a single big transaction for each cache purge process. This leads to good performance gains; recovery mechanisms have been modified to overcome whole transaction trashing. Many thanks to James Gregory and Jamie Wilkinson. ! Enhanced debug messages output when specific error conditions are returned by the DB. ! Fixed a potential counters overflow issue in both MySQL and PgSQL plugins cache. ! Fixed preprocessor definitions issue: LOCK_UN, LOCK_EX are undeclared on IRIX and Solaris. Thanks to Wilhelm Greiner for the fix. 0.6.3 -- 27-Apr-2004 + Added support for full libpcap-style filtering capabilities inside pmacctd. This allows to bind arbitrary filters to each plugin (in addition to already existing chance to apply them to the listening interface via 'pcap_filter' configuraiton key). The config key to specify these new filters is 'aggregate_filter'. + Strongly improved networks definition file handling; now the file is parsed and organized as a hierarchical tree in memory. This allows to recognize and support networks-in-networks. + Initial optimizations has been done over the code produced in last few months. + Preprocessor definitions has been added to some part of the code, to allow pmacctd compile over IRIX. It has been reported to work over a IRIX64 6.5.23 box. Thanks to Wilhelm Greiner for his efforts. + Added flock() protected access to recovery logfiles. ! Fixed an ugly SEGV issue detected in both 0.6.2's logfile player tools. 0.6.2 -- 14-Apr-2004 + Added support for networks aggregation. Two new primitives has been added 'src_net' and 'dst_net' to be used in conjunction with a network's definitions file (path is supplied via 'networks_file' configuration key). An example of this file is in the examples/ directory. When this aggregation is enabled, IP addresses are compared against the networks table; then the matching network will get written to the backend; if any match occurs a '0.0.0.0' is written. A really big thank goes to Martin Anderberg for his strong support during last weeks. + pipe() has been thrown away; socketpair() has been introduced to set up a communication channel between pmacctd core process and plugins. + Added 'plugin_pipe_size' configuration key to adjust queue depth (size) beween core process and plugins. A default value is set by operating system; it could not suffice when handling heavy traffic loads. Added also a specific error string when pipe gets filled. + Added 'plugin_buffer_size' configuration key to enable chances to bufferize data to be sent to plugins. When under great loads this helps in preventing high CPU usage and excessive pressure over kernel. + SQL plugins aliasing behaviour has been changed; when no free space for new data is found and old data has to be pulled out, it's now actually written to the DB but it's inserted in a new 'collision queue'. This new queue is purged together with the 'queries queue'. See INTERNALS for further details. + SQL plugins cache behaviour has been changed by a direct-mapped one to a 3-ways associative to get better scores when searching free space for new data. See INTERNALS for further details. + Added 'sql_cache_entries' configuration key to adjust bucket's number of SQL plugin cache. As every hashed structure, a prime number of buckets is advisable to get better dispersion of data through the table. ! Fixed a malloc() SEGV issue in in-memory table plugin first noticed with gcc 3.3.3 (Debian 20040320) and glibc 2.3.2. ! Fixed a SEGV issue carried with last release. Improved handling of communication channels between core process and plugins. ! Uniformed plugin's handling of signals; now sending a SIGINT to all pmacctd processes causes it to flush caches and exit nicely. ! Updated documentation; still no man page. 0.6.1 -- 24-Mar-2004 + A new concept has been introduced: plugin names. A name could be assigned to each running plugin allowing to run more instances of the same plugin type; each one is configurable with global or 'named' keys. Take a look to examples for further info. + Added support for PPPOE links. The code has been fully contributed by Vasiliy Ponomarev. A big thank goes to him. + Added a 'sql_startup_delay' configuration key to allow more plugin instances that need to write to the DB, to flush their data at same intervals but in different times to avoid locking stalls or DB overkills. + Improved handling of syslog connections. SIGHUP signal, used to reopen a connection with syslog (eg. for log rotation purposes), now is supported in all plugins. + A simple LRU (Last Recently Used) cache has been added to the in-memory table plugin. The cache gives great benefits (exploiting some kind of locality in communication flows) when the table gets large (and chain in buckets become long and expensive to traverse). + Down-up of listening interface are now handled properly. Such an event traps a reopening of connection with libpcap. [EXPERIMENTAL] + Some work has been done (mostly via directives to preprocessor) in order to get pmacct compiled under Solaris. [HIGLY EXPERIMENTAL, translates: don't assume it works but, please, try it out and some kind of feedback would be appreciated] ! Plugins have been better structured; plugin hooking has been simplified and re-documented; configuration parser has been strongly improved. ! Fixed a bug in 'configure' script; when supplying custom paths to MySQL libraries an erroneous library filename was searched for. (thanks to Wim Kerkhoff) 0.6.0p3 -- 09-Feb-2004 ! Fixed an issue concerning promiscuous mode; it was erroneously defaulting to 'false' under certain conditions. (Thanks to Royston Boot for signalling the problem) 0.6.0p2 -- 05-Feb-2004 ! Fixed pmacct daemon in-memory table plugin unstability, noticed under sustained loads. (A thank for signalling the problem goes to Martin Pot) ! Minor code rewritings for better optimizazion done in both in-memory table plugin and pmacct client. 0.6.0p1 -- 28-Jan-2004 ! Fixed a bug in in-memory table plugin that was causing incorrect memorization of statistics. (Many thanks for promptly signalling it go to Martin Pot) ! Fixed a bug in pmacct client, used to gather stats from in-memory table. Under high loads and certain conditions the client was returning SEGV due to a realloc() issue. (Thanks to Martin Pot) 0.6.0 -- 27-Jan-2004 + PMACCT OPENS TO POSTGRESQL: fully featured PostgreSQL plugin has been added; it's transaction based and already supports "recovery mode" both via logfile and backup DB actions. pmpgplay is the new tool that allows to play logfiles written in recovery mode by the plugin into a PostgreSQL DB. See CONFIG-KEYS and EXAMPLES for further informations. (Again, many thanks to Wim Kerkoff) + Added new "recovery mode" action to MySQL plugin: write data to a backup DB if primary DB fails. DB table/user/ password need to be the same as in the primary DB. The action could be enabled via "sql_backup_host" config key. + Added a "sql_data" configuration optinion; a "frontend" value means to write human readable (strings) data; a "backend" value means to write integers in network byte order. Currently, this option is supported only into the new PostgreSQL plugin. See CONFIG-KEYS and README.pgsql for further informations. + Added support for simple password authentication in client/server query mechanism for in-memory table statistics. It's available via "imt_passwd" config key. + Added a "-t" commandline switch to pmmyplay; it runs the tool in a test only mode; useful to check header infos or logfile integrity. ! Fixed an ugly bug that made impossible MAC accounting over certain links. Was affected only version 0.5.4. ! Many code and structure cleanups. 0.5.4 -- 18-Dec-2003 + Added a commandline and configuration switch to use or not promiscuous mode for traffic capturing; useful to avoid waste of resources if running over a router. + Introduced a "recovery mode" concept for MySQL plugin: if DB fails an action is taken; currently is possible to write data to a logfile. More failover solutions to come in next releases. Thanks also to Wim Kerkhoff. + Added a new "pmmyplay" tool. Allows to play logfiles previously written by a MySQL plugin in recovery mode. Check EXAMPLES for hints; see INTERNALS for further details about recovery mode and pmmyplay. + Added syslog logging and debugging. Thanks for long brainstormings to Wim Kerkhoff. + Added chance to write PID of pmacctd core process to a specified file; it could help in automating tasks that need to send signals to pmacctd (eg. to rotate logfiles and reopen syslog connection). Take a look to SIGNALS file for further informations. + support for 802.11 Wireless links. [EXPERIMENTAL] + support for linux cooked device links (DLT_LINUX_SLL). pcap library >= 0.6.x is needed. A big thank goes to KP Kirchdoerfer. ! Simplified client/server query mechanism; avoided all string comparison stuff. ! Large parts of in-memory table plugin code has been revised to achieve better efficiency and optimization of available resources. 0.5.3 -- 20-Nov-2003 ! pmacctd core has been optimized and a new loop-callback scheme driven by pcap library has been introduced; I/O multiplexing is avoided. ! In MySQL plugin, refresh of entries in the DB has been switched from a signal-driven approach to a lazy timeslot based one. If using historical recording, taking care to the choosen values, this greatly alleviates cache aliasing. ! In MySQL plugin, modulo function (for insertion of data in the direct mapped cache) has been changed: crc32 algorithm has been adopted. Experimental tests shown the reduction of cache aliasing to about 0.45%. ! The whole MySQL plugin has been inspected for performance bottlenecks resulted by the addition of new features in last releases. ! Fixed a bug in link layer handlers. 0.5.2 -- 03-Nov-2003 + "sql_history" configuration key syntax has been changed to support history recording at fixed times with mins, hrs and days granularity. A little of date arithmetics has been introduced (merely multiplicative factors, eg. to ease 95th percentile operations). + Added "sql_history_roundoff" configuration key to round off time of first timeslot. This little care gives cleaner time results and inductively affects all subsequent slots. + Achieved more precise calculations via timestamps added to the cache structure to avoid data counted during the current timeslot and not already fed in the DB to be accounted in next slot. ! Monthly historical aggregation is no more available. ! Fixed portability issues posed by vsnprintf() in MySQL plugin. Now the plugin compiles smoothly under Tru64 Unix. 0.5.1 -- 01-Oct-2003 + due to the proliferation of command-line options, the support for a configuration file has been added. All commandline switches until version 0.5.0 will be supported in the future. New configurable options (eg. log to a remote SQL server) will be only supported via configuration file. See CONFIG-KEYS file for available configuration keys. + added support for historical recording of counters in the MySQL database. Available granularities of aggregation are hourly, daily or monthly (eg. counters are separated hour by hour, daily of monthly for each record). Timestamps of last INSERT and UPDATE have been added over each record. (thanks to Wim Kerkhoff for his strong collaboration) + support for IP header options. + support for PPP links. [EXPERIMENTAL] ! Fixed a MySQL plugin direct-mapped cache issue: the cache now traps INSERT queries when an UPDATE fails due to any asyncronous table manipulation event (eg. external scripts, table truncation, etc.). ! MySQL plugin has been strongly revised and optimized; added options to save data to a remote sql server and to customize username, password and table; added MySQL locking stuff. (another big thank to Wim Kerkhoff). ! various code cleanups. 0.5.0 -- 22-Jul-2003 + static aggregation directives (src_host, dst_host, ..) are now superseded by primitives that can be stacked together to form complex aggregation methods. The commandline syntax of the client program has been consequently changed to support these new features. + two new primitives have been added: source MAC address and destination MAC address. + support for 802.1Q (VLANs) tagged packets (thanks to Rich Gade). + support for FDDI links. [EXPERIMENTAL] ! the core pmacctd loop (that gathers packets off the wire and feeds data to plugins) has been revised and strongly optimized. ! the main loop of MySQL plugin has been optimized with the introduction of adaptive selection queries during the update process. ! fixed a memory allocation issue (that caused a SIGSEGV, under certain circustances) in pmacct client: now the upper bound of dss is checked for large data retrieval. 0.4.2 -- 20-Jun-2003 + limited support for transport protocols (currently only tcp and udp): aggregation of statistics for source or destination port. + optimized query mechanism for in-memory table; solved few generalization issues that will enable (in future versions) to support complex queries. + added "-t" pmacctd commandline switch to specify a custom database table. ! fixed realloc() issue in pmacct client (thanks to Arjen Nienhuis). ! fixed an issue regarding mysql headers in the configure script. 0.4.1 -- 08-May-2003 ! missing break in a case statement that led pmacctd to misbehaviours; a cleaner approach to global vars (thanks to Peter Payne). ! fixed an issue with getopt() and external vars. Now pmacct has reported to compile without problems on FreeBSD 4.x (thanks to Kirill Ponomarew). ! missing conditional statement to check the runtime execution of compiled plugins in exec_plugins() 0.4.0 -- 02-May-2003 + switched to a plugin architecture: plugins need to be activated at configure time to be compiled and then used via "-P" command-line switch in pmacctd. See PLUGINS for more details. + added first plugin: Mysql driver. It uses a Mysql database as backend to store statistics other than in-memory table. See sql/ directory for scripts for creation of db needed to store data. + added the choice to collect statistics for traffic flows in addition to src|dst|sum aggregation via the "-c flows" command-line switch in pmacctd. + major code cleanups. + mostly rewritten configure script; switched back to autoconf 2.1. 0.3.4 -- 24-Mar-2003 + accounting of IP traffic for source, destination and aggregation of both. Introduced -c switch to pmacctd (thanks to Martynas Bieliauskas). + added daemonization of pmacctd process via -D command line switch + added buffering via pcap_open_live() timeout handling on those architectures where it is supported. + It compiles and works fine over FreeBSD 5.x; solved some pcap library issues. + added customization of pipe for client/server communication via -p command line switch both in pmacct and pmacctd 0.3.3 -- 19-Mar-2003 + introduced synchronous I/O multiplexing + support for -m 0 pmacctd switch, in-memory table can grow undefinitely. + revised memory pool descriptors table structure ! introduced realloc() in pmacct to support really large in-memory table transfers; solved additional alignment problems. ! solved compatibility issues with libpcap 0.4 ! solved nasty problem with -i pmacctd switch ! solved various memory code bugs and open issues 0.3.2 -- 13-Mar-2003 + support for pcap library filters ! minor bugfixes 0.3.1 -- 12-Mar-2003 + documentation stuff: updated TODO and added INTERNALS + revised query mechanism to server process, added a standard header to find command and optional values carried in query buffer. + added -s commandline switch to customize the size of each memory pool; see INTERNLS for more informations ! stability tests and fixes ! configure script enhancements 0.3.0 -- 11-Mar-2003 ! not public release + increased efficiency through allocation of memory pools instead of sparse malloc() calls when inserting new elements in in-memory table. + added -m commandline switch to pmacctd to set the number of available memory pools; the size of each memory pool is the number of buckets, chosen with -b commandline option, see INTERNALS for more informations. + switched client program to getopt() to acquire commandline inputs. + new -m commandline option in client program to acquire statistics of a specified IP address in a format useful for acquisition by MRTG program; see examples directory for a sample mrtg configuration. ! major bugfixes ! minor code cleanups 0.2.4 -- 07-Mar-2003 + portability: Tru64 5.x ! configure script fixes ! minor bugfixes 0.2.3 -- 05-Mar-2003 + first public release ! portability fixes ! minor bugfixes 0.2.2 -- 04-Mar-2003 + minor code cleanups + added autoconf, automake stuff 0.2.1 -- 03-Mar-2003 + fork()ing when handling queries + signal handling + command-line options using getopt() + usage instructions ! major bugfixes 0.2.0 -- 01-Mar-2003 + dynamic allocation of in-memory table + query (client/server) mechanism + added a Makefile ! major bugfixes 0.1.0 -- late Feb, 2003 + Initial release pmacct-1.7.8/aclocal.m40000644000175000017500000014624314354105413013656 0ustar paolopaolo# generated automatically by aclocal 1.16.3 -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/ac_linearize_path.m4]) m4_include([m4/ax_lib_mysql.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) pmacct-1.7.8/FAQS0000644000175000017500000005234314354105275012476 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI : IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2021 by Paolo Lucente Q1: What is pmacct project homepage ? A: pmacct homepage is http://www.pmacct.net/ . pmacct is also present on GitHub at the URL: https://github.com/pmacct/pmacct . Q2: 'pmacct', 'pmacctd', 'nfacctd', 'sfacctd', 'uacctd', 'pmtelemetryd', 'pmbgpd' and 'pmbmpd' -- but what do they mean ? A: 'pmacct' is the name of the project; 'pmacctd' is the libpcap-based IPv4/IPv6 accounting daemon; 'nfacctd' is the NetFlow (versions supported NetFlow v1, v5 and v9) and IPFIX accounting daemon; 'sfacctd' is the sFlow v2/v4 and v5 accounting daemon; 'uacctd' is the Linux NFLOG-based accounting daemon (historically, it was using ULOG, hence its name); 'pmtelemetryd' is the Streaming Telemetry collector, where "Streaming telemetry [ .. ] data can be used for analysis and troubleshooting purposes to maintain the health of the network. This is achieved by leveraging the capabilities of machine-to-machine communication. [ .. ]" (quoting Cisco IOS-XR Telemetry Configuration Guide at the time of this writing); 'pmbgpd' is the pmacct BGP collector and 'pmbmpd' is the pmacct BMP collector. Q3: Does pmacct stand for Promiscuous mode IP Accounting package? A: Not anymore, it was originally though: pmacct was born as a libpcap-based traffic collection project only. Over the time it evolved to include NetFlow first, sFlow shortly afterwards and NFLOG more recently. Latest additions being in the areas of BGP, BMP, RPKI and Streaming Telemetry. However the unpronounceable name 'pmacct' remained as a distinctive signature of the project. Q4: What are pmacct main features? A: pmacct can collect, replicate and export network information. On the data plane (ie. IPv4/IPv6 traffic) it can cache in memory tables, store persistently to RDBMS (MySQL/MariaDB, PostgreSQL, SQLite 3.x), noSQL databases (key-value: BerkeleyDB 5.x via SQLite API or document-oriented: MongoDB) and flat-files (CSV, formatted, JSON, Apache Avro output), publish to AMQP and Kafka brokers (ie. to insert in ElasticSearch, InfluxDB, Druid or ClickHouse). Export sFlow v5, NetFlow v5/v9 and IPFIX. pmacct is able to perform data aggregation, offering a rich set of primitives to choose from; it can also filter, sample, renormalize, tag and classify at L7. On the control and infrastructure planes it can collect and publish to AMQP and Kafka brokers BGP, BMP, RPKI and Streaming Telemetry data both standalone and as correlation/enrichment of data plane information. Q5: Do pmacct IPv4/IPv6 traffic accounting daemons log to flat files? A: Yes. Each micro-flow (NetFlow, IPFIX and sFlow) or packet (libpcap, NFLOG) can be written to a flat-file for a two-stages approach, ie. a) write all down to persistent storage then b) consolidate stats to build the desired view(s). Also pmacct always aimed to offer a single-stage approach so to get immediate view(s) of the traffic and this be achieved leveraging data reduction tecniques and correlation tools to process network traffic data on the fly. pmacct writes to files in text-format (JSON, Avro, CSV or formatted via 'print' plugin, and JSON or Avro via Kafka and AMQP plugins, see QUICKSTART doc for further information) so to maximize integration with 3rd party tools while keeping low the effort of customization. Q6: What are the options to scale a pmacct deployment to match input data rate? A: There are two dimensions to it: 1) scale within the same instance of pmacct: make use of data reduction tecniques part of pmacct, ie. spatial and temporal aggregation, filtering, sampling and tagging. As these features are fully configurable, going from full micro-flow visibility to - say - node-to-node IP network traffic matrix, data granularity/resolution can be traded off for scalability/resources consumption; 2) divide-and-conquer input data over a set of pmacct instances by either balancing or mapping data onto collectors. See next point, Q7, for libpcap; the 'tee' plugin can be used for this purpose for NetFlow, IPFIX and sFlow. Q7: I see my libpcap-based daemon (pmacctd) taking much CPU cycles; is there a way to reduce the load? A: CPU cycles are proportional to the amount of traffic (packets, flows, samples) that the daemon receives; in case of pmacctd it's possible to reduce the CPU share by avoiding unnecessary copies of data, also optimizing and buffering the necessary ones. Kernel-to-userspace copies are critical and hence the first to be optimized; for this purpose you may look at the following solutions: Linux kernel has support for mmap() since 2.4. The kernel needs to be 2.6.34+ or compiled with option CONFIG_PACKET_MMAP. You need at least a 2.6.27 to get compatibility with 64bit. Starting from 3.10, you get 20% increase of performance and packet capture rate. You also need a matching libpcap library. mmap() support has been added in 1.0.0. To take advantage of the performance boost from Linux 3.10, you need at least libpcap 1.5.0. PF_RING, http://www.ntop.org/PF_RING.html : PF_RING is a new type of network socket that improves the packet capture speed; it's available for Linux kernels 2.6.32 and newer. It needs a kernel module to be loaded, it's device driver independent and has libpcap support for seamless integration with existing applications. NetMap, http://info.iet.unipi.it/~luigi/netmap/ : Netmap is a BSD-licensed framework that supports line-rate direct packet I/O even on 10GBit/s interfaces (14.88Mpps) with limited system load, and includes a libpcap emulation library to port applications. Internal buffering can also help and, contrary to the previous tecniques, applies to all daemons. Buffering is enabled with the plugin_buffer_size directive; buffers can then be queued and distributed with a choice of an home-grown circolar queue implementation (plugin_pipe_size) or a ZeroMQ queue (plugin_pipe_zmq). Check both CONFIG-KEYS and QUICKSTART for more information. Q8: I want to to account both inbound and outbound traffic of my network, with an host breakdown; how to do that in a savy fashion? Do i need to run two daemon instances one per traffic direction? A: No, this is a toy case where you will be able to leverage the pluggable architecture of the pmacct daemons: you will run a single daemon with two plugins attached to it; each of these will get part of the traffic (aggregate_filter), either outbound or inbound. A sample config snippet follows: ... aggregate[inbound]: dst_host aggregate[outbound]: src_host aggregate_filter[inbound]: dst net 192.168.0.0/16 aggregate_filter[outbound]: src net 192.168.0.0/16 plugins: mysql[inbound], mysql[outbound] sql_table[inbound]: acct_in sql_table[outbound]: acct_out ... It will account all traffic directed to your network into the 'acct_in' table and all traffic it generates into 'acct_out' table. Furthermore, if you actually need totals (inbound plus outbound traffic), you will just need to play around with basic SQL queries. If you are only interested into having totals instead, you may alternatively use the following piece of configuration: ... aggregate: sum_host plugins: mysql networks_file: /usr/local/pmacct/etc/networks.lst ... Where 'networks.lst' is a file where to define local network prefixes. Q9: I'm intimately fashioned by the idea of storing every single flow flying through my network, before making up my mind what to do with such data: i basically would like to (de-)aggregate my traffic as 'src_host, dst_host, src_port, dst_port, proto' or 'src_host, dst_host, src_port, dst_port, proto, timestamp_start, timestamp_end'. Is this feasible without any filtering? A: If such data granularity is required by the use-case addressed, ie. DDoS, forensics, security, research, etc. then this can be achieved no problem with pmacct - you have only to be careful planning for the right amount of system/cluster resources. In all other cases this is not adviceable as this would result in a huge matrix of data - meaning increased CPU, memory and disk usage - for no benefit - plus, to be always considered, the impact of unexpected network events (ie. port scans, DDoS, etc.) on the solution. Q10: I use pmacctd. What portion of the packets is included into the bytes counter ? A: The portion of the packet accounted starts from the IPv4/IPv6 header (inclusive) and ends with the last bit of the packet payload. This means that are excluded from the accounting: packet preamble (if any), link layer headers (e.g. ethernet, llc, etc.), MPLS stack length, VLAN tags size and trailing FCS (if any). This is the main reason of skews reported while comparing pmacct counters to SNMP ones. However, by having available a counter of packets, accounting for the missing portion is, in most cases, a simple math exercise which depends on the underlying network architecture. Example: Ethernet header = 14 bytes, Preamble+SFD (Start Frame Delimiter) = 8 bytes, FCS (Framke Check Sequence) = 4 bytes. It results in an addition of a maximum of 26 bytes (14+8+4) for each packet. The use of VLANs will result in adding 4 more bytes to the forementioned 26. Q11: What is historical accounting feature and how to get it configured? A: pmacct allows to optionally define arbitrary time-bins (ie. 5 mins, 1 hour, etc.) and assign collected data to it basing on a timestamp. This is in brief called historical accounting and is enabled via *history* directives (ie. print_history, print_history_roundoff, sql_history, etc.). The time-bin to which data is allocated to is stored in the 'stamp_inserted' field (if supported by the plugin in use, ie. all except 'print', where to avoid redundancy this is encoded as part of the file name, and 'memory'). Flow data is by default assigned to a time-bin basing on its start time or - not applying that or missing such info - the timestamp of the whole datagram or - not applying that or missing such info - the time of arrival at the collector. Where multiple choices are supported, ie. NetFlow/IPFIX, the directive nfacctd_time_new allows to explicitely select the time source. Q12: Counters via CLI are good for (email, web) reporting but not enough. What are the options to graph network data? A: An option could be to use traditional graphing tools like RRDtool, MRTG and GNUplot in conjunction with the 'memory' plugin. The plugin works as a cache and offers a pull mechanism, the pmacct IMT client tool, that allows to easily retrieve counters: shell> ./pmacctd -D -c src_host -P memory -i eth0 shell> ./pmacct -c src_host -N 192.168.4.133 -r 2339 shell> Et voila'! This is the bytes counter. Because of the '-r', counters will get reset or translating into the RRDTool jargon, each time you will get an 'ABSOLUTE' value. Let's now encapsulate our query into, say, RRDtool commandline: shell> rrdtool update 192_168_4_133.rrd N:`./pmacct -c src_host -N 192.168.4.133 -r` Multiple requests can be batched as part of a single query, each request can be ';' separated via CLI or read from an input file (one query per line): shell> ./pmacct -c src_host,dst_host -N 192.168.4.133,192.168.0.101;192.168.4.5,192.168.4.1;... -r 50905 1152 ... OR shell> ./pmacct -c src_host,dst_host -N "file:queries.list" -r ... shell> cat queries.list 192.168.4.133,192.168.0.101 192.168.4.5,192.168.4.1 ... A second option, perhaps the most current of the two, is to leverage one of the many modern data analytics stacks that do typically comprise of data manipulation, storage and visualization. Like the ELK stack (ElasticSearch, Logstash, Kibana) or the TICK stack (Telegraf, InfluxDB, Chronograf, Kapacitor). Many more, free and commercial, exists. Q13: The network equipment i'm using supports sFlow but i don't know how to enable it. I'm unable to find any sflow-related command. What to do ? A: If you are unable to enable sFlow commandline, you have to resort to the SNMP way. The sFlow MIB is documented into the RFC 3176; all you will need is to enable a SNMP community with both read and write access. Then, continue using the sflowenable tool available at the following URL: http://www.inmon.com/technology/sflowenable Q14: When i launch either nfacctd or sfacctd i receive the following error message: ERROR ( default/core ): socket() failed. What to do ? A: When IPv6 code is enabled, sfacctd and nfacctd will try to fire up an IPv6 socket. The error message is very likely to be caused by the proper kernel module not being loaded. So, try either to load it or specify an IPv4 address to bind to. If using a configuration file, add a line like 'nfacctd_ip: 192.168.0.14'; otherwise if going commandline, use the following: 'nfacctd [ ... options ... ] -L 192.168.0.14'. Q15: SQL table versions, what they are -- why and when do i need them ? Also, can i customize SQL tables ? A: pmacct tarball gets with so called 'default' tables (IP and BGP); they are built by SQL scripts stored in the 'sql/' section of the tarball. Default tables enable to start quickly with pmacct out-of-the-box; this doesn't imply they are suitable as-is to larger installations. SQL table versioning is used to introduce features over the time without breaking backward compatibility when upgrading pmacct. The most updated guide on which version to use given a required feature-set can be, once again, found in the 'sql/' section of the tarball. SQL tables *can* be fully customized so that primitives of interest can be freely mixed and matched - hence making a SQL table to perfectly adhere to the required feature-set. This is achieved by setting the 'sql_optimize_clauses' configuration key. You will then be responsible for building the custom schema and indexes. Q16: What is the best way to kill a running instance of pmacct avoiding data loss ? A: Two ways. a) Simply kill a specific plugin that you don't need anymore: you will have to identify it and use the 'kill -INT ' command; b) kill the whole pmacct instance: you can either use the 'killall -INT ' command or identify the Core Process and use the 'kill -INT ' command. All of these, will do the job for you: will stop receiving new data from the network, clear the memory buffers, notify the running plugins to take th exit lane (which in turn will clear cached data as required). To identify the Core Process you can either take a look to the process list (on the Operating Systems where the setproctitle() call is supported by pmacct) or use the 'pidfile' (-F) directive. Note also that shutting down nicely the daemon improves restart turn-around times: the existing daemon will, first thing, close its listening socket while the newly launched one will mostly take advantage of the SO_REUSEADDR socket option. Q17: I find interesting store network data in a SQL database. But i'm actually hitting poor performances. Do you have any tips to improve/optimize things ? A: Few hints are summed below in order to improve SQL database performances. They are not really tailored to a specific SQL engine but rather of general applicability. Many thanks to Wim Kerkhoff for the many suggestions he contributed on this topic over the time: * Keep the SQL schema lean: include only required fields, strip off all the others. Set the 'sql_optimize_clauses' configuration key in order to flag pmacct you are going to use a custom-built table. * Avoid SQL UPDATEs as much as possible and use only INSERTs. This can be achieved by setting the 'sql_dont_try_update' configuration key. A pre-condition is to let sql_history == sql_refresh_time. UPDATEs are demanding in terms of resources and are, for simplicity, enabled by default. * If the previous point holds, then look for and enable database-specific directives aimed to optimize performances ie. sql_multi_values for MySQL and sql_use_copy for PostgreSQL. * Don't rely automagically on standard indexes but enable optimal indexes based on clauses you (by means of reports, 3rd party tools, scripts, etc.) and pmacct use the most to SELECT data. Then remove every unused index. * See if the dynamic table strategy offered by pmacct fits the bill: helps keeping SQL tables and indexes of a manageable size by rotating SQL tables (ie. per hour, day, week, etc.). See the 'sql_table_schema' configuration directive. * Run all SELECT and UPDATE queries under the "EXPLAIN ANALYZE ..." method to see if they are actually hitting the indexes. If not, you need to build indexes that better fit the actual scenario. * Sometimes setting "SET enable_seqscan=no;" before a SELECT query can make a big difference. Also don't underestimate the importance of daily VACUUM queries: 3-5 VACUUMs + 1 VACUUM FULL is generally a good idea. These tips hold for PostgreSQL. * MyISAM is a lean SQL engine; if there is no concurrence, it might be preferred to InnoDB. Lack of transactions can reveal painful in case of unsecured shutdowns, requiring data recovery. This applies to MySQL only. * Disabling fsync() does improve performance. This might have painful consequences in case of unsecured shutdowns (remember power failure is a variable ...). Q18: Does having the local timezone configured on servers, routers, etc. - which can very well include DST (Daylight Saving Time) shifts - impact accounting? A: It is good rule to run the infrastructure and the backend part of the accounting system as UTC; for example, accuracy can be negatively impacted if sampled flows are cached on a router while the DST shift takes place; plus, pmacct uses system clock to calculate time-bins and scanner deadlines among the others. In short, the use of local timezones is not recommended. timestamps_utc config directive set to true can be used to present timestamps in UTC even if the system where pmacct is running is set to some timezone different than that. Q19: I'm using the 'tee' plugin with transparent mode set to true and keep receiving "Can't bridge Address Families when in transparent mode. Exiting ..." messages, why? A: It means you can't receive packets on an IPv4 address and transparently replicate to an IPv6 collector or vice-versa. Less obvious scenarios are: a) some operating systems where loopback (127.0.0.1) is considered a different address family hence it's not possible to replicate to a 127.0.0.1 address; it's possible though to use any locally configured IPv4 address bound to a (sub-)interface in 'up' state; b) an IPv4-mapped IPv6 address is still technically an IPv6 address hence on servers running IPv4 and IPv6 it is good practice to explicitely define also the receiving IP address (nfacctd_ip), if IPv4 is used. Q20: I'm using IPv6 support in pmacct. Even though the daemon binds to the "::" address, i don't receive NetFlow/IPFIX/sFlow/BGP data sent via IPv4, why? A: Binding to a "::" address (ie. no [sn]facctd_ip specified should allow to receive both IPv4 and IPv6 senders. IPv4 ones should be reportd in 'netstat' as IPv4-mapped IPv6 addresses. Linux has a kernel switch to enable/disable the functionality and its status can be checked via the /proc/sys/net/ipv6/bindv6only . Historically the default has been '0'. It appears over time some distributions have changed the default to be '1'. If you experience this issue on Linux, please check your kernel setting. Q21: How can i count how much telemetry data (ie. NetFlow, sFlow, IPFIX, Streaming Telemetry) i'm receiving on my collector? A: If the interface where telemetry data is received is dedicated to the task then any ifconfig, netstat or dstat tools or SNMP meaurement would do in order to verify amount of telemetry packets and bytes (from which packets per second, bytes per second can be easily inferred). If, instead, the interface is shared then pmacctd, the libpcap-based daemon, can help to isolate and account for the telemetry traffic; guess telemetry data is pointed to UDP port 2100 of the IP address configured on eth0, pmacctd can be started as "pmacctd -i eth0 -P print -c none port 2100" to account for the grand total of telemetry packets and bytes; if a breakdown per telemetry exporting node is wanted, the following command-line can be used: "pmacctd -i eth0 -P print -c src_host port 2100"; this example is suitable for manual reading as it will print data every 60 secs on the screen and can, of course, be complicated slightly to make it suitable for automation. A related question that often arises is: how many flows per second am i receiving? This can be similarly addressed by using "nfacctd -P print -c flows" for NetFlow/IPFIX and "sfacctd -P print -c flows" for sFlow. Here FLOWS is the amount of flow records (NetFlow/IPFIX) or flow samples (sFlow) processed in the period of time, and is the measure of interest. Changing the aggregation argument in "-c peer_src_ip,flows" gives the amount of flows per telemetry exporter (ie. router). /* EOF */ pmacct-1.7.8/compile0000755000175000017500000001635014354105415013371 0ustar paolopaolo#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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 2, 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 file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/VERSION0000644000175000017500000000001214354105275013053 0ustar paolopaolo1.7.8-git pmacct-1.7.8/bin/0000755000175000017500000000000014354105416012557 5ustar paolopaolopmacct-1.7.8/bin/configure-help-replace.txt0000644000175000017500000000553314354105275017651 0ustar paolopaolo CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path PGSQL_CFLAGS C compiler flags for PGSQL, overriding pkg-config PGSQL_LIBS linker flags for PGSQL, overriding pkg-config MONGODB_CFLAGS C compiler flags for MONGODB, overriding pkg-config MONGODB_LIBS linker flags for MONGODB, overriding pkg-config SQLITE3_CFLAGS C compiler flags for SQLITE3, overriding pkg-config SQLITE3_LIBS linker flags for SQLITE3, overriding pkg-config RABBITMQ_CFLAGS C compiler flags for RABBITMQ, overriding pkg-config RABBITMQ_LIBS linker flags for RABBITMQ, overriding pkg-config ZMQ_CFLAGS C compiler flags for ZMQ, overriding pkg-config ZMQ_LIBS linker flags for ZMQ, overriding pkg-config KAFKA_CFLAGS C compiler flags for KAFKA, overriding pkg-config KAFKA_LIBS linker flags for KAFKA, overriding pkg-config REDIS_CFLAGS C compiler flags for REDIS, overriding pkg-config REDIS_LIBS linker flags for REDIS, overriding pkg-config GNUTLS_CFLAGS C compiler flags for GNUTLS, overriding pkg-config GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config GEOIP_CFLAGS C compiler flags for GEOIP, overriding pkg-config GEOIP_LIBS linker flags for GEOIP, overriding pkg-config GEOIPV2_CFLAGS C compiler flags for GEOIPV2, overriding pkg-config GEOIPV2_LIBS linker flags for GEOIPV2, overriding pkg-config JANSSON_CFLAGS C compiler flags for JANSSON, overriding pkg-config JANSSON_LIBS linker flags for JANSSON, overriding pkg-config AVRO_CFLAGS C compiler flags for AVRO, overriding pkg-config AVRO_LIBS linker flags for AVRO, overriding pkg-config SERDES_CFLAGS C compiler flags for SERDES, overriding pkg-config SERDES_LIBS linker flags for SEREDES, overriding pkg-config NFLOG_CFLAGS C compiler flags for NFLOG, overriding pkg-config NFLOG_LIBS linker flags for NFLOG, overriding pkg-config NDPI_CFLAGS C compiler flags for dynamic nDPI, overriding pkg-config NDPI_LIBS linker flags for dynamic nDPI, overriding pkg-config UNYTE_UDP_NOTIF_CFLAGS C compiler flags for dynamic Unyte UDP Notif, overriding pkg-config UNYTE_UDP_NOTIF_LIBS linker flags for dynamic Unyte UDP Notif, overriding pkg-config EBPF_CFLAGS C compiler flags for dynamic libbpf, overriding pkg-config EBPF_LIBS linker flags for dynamic libbpf, overriding pkg-config pmacct-1.7.8/bin/configure-help-replace.sh0000755000175000017500000000115414354105275017442 0ustar paolopaolo#!/usr/bin/env bash # # This script is meant to be called by autogen.sh from the parent directory. # # Silence on exec 1>/dev/null 2>/dev/null # Vars HEAD="^Some influential environment variables:$" TAIL="^Use these variables to override the choices made by \`configure' or to help" FILE_ORIGINAL="configure" FILE_REPLACE="bin/configure-help-replace.txt" FILE_TMP="bin/configure-output.tmp" # Code sed --posix -e "/$HEAD/,/$TAIL/{ /$HEAD/{p; r $FILE_REPLACE }; /$TAIL/p; d }" $FILE_ORIGINAL > $FILE_TMP if [ $? = 0 ]; then chmod 755 $FILE_TMP mv -f $FILE_TMP $FILE_ORIGINAL else rm -f $FILE_TMP fi pmacct-1.7.8/COPYING0000644000175000017500000004531714354105275013057 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI: IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2021 by Paolo Lucente ------------------------------------------------------------------------ Part of pmacct is distributed under the ISC License, as following: Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------ Part of pmacct is distributed under the GPL License, as following: GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pmacct-1.7.8/configure.ac0000644000175000017500000011223014354105275014277 0ustar paolopaolodnl Process this file with autoconf to produce a configure script. dnl configuration file for pmacct m4_include([VERSION]) #Force reconf on VERSION change AC_INIT([pmacct], m4_esyscmd_s(cat VERSION), [paolo@pmacct.net]) AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_MACRO_DIR([m4]) LT_INIT AC_PREFIX_DEFAULT([/usr/local]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)]) PMACCT_VERSION=`cat $srcdir/VERSION` AC_SUBST(PMACCT_VERSION) COMPILE_ARGS="${ac_configure_args}" dnl Checks for programs. AC_PROG_CC dnl pkg-config stuff PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig export PKG_CONFIG_PATH PKG_PROG_PKG_CONFIG AC_CANONICAL_HOST AC_MSG_CHECKING(OS) AC_MSG_RESULT($host_os) AC_MSG_CHECKING(hardware) AC_MSG_RESULT($host_cpu) dnl initial checks; tweakings to CFLAGS and LDFLAGS dnl see final checks for tweakings to LIBS if test "x$ac_cv_prog_gcc" = xyes ; then CFLAGS="-O2 ${CFLAGS}" fi dnl: shared object handling AC_MSG_CHECKING([whether to disable linking against shared objects]) AC_ARG_ENABLE(so, [ --disable-so Disable linking against shared objects (default: no)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(no) AC_CHECK_FUNC(dlopen, [ USING_DLOPEN="yes" ], []) AC_CHECK_LIB(dl, dlopen, [ USING_DLOPEN="yes" LIBS="${LIBS} -ldl" ], []) if test x"$USING_DLOPEN" != x"yes"; then AC_MSG_ERROR(Unable to find dlopen(). Try with --disable-so) fi else AC_MSG_RESULT(yes) if test "x$ac_cv_prog_gcc" = xyes ; then LDFLAGS="-static ${LDFLAGS}" fi fi ], [ AC_MSG_RESULT(no) AC_CHECK_FUNC(dlopen, [ USING_DLOPEN="yes" ], []) AC_CHECK_LIB(dl, dlopen, [ USING_DLOPEN="yes" LIBS="${LIBS} -ldl" ], []) if test x"$USING_DLOPEN" != x"yes"; then AC_MSG_ERROR(Unable to find dlopen(). Try with --disable-so) fi ] ) dnl finish: shared object handling dnl os specific flags case "$host_os" in Sun*) AC_DEFINE(SOLARIS, 1) LIBS="-lresolv -lsocket -lnsl ${LIBS}" ;; *BSD) AC_DEFINE(BSD, 1) ;; linux*) AC_DEFINE(LINUX, 1) ;; esac AC_CHECK_PROG(MAKE, gmake, gmake) if test x"$MAKE" = x""; then AC_CHECK_PROG(MAKE, make, make) fi AC_SUBST(MAKE) AC_PROG_MAKE_SET dnl dnl some systems have __progname ; if this is the case and we play around argv dnl we need to enable a minor hack to make things work nicely. dnl AC_MSG_CHECKING(for __progname) AC_TRY_LINK([ extern char *__progname; ], [ __progname = "test"; ], [AC_MSG_RESULT(yes); AC_DEFINE(PROGNAME, 1)], [AC_MSG_RESULT(no)]) dnl dnl Check for architecture endianess: big | little dnl dnl XXX: switch to manually define this feature ac_cv_endianess="unknown" if test x"$ac_cv_endianess" = x"unknown"; then AC_MSG_CHECKING(endianess) AC_TRY_RUN([ #include int main () { union { long l; char c[sizeof (long)]; } u; u.l = 1; exit (u.c[sizeof (long) - 1] == 1); } ], ac_cv_endianess="little", ac_cv_endianess="big", ac_cv_endianess="little") AC_MSG_RESULT($ac_cv_endianess) fi if test x"$ac_cv_endianess" = x"big"; then AC_DEFINE(IM_BIG_ENDIAN, 1) fi if test x"$ac_cv_endianess" = x"little"; then AC_DEFINE(IM_LITTLE_ENDIAN, 1) fi dnl dnl Check for unaligned memory access; based entirely over dnl AC_LBL_UNALIGNED_ACCESS dnl dnl XXX: switch to manually define this feature; ac_cv_unaligned="unknown" case "$host_cpu" in alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_unaligned="fail" AC_MSG_CHECKING(unaligned accesses) AC_MSG_RESULT($ac_cv_unaligned) ;; esac if test x"$ac_cv_unaligned" = x"unknown"; then AC_MSG_CHECKING(unaligned accesses) cat > conftest.c << EOF #include #include #include #include #include unsigned char a[[5]] = { 1, 2, 3, 4, 5 }; int main () { unsigned int i; pid_t pid; int status; /* avoid "core dumped" message */ pid = fork(); if (pid < 0) exit(2); if (pid > 0) { /* parent */ pid = waitpid(pid, &status, 0); if (pid < 0) exit(3); exit(!WIFEXITED(status)); } /* child */ i = *(unsigned int *)&a[[1]]; printf("%d\n", i); exit(0); } EOF ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ conftest.c $LIBS >/dev/null 2>&1 if test ! -x conftest ; then ac_cv_unaligned="fail" else ./conftest >conftest.out if test ! -s conftest.out ; then ac_cv_unaligned="fail" else ac_cv_unaligned="ok" fi fi rm -f conftest* core core.conftest AC_MSG_RESULT($ac_cv_unaligned) fi if test x"$ac_cv_unaligned" = x"fail"; then AC_DEFINE(NEED_ALIGN, 1) fi AC_MSG_CHECKING([whether to enable L2 features]) AC_ARG_ENABLE(l2, [ --enable-l2 Enable Layer-2 features and support (default: yes)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_L2, 1) else AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_L2, 1) COMPILE_ARGS="${COMPILE_ARGS} '--enable-l2'" ] ) AC_CHECK_FUNCS(inet_pton) if test x"$ac_cv_func_inet_pton" = x"no"; then AC_MSG_ERROR(ERROR: missing inet_pton()) fi AC_CHECK_FUNCS(inet_ntop) if test x"$ac_cv_func_inet_ntop" = x"no"; then AC_MSG_ERROR(ERROR: missing inet_ntop()) fi AC_ARG_WITH(pcap-includes, [ --with-pcap-includes=DIR Search the specified directory for header files], [ AC_LINEARIZE_PATH($withval, withval=$absdir) INCLUDES="${INCLUDES} -I$withval" PCAPINCLS=$withval PCAPINCLUDESFOUND=1 ]) if test x"$PCAPINCLS" != x""; then AC_MSG_CHECKING(your own pcap includes) if test -r $PCAPINCLS/pcap.h; then AC_MSG_RESULT(ok) AC_DEFINE(HAVE_PCAP_H, 1) PCAPINCLUDESFOUND=1 else AC_MSG_RESULT(no) AC_MSG_ERROR(ERROR: missing pcap.h in $PCAPINCLS) fi fi AC_CHECK_PROG([PCAP_CONFIG], [pcap-config], [pcap-config], [no]) if test x"$PCAPINCLUDESFOUND" = x""; then if test ${PCAP_CONFIG} = "pcap-config"; then AC_MSG_CHECKING([using pcap-config for pcap.h]) PCAP_CONFIG_INCLUDES=`${PCAP_CONFIG} --cflags` INCLUDES="${INCLUDES} ${PCAP_CONFIG_INCLUDES}" AC_DEFINE(HAVE_PCAP_PCAP_H, 1) AC_MSG_RESULT([${PCAP_CONFIG_INCLUDES}]) PCAPINCLUDESFOUND=1 fi fi if test x"$PCAPINCLUDESFOUND" = x""; then AC_MSG_CHECKING([default locations for pcap.h]) if test -r /usr/include/pcap.h; then AC_MSG_RESULT([found in /usr/include]) PCAPINCLUDESFOUND=1 AC_DEFINE(HAVE_PCAP_H, 1) elif test -r /usr/include/pcap/pcap.h; then AC_MSG_RESULT([found in /usr/include]) PCAPINCLUDESFOUND=1 AC_DEFINE(HAVE_PCAP_PCAP_H, 1) elif test -r /usr/local/include/pcap.h; then AC_MSG_RESULT([found in /usr/local/include]) INCLUDES="${INCLUDES} -I/usr/local/include" PCAPINCLUDESFOUND=1 AC_DEFINE(HAVE_PCAP_H, 1) elif test -r /usr/local/include/pcap/pcap.h; then AC_MSG_RESULT([found in /usr/local/include]) INCLUDES="${INCLUDES} -I/usr/local/include" PCAPINCLUDESFOUND=1 AC_DEFINE(HAVE_PCAP_PCAP_H, 1) fi if test x"$PCAPINCLUDESFOUND" = x""; then AC_MSG_RESULT([not found]) AC_MSG_ERROR(ERROR: missing pcap.h) fi fi AC_ARG_WITH(pcap-libs, [ --with-pcap-libs=DIR Search the specified directory for pcap library], [ AC_LINEARIZE_PATH($withval, withval=$absdir) LIBS="${LIBS} -L$withval" PCAPLIB=$withval PCAPLIBFOUND=1 ]) if test x"$PCAPLIB" != x""; then AC_MSG_CHECKING(your own pcap libraries) if test -r $PCAPLIB/libpcap.a -o -r $PCAPLIB/libpcap.so; then AC_MSG_RESULT(ok) PCAP_LIB_FOUND=1 AC_MSG_CHECKING(for PF_RING library) if test -r $PCAPLIB/libpfring.a -o -r $PCAPLIB/libpfring.so; then LIBS="${LIBS} -lpfring -lpcap" AC_MSG_RESULT(yes) PFRING_LIB_FOUND=1 AC_DEFINE(PFRING_LIB_FOUND, 1) else AC_MSG_RESULT(no) fi else AC_MSG_RESULT(no) AC_MSG_ERROR(ERROR: unable to find pcap library in $PCAPLIB) fi fi if test x"$PCAPLIBFOUND" = x""; then AC_MSG_CHECKING([default locations for libpcap]) if test -r /usr/local/lib/libpcap.a -o -r /usr/local/lib/libpcap.so; then LIBS="${LIBS} -L/usr/local/lib" AC_MSG_RESULT([found in /usr/local/lib]) PCAPLIBFOUND=1 AC_MSG_CHECKING(for PF_RING library) if test -r /usr/local/lib/libpfring.a -o -r /usr/local/lib/libpfring.so; then LIBS="${LIBS} -lpfring -lpcap" AC_MSG_RESULT(yes) PFRING_LIB_FOUND=1 AC_DEFINE(PFRING_LIB_FOUND, 1) else AC_MSG_RESULT(no) fi else AC_MSG_RESULT(no) fi fi if test x"$PCAPLIBFOUND" = x""; then if test ${PCAP_CONFIG} = "pcap-config"; then AC_MSG_CHECKING([using pcap-config for libpcap]) PCAP_CONFIG_LIBS=`${PCAP_CONFIG} --libs` INCLUDES="${INCLUDES} ${PCAP_CONFIG_LIBS}" AC_MSG_RESULT([${PCAP_CONFIG_LIBS}]) PCAPLIBFOUND=1 fi fi dnl Checks for libraries. dnl libpcap is checked only if PF_RING is not found if test x"$PFRING_LIB_FOUND" = x""; then AC_CHECK_LIB([pcap], [pcap_dispatch], [], [AC_MSG_ERROR([ ERROR: missing pcap library. Refer to: http://www.tcpdump.org/ ])]) AC_CHECK_LIB([pcap], [pcap_set_protocol], [ AC_DEFINE(PCAP_SET_PROTOCOL, 1) ], []) else AC_CHECK_LIB([numa], [numa_bind], [], [AC_MSG_ERROR([ ERROR: missing libnuma. Requirement for building PF_RING. ])]) #AC_CHECK_LIB([rt], [clock_gettime], [], [AC_MSG_ERROR([ # ERROR: missing librt devel. Requirement for building PF_RING. #])]) LIBS="${LIBS} -lrt -lnuma" fi AC_CHECK_LIB([pcap], [pcap_setdirection], [ AC_DEFINE(PCAP_SET_DIRECTION, 1) ], []) dnl start: mysql handling AC_MSG_CHECKING(whether to enable MySQL support) AC_ARG_ENABLE(mysql, [ --enable-mysql Enable MySQL support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) dnl no pkg-config support for MySQL AC_CHECK_PROG([MYSQL_CONFIG], [mysql_config], [mysql_config], [no]) if test "x${MYSQL_CONFIG}" = "xno"; then AC_MSG_ERROR([ERROR: missing mysql_config program]) fi MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags` MYSQL_LIBS=`$MYSQL_CONFIG --libs` dnl version check not enforced with a AC_MSG_ERROR for now AX_LIB_MYSQL(5.6.3) AC_SUBST(MYSQL_CFLAGS) AC_SUBST(MYSQL_LIBS) PLUGINS="${PLUGINS} mysql" USING_SQL="yes" USING_MYSQL="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $MYSQL_CFLAGS" AC_DEFINE(WITH_MYSQL, 1) _save_LIBS="$LIBS" LIBS="$LIBS $MYSQL_LIBS" AC_CHECK_LIB([mysqlclient], [mysql_query]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MYSQL_CFLAGS" AC_CHECK_HEADERS([mysql.h mysql/mysql.h]) CFLAGS="$_save_CFLAGS" case "$host_os" in linux*) AC_CHECK_LIB([numa], [numa_bind], [], [AC_MSG_ERROR([ ERROR: missing libnuma. Requirement for building MySQL. ])]) ;; esac ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: mysql handling dnl start: pgsql handling AC_MSG_CHECKING(whether to enable PostgreSQL support) AC_ARG_ENABLE(pgsql, [ --enable-pgsql Enable PostgreSQL support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([PGSQL], [libpq >= 8.4], [ PLUGINS="${PLUGINS} pgsql" USING_SQL="yes" USING_PGSQL="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $PGSQL_CFLAGS" AC_DEFINE(WITH_PGSQL, 1) _save_LIBS="$LIBS" LIBS="$LIBS $PGSQL_LIBS" AC_CHECK_LIB([pq], [PQexec]) AC_CHECK_FUNCS([PQlibVersion]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PGSQL_CFLAGS" AC_CHECK_HEADER([libpq-fe.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing PQ library. Refer to: http://www.postgresql.org/download/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: pgsql handling dnl start: mongodb handling AC_MSG_CHECKING(whether to enable MongoDB support) AC_ARG_ENABLE(mongodb, [ --enable-mongodb Enable MongoDB support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([MONGODB], [libmongoc],, [ AC_MSG_CHECKING([default locations for libmongoc]) if test -r /usr/lib/libmongoc.a -o -r /usr/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/lib -lmongoc" AC_MSG_RESULT([found in /usr/lib]) elif test -r /usr/lib64/libmongoc.a -o -r /usr/lib64/libmongoc.so; then MONGODB_LIBS="-L/usr/lib64 -lmongoc" AC_MSG_RESULT([found in /usr/lib64]) elif test -r /usr/local/lib/libmongoc.a -o -r /usr/local/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/local/lib -lmongoc" AC_MSG_RESULT([found in /usr/local/lib]) else AC_MSG_RESULT([not found]) _save_LIBS="$LIBS" LIBS="$LIBS $MONGODB_LIBS" AC_CHECK_LIB([mongoc], [mongo_connect], [], [AC_MSG_ERROR([ ERROR: missing MongoDB library (0.8 version). Refer to: https://github.com/mongodb/mongo-c-driver-legacy ])]) LIBS="$_save_LIBS" fi AC_MSG_CHECKING([default locations for mongo.h]) if test -r /usr/include/mongo.h; then MONGODB_CFLAGS="-I/usr/include" AC_MSG_RESULT([found in /usr/include]) elif test -r /usr/local/include/mongo.h; then MONGODB_CFLAGS="-I/usr/local/include" AC_MSG_RESULT([found in /usr/local/include]) else AC_MSG_RESULT([not found]) _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MONGODB_CFLAGS" AC_CHECK_HEADER([mongo.h], [], [AC_MSG_ERROR(ERROR: missing MongoDB headers)]) CFLAGS="$_save_CFLAGS" fi ]) PLUGINS="${PLUGINS} mongodb" USING_MONGODB="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $MONGODB_CFLAGS" AC_DEFINE(WITH_MONGODB, 1) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: mongodb handling dnl start: sqlite3 handling AC_MSG_CHECKING(whether to enable SQLite3 support) AC_ARG_ENABLE(sqlite3, [ --enable-sqlite3 Enable SQLite3 support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) dnl reasonably old libsqlite3 already support pkg-config PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.7.13], [ PLUGINS="${PLUGINS} sqlite3" USING_SQL="yes" USING_SQLITE3="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $SQLITE3_CFLAGS" AC_DEFINE(WITH_SQLITE3, 1) _save_LIBS="$LIBS" LIBS="$LIBS $SQLITE3_LIBS" AC_CHECK_LIB([sqlite3], [sqlite3_exec]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SQLITE3_CFLAGS" AC_CHECK_HEADER([sqlite3.h]) CFLAGS="$_save_CFLAGS" ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: sqlite3 handling dnl start: RabbitMQ/AMQP handling AC_MSG_CHECKING(whether to enable RabbitMQ/AMQP support) AC_ARG_ENABLE(rabbitmq, [ --enable-rabbitmq Enable RabbitMQ/AMQP support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) dnl reasonably old librabbitmq already support pkg-config PKG_CHECK_MODULES([RABBITMQ], [librabbitmq >= 0.8.0], [ PLUGINS="${PLUGINS} rabbitmq" USING_RABBITMQ="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $RABBITMQ_CFLAGS" AC_DEFINE(WITH_RABBITMQ, 1) _save_LIBS="$LIBS" LIBS="$LIBS $RABBITMQ_LIBS" AC_CHECK_LIB([rabbitmq], [amqp_basic_publish]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $RABBITMQ_CFLAGS" AC_CHECK_HEADER([amqp.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing RabbitMQ C API. Refer to: https://github.com/alanxz/rabbitmq-c/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: RabbitMQ/AMQP handling dnl start: ZeroMQ handling AC_MSG_CHECKING(whether to enable ZeroMQ support) AC_ARG_ENABLE(zmq, [ --enable-zmq Enable ZeroMQ support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([ZMQ], [libzmq >= 4.2.0], [ SUPPORTS="${SUPPORTS} zmq" USING_ZMQ="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $ZMQ_CFLAGS" AC_DEFINE(WITH_ZMQ, 1) _save_LIBS="$LIBS" LIBS="$LIBS $ZMQ_LIBS" AC_CHECK_LIB([zmq], [zmq_send]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ZMQ_CFLAGS" AC_CHECK_HEADER([zmq.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing ZeroMQ. Refer to: http://zeromq.org/intro:get-the-software]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: ZeroMQ handling dnl start: Kafka handling AC_MSG_CHECKING(whether to enable Kafka support) AC_ARG_ENABLE(kafka, [ --enable-kafka Enable Kafka support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([KAFKA], [rdkafka >= 0.9.2], [ PLUGINS="${PLUGINS} kafka" USING_KAFKA="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $KAFKA_CFLAGS" AC_DEFINE(WITH_KAFKA, 1) _save_LIBS="$LIBS" LIBS="$LIBS $KAFKA_LIBS" AC_CHECK_LIB([rdkafka], [rd_kafka_produce]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $KAFKA_CFLAGS" AC_CHECK_HEADER([librdkafka/rdkafka.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing librdkafka. Refer to: https://github.com/edenhill/librdkafka/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: Kafka handling dnl start: Redis handling AC_MSG_CHECKING(whether to enable Redis support) AC_ARG_ENABLE(redis, [ --enable-redis Enable Redis support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([REDIS], [hiredis >= 0.13.0], [ SUPPORTS="${SUPPORTS} redis" USING_REDIS="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $REDIS_CFLAGS" AC_DEFINE(WITH_REDIS, 1) _save_LIBS="$LIBS" LIBS="$LIBS $REDIS_LIBS" AC_CHECK_LIB([hiredis], [redisConnect]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $REDIS_CFLAGS" AC_CHECK_HEADER([hiredis/hiredis.h]) CFLAGS="$_save_CFLAGS" ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: Redis handling dnl start: GnuTLS handling AC_MSG_CHECKING(whether to enable GnuTLS support) AC_ARG_ENABLE(gnutls, [ --enable-gnutls Enable GnuTLS support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.6], [ SUPPORTS="${SUPPORTS} gnutls" USING_GNUTLS="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GNUTLS_CFLAGS" AC_DEFINE(WITH_GNUTLS, 1) _save_LIBS="$LIBS" LIBS="$LIBS $GNUTLS_LIBS" AC_CHECK_LIB([gnutls], [gnutls_global_init]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $GNUTLS_CFLAGS" AC_CHECK_HEADER([gnutls/gnutls.h]) CFLAGS="$_save_CFLAGS" ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: GnuTLS handling dnl start: geoip handling AC_MSG_CHECKING(whether to enable GeoIP support) AC_ARG_ENABLE(geoip, [ --enable-geoip Enable GeoIP support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) dnl reasonably old Maxmind GeoIP v1 already support pkg-config PKG_CHECK_MODULES([GEOIP], [geoip >= 1.0.0], [ SUPPORTS="${SUPPORTS} geoip" USING_MMGEOIP="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GEOIP_CFLAGS" AC_DEFINE(WITH_GEOIP, 1) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) AC_MSG_CHECKING(whether to enable GeoIPv2 (libmaxminddb) support) AC_ARG_ENABLE(geoipv2, [ --enable-geoipv2 Enable GeoIPv2 (libmaxminddb) support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([GEOIPV2], [libmaxminddb >= 1.2], [ SUPPORTS="${SUPPORTS} geoipv2" USING_MMGEOIPV2="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GEOIPV2_CFLAGS" AC_DEFINE(WITH_GEOIPV2, 1) _save_LIBS="$LIBS" LIBS="$LIBS $GEOIPV2_LIBS" AC_CHECK_LIB([maxminddb], [MMDB_open]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $GEOIPV2_CFLAGS" AC_CHECK_HEADER([maxminddb.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing Maxmind libmaxminddb C library. Refer to: http://www.maxmind.com/download/geoip/api/c/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: GeoIP handling dnl start: Jansson handling AC_MSG_CHECKING(whether to enable Jansson support) AC_ARG_ENABLE(jansson, [ --enable-jansson Enable Jansson support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) dnl reasonably old Jansson already support pkg-config PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5], [ SUPPORTS="${SUPPORTS} jansson" USING_JANSSON="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $JANSSON_CFLAGS" AC_DEFINE(WITH_JANSSON, 1) _save_LIBS="$LIBS" LIBS="$LIBS $JANSSON_LIBS" AC_CHECK_LIB([jansson], [json_object]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $JANSSON_CFLAGS" AC_CHECK_HEADER([jansson.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing libjansson. Refer to: http://www.digip.org/jansson/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: Jansson handling dnl start: Avro handling AC_MSG_CHECKING(whether to enable Avro support) AC_ARG_ENABLE(avro, [ --enable-avro Enable Apache Avro support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([AVRO], [avro-c >= 1.8], [ SUPPORTS="${SUPPORTS} avro" USING_AVRO="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $AVRO_CFLAGS" AC_DEFINE(WITH_AVRO, 1) _save_LIBS="$LIBS" LIBS="$LIBS $AVRO_LIBS" AC_CHECK_LIB([avro], [avro_record_get]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $AVRO_CFLAGS" AC_CHECK_HEADER([avro.h]) CFLAGS="$_save_CFLAGS" ], [ AC_MSG_ERROR([Missing Apache Avro C library. Refer to: http://www.apache.org/dyn/closer.cgi/avro/]) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: Avro handling dnl start: libserdes handling AC_MSG_CHECKING(whether to enable Confluent schema-registry support) AC_ARG_ENABLE(serdes, [ --enable-serdes Enable Confluent schema-registry support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_SUBST(SERDES_CFLAGS) AC_SUBST(SERDES_LIBS) SUPPORTS="${SUPPORTS} serdes" USING_SERDES="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $SERDES_CFLAGS" SERDES_LIBS="$SERDES_LIBS -lserdes" AC_DEFINE(WITH_SERDES, 1) _save_LIBS="$LIBS" LIBS="$LIBS $SERDES_LIBS" AC_CHECK_LIB([serdes], [serdes_new],, AC_MSG_ERROR([Missing Confluent serdes library. Refer to: https://github.com/confluentinc/libserdes])) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SERDES_CFLAGS" AC_CHECK_HEADER([libserdes/serdes.h],, AC_MSG_ERROR([Missing Confluent serdes headers. Refer to: https://github.com/confluentinc/libserdes])) CFLAGS="$_save_CFLAGS" ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: libserdes handling dnl start: nDPI handling AC_ARG_WITH(ndpi-static-lib, [ --with-ndpi-static-lib=DIR Search the specified directory for nDPI static library], [ AC_LINEARIZE_PATH($withval, withval=$absdir) NDPI_CUST_STATIC_LIB=$withval ]) if test x"$NDPI_CUST_STATIC_LIB" != x""; then AC_MSG_CHECKING(your own nDPI library) if test -r $NDPI_CUST_STATIC_LIB/libndpi.a; then AC_MSG_RESULT(ok) NDPI_CUST_STATIC_LIB_FOUND="yes" else AC_MSG_RESULT(no) AC_MSG_ERROR(ERROR: unable to find nDPI library in $NDPI_CUST_STATIC_LIB) fi fi AC_MSG_CHECKING(whether to enable nDPI support) AC_ARG_ENABLE(ndpi, [ --enable-ndpi Enable nDPI support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([NDPI], [libndpi >= 4.0], [ SUPPORTS="${SUPPORTS} ndpi" USING_NDPI="yes" if test x"$NDPI_CFLAGS" != x""; then NDPI_CFLAGS_INST=`echo $NDPI_CFLAGS | sed 's/ $//'` NDPI_CFLAGS_INST="$NDPI_CFLAGS_INST/libndpi" else NDPI_CFLAGS_INST="" fi PMACCT_CFLAGS="$PMACCT_CFLAGS $NDPI_CFLAGS $NDPI_CFLAGS_INST" AC_DEFINE(WITH_NDPI, 1) _save_LIBS="$LIBS" LIBS="$LIBS $NDPI_LIBS" AC_CHECK_LIB([ndpi], [ndpi_init_detection_module]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $NDPI_CFLAGS" AC_CHECK_HEADER([libndpi/ndpi_main.h]) CFLAGS="$_save_CFLAGS" ], [AC_MSG_ERROR([Missing nDPI API. Refer to: https://github.com/ntop/nDPI/])]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: nDPI handling dnl start: unyte udp notif handling AC_MSG_CHECKING(whether to enable Unyte UDP-Notif support) AC_ARG_ENABLE(unyte-udp-notif, [ --enable-unyte-udp-notif Enable Unyte UDP Notif support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([UNYTE_UDP_NOTIF], [unyte-udp-notif >= 0.6.0], [ AC_SUBST(UNYTE_UDP_NOTIF_CFLAGS) AC_SUBST(UNYTE_UDP_NOTIF_LIBS) SUPPORTS="${SUPPORTS} unyte-udp-notif" USING_UNYTE_UDP_NOTIF="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $UNYTE_UDP_NOTIF_CFLAGS" UNYTE_UDP_NOTIF_LIBS="$UNYTE_UDP_NOTIF_LIBS -lunyte-udp-notif" AC_DEFINE(WITH_UNYTE_UDP_NOTIF, 1) _save_LIBS="$LIBS" LIBS="$LIBS $UNYTE_UDP_NOTIF_LIBS -lpthread" AC_CHECK_LIB([unyte-udp-notif], [unyte_udp_start_collector], [], [AC_MSG_ERROR([ ERROR: missing unyte-udp-notif library. Refer to: https://github.com/insa-unyte/udp-notif-c-collector ])]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $UNYTE_UDP_NOTIF_CFLAGS" AC_CHECK_HEADER([unyte-udp-notif/unyte_udp_collector.h], [], [AC_MSG_ERROR(ERROR: missing unyte-udp-notif headers)]) CFLAGS="$_save_CFLAGS" ], [AC_MSG_ERROR([ERROR: missing unyte-udp-notif pkg-config. Refer to: https://github.com/insa-unyte/udp-notif-c-collector])]) ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: unyte udp notif handling dnl start: eBPF handling AC_MSG_CHECKING(whether to enable eBPF support) AC_ARG_ENABLE(ebpf, [ --enable-ebpf Enable eBPF support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_SUBST(EBPF_CFLAGS) AC_SUBST(EBPF_LIBS) SUPPORTS="${SUPPORTS} ebpf" USING_EBPF="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $EBPF_CFLAGS" EBPF_LIBS="$EBPF_LIBS -lbpf" AC_DEFINE(WITH_EBPF, 1) _save_LIBS="$LIBS" LIBS="$LIBS $EBPF_LIBS" AC_CHECK_LIB([bpf], [bpf_object__open_file], [], [AC_MSG_ERROR([ ERROR: missing libbpf library. Refer to: https://github.com/libbpf/libbpf ])]) LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $EBPF_CFLAGS" AC_CHECK_HEADER([bpf/libbpf.h], [], [AC_MSG_ERROR(ERROR: missing libbpf headers)]) CFLAGS="$_save_CFLAGS" ;; no) AC_MSG_RESULT(no) ;; esac ], [ AC_MSG_RESULT(no) ] ) dnl finish: ebpf handling if test x"$USING_DLOPEN" = x"yes"; then AC_DEFINE(HAVE_DLOPEN, 1) else # Adding linking to libdl here 1) if required and 2) in case of --disable-so if test x"$USING_MYSQL" = x"yes" -o x"$USING_SQLITE3" = x"yes"; then AC_CHECK_LIB([dl], [dlopen], [LIBS="${LIBS} -ldl"], [AC_MSG_ERROR([ ERROR: missing libdl devel. ])]) fi fi if test x"$USING_SQL" = x"yes"; then AC_CHECK_LIB([z], [zlibVersion], [], [AC_MSG_ERROR([ERROR: missing zlib. Requirement for building SQL plugins.])]) fi LIBS="${LIBS} -lm -lpthread" dnl Checks for header files. AC_HEADER_STDC dnl Extra checks for header files AC_CHECK_HEADERS([arpa/inet.h assert.h ctype.h dirent.h dlfcn.h errno.h fcntl.h getopt.h grp.h inttypes.h]) AC_CHECK_HEADERS([limits.h malloc.h math.h netdb.h net/if.h netinet/in.h netinet/in_systm.h netinet/ip.h]) AC_CHECK_HEADERS([netinet/udp.h pthread.h pwd.h signal.h string.h sys/ansi.h sys/errno.h sys/file.h]) AC_CHECK_HEADERS([sys/ioctl.h syslog.h sys/mbuf.h sys/mman.h sys/param.h sys/poll.h sys/resource.h]) AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/stat.h sys/time.h sys/types.h sys/un.h sys/utsname.h]) AC_CHECK_HEADERS([sys/wait.h time.h unistd.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_CHECK_TYPE(u_int64_t, [AC_DEFINE(HAVE_U_INT64_T, 1)]) AC_CHECK_TYPE(u_int32_t, [AC_DEFINE(HAVE_U_INT32_T, 1)]) AC_CHECK_TYPE(u_int16_t, [AC_DEFINE(HAVE_U_INT16_T, 1)]) AC_CHECK_TYPE(u_int8_t, [AC_DEFINE(HAVE_U_INT8_T, 1)]) AC_CHECK_TYPE(uint64_t, [AC_DEFINE(HAVE_UINT64_T, 1)]) AC_CHECK_TYPE(uint32_t, [AC_DEFINE(HAVE_UINT32_T, 1)]) AC_CHECK_TYPE(uint16_t, [AC_DEFINE(HAVE_UINT16_T, 1)]) AC_CHECK_TYPE(uint8_t, [AC_DEFINE(HAVE_UINT8_T, 1)]) AC_MSG_CHECKING(whether to enable NFLOG support) AC_ARG_ENABLE(nflog, [ --enable-nflog Enable NFLOG support (default: no)], [ case "$enableval" in yes) AC_MSG_RESULT(yes) PKG_CHECK_MODULES([NFLOG], [libnetfilter_log >= 1], [ SUPPORTS="${SUPPORTS} nflog" USING_NFLOG="yes" AC_DEFINE(WITH_NFLOG, 1) ]) ;; no) AC_MSG_RESULT(no) ;; esac ], AC_MSG_RESULT(no)) AC_MSG_CHECKING(whether to link IPv4/IPv6 traffic accounting accounting binaries) AC_ARG_ENABLE(traffic-bins, [ --enable-traffic-bins Link IPv4/IPv6 traffic accounting binaries (default: yes)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_TRAFFIC_BINS, 1) USING_TRAFFIC_BINS="yes" else AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_TRAFFIC_BINS, 1) USING_TRAFFIC_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-traffic-bins'" ] ) AC_MSG_CHECKING(whether to link BGP daemon binaries) AC_ARG_ENABLE(bgp-bins, [ --enable-bgp-bins Link BGP daemon binaries (default: yes)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_BGP_BINS, 1) USING_BGP_BINS="yes" else AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_BGP_BINS, 1) USING_BGP_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-bgp-bins'" ] ) AC_MSG_CHECKING(whether to link BMP daemon binaries) AC_ARG_ENABLE(bmp-bins, [ --enable-bmp-bins Link BMP daemon binaries (default: yes)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_BMP_BINS, 1) USING_BMP_BINS="yes" else AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_BMP_BINS, 1) USING_BMP_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-bmp-bins'" ] ) AC_MSG_CHECKING(whether to link Streaming Telemetry daemon binaries) AC_ARG_ENABLE(st-bins, [ --enable-st-bins Link Streaming Telemetry daemon binaries (default: yes)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ST_BINS, 1) USING_ST_BINS="yes" else AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ST_BINS, 1) USING_ST_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-st-bins'" ] ) dnl Checks for library functions. AC_TYPE_SIGNAL AC_CHECK_FUNCS([setproctitle mallopt tdestroy strlcpy vfork]) dnl Check for SO_BINDTODEVICE AC_CHECK_DECL([SO_BINDTODEVICE], AC_DEFINE(HAVE_SO_BINDTODEVICE, 1, [Check if kernel supports SO_BINDTODEVICE]),, [ #include ] ) dnl Check for SO_REUSEPORT & friends AC_CHECK_DECL([SO_REUSEPORT], AC_DEFINE(HAVE_SO_REUSEPORT, 1, [Check if kernel supports SO_REUSEPORT]),, [ #include #include ] ) AC_CHECK_DECL([SO_ATTACH_REUSEPORT_EBPF], AC_DEFINE(HAVE_SO_ATTACH_REUSEPORT_EBPF, 1, [Check if kernel supports SO_ATTACH_REUSEPORT_EBPF]),, [ #include #include ] ) dnl -------------------------------------- dnl Git submodule Dependencies buid system dnl -------------------------------------- dnl First check whether to build git submodule deps WITH_EXTERNAL_DEPS_DEFAULT=yes if [ test ! -f "$srcdir/src/external_libs/libcdada/include/cdada.h" ] && [ test -z `git rev-parse HEAD 2> /dev/null` ]; then WITH_EXTERNAL_DEPS_DEFAULT=no fi AC_MSG_CHECKING([whether external dependencies (git submodules) should be compiled]) AC_ARG_WITH(external-deps, AS_HELP_STRING([--without-external-deps], [Do not build external dependencies (git submodules), specially useful for package maintainers [default=with]]), [WITH_EXTERNAL_DEPS="$withval"], [WITH_EXTERNAL_DEPS="$WITH_EXTERNAL_DEPS_DEFAULT"] ) if test x"$WITH_EXTERNAL_DEPS" = x"yes"; then dnl Compiled-in dependencies INCLUDES="-I${ac_pwd}/src/external_libs/rootfs/include ${INCLUDES} " LDFLAGS="-L${ac_pwd}/src/external_libs/rootfs/lib ${LDFLAGS}" AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([WITH_EXTERNAL_DEPS], [test "x$WITH_EXTERNAL_DEPS" = "xyes"]) AS_CASE(["$AM_DEFAULT_VERBOSITY"], [0], [AC_SUBST([configure_silent_rules_val], [--enable-silent-rules])], [1], [AC_SUBST([configure_silent_rules_val], [--disable-silent-rules])], [AC_SUBST([configure_silent_rules_val], [--enable-silent-rules])]) dnl -------------------------------------- dnl libcdada requires C++ (and needs to add libstdc++ to LDFLAGS AC_PROG_CXX AC_MSG_CHECKING([for a valid C++ compiler]) AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],[AC_MSG_RESULT(yes)],[AC_MSG_ERROR([No C++ compiler found])]) AC_LANG_POP([C++]) LIBS="-lcdada -lstdc++ ${LIBS}" AS_CASE(["$WITH_EXTERNAL_DEPS"], [yes], [], [no], [AC_CHECK_LIB([cdada], [cdada_get_ver], [], [AC_MSG_ERROR([Could not find libcdada])])], []) dnl set debug level AC_MSG_CHECKING([whether to enable debugging compiler options]) AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging compiler options (default: no)], [ if test x$enableval = x"yes" ; then AC_MSG_RESULT(yes) tmp_CFLAGS=`echo $CFLAGS | sed 's/O2/O0/g'` CFLAGS="$tmp_CFLAGS" CFLAGS="$CFLAGS -g -Wall -Werror" else CFLAGS="$CFLAGS -Wall -Werror" AC_MSG_RESULT(no) fi ], [ AC_MSG_RESULT(no) ] ) dnl Necessary for autogenerated build string INCLUDES="${INCLUDES} -I$(pwd)/src" dnl final checks dnl trivial solution to portability issue AC_DEFINE_UNQUOTED(COMPILE_ARGS, "$COMPILE_ARGS") CFLAGS="${CFLAGS} ${INCLUDES}" INCLUDES="" echo " PLATFORM ..... : `uname -m` OS ........... : `uname -rs` (`uname -n`) COMPILER ..... : ${CC} CFLAGS ....... : ${CFLAGS} LIBS ......... : ${LIBS} LDFLAGS ...... : ${LDFLAGS} PLUGINS ...... : ${PLUGINS} SUPPORTS ..... : ${SUPPORTS} Now type 'make' to compile the source code. Wanting to get in touch with other pmacct users? Join the pmacct mailing-list with an email to pmacct-discussion-subscribe@pmacct.net Need for documentation and examples? Start by reading the README.md file Star, watch or contribute to the project on GitHub: https://github.com/pmacct/pmacct " AC_SUBST([PMACCT_CFLAGS]) AM_CONDITIONAL([WITH_MYSQL], [test x"$USING_MYSQL" = x"yes"]) AM_CONDITIONAL([WITH_PGSQL], [test x"$USING_PGSQL" = x"yes"]) AM_CONDITIONAL([WITH_MONGODB], [test x"$USING_MONGODB" = x"yes"]) AM_CONDITIONAL([WITH_SQLITE3], [test x"$USING_SQLITE3" = x"yes"]) AM_CONDITIONAL([WITH_RABBITMQ], [test x"$USING_RABBITMQ" = x"yes"]) AM_CONDITIONAL([WITH_ZMQ], [test x"$USING_ZMQ" = x"yes"]) AM_CONDITIONAL([WITH_KAFKA], [test x"$USING_KAFKA" = x"yes"]) AM_CONDITIONAL([WITH_REDIS], [test x"$USING_REDIS" = x"yes"]) AM_CONDITIONAL([WITH_GNUTLS], [test x"$USING_GNUTLS" = x"yes"]) AM_CONDITIONAL([USING_SQL], [test x"$USING_SQL" = x"yes"]) AM_CONDITIONAL([WITH_JANSSON], [test x"$USING_JANSSON" = x"yes"]) AM_CONDITIONAL([WITH_AVRO], [test x"$USING_AVRO" = x"yes"]) AM_CONDITIONAL([WITH_SERDES], [test x"$USING_SERDES" = x"yes"]) AM_CONDITIONAL([WITH_NDPI], [test x"$USING_NDPI" = x"yes"]) AM_CONDITIONAL([WITH_UNYTE_UDP_NOTIF], [test x"$USING_UNYTE_UDP_NOTIF" = x"yes"]) AM_CONDITIONAL([WITH_EBPF], [test x"$USING_EBPF" = x"yes"]) AM_CONDITIONAL([WITH_NFLOG], [test x"$USING_NFLOG" = x"yes"]) AM_CONDITIONAL([WITH_DLOPEN], [test x"$USING_DLOPEN" = x"yes"]) AM_CONDITIONAL([USING_TRAFFIC_BINS], [test x"$USING_TRAFFIC_BINS" = x"yes"]) AM_CONDITIONAL([USING_BGP_BINS], [test x"$USING_BGP_BINS" = x"yes"]) AM_CONDITIONAL([USING_BMP_BINS], [test x"$USING_BMP_BINS" = x"yes"]) AM_CONDITIONAL([USING_ST_BINS], [test x"$USING_ST_BINS" = x"yes"]) AC_CONFIG_FILES([ src/pmacct-version.h ]) AC_OUTPUT([ Makefile \ src/Makefile src/external_libs/Makefile \ src/nfprobe_plugin/Makefile \ src/sfprobe_plugin/Makefile src/bgp/Makefile \ src/tee_plugin/Makefile src/isis/Makefile \ src/bmp/Makefile src/rpki/Makefile \ src/telemetry/Makefile src/ndpi/Makefile \ src/filters/Makefile examples/lg/Makefile \ src/ebpf/Makefile examples/custom/Makefile ]) pmacct-1.7.8/LICENSE.template0000644000175000017500000000200314354105275014624 0ustar paolopaoloBelow is an example license to be used for new code in pmacct, modeled after the ISC license. This template was copied from the OpenBSD project. It is important to specify the year of the copyright, e.g. "Copyright (c) 2003, 2004". /* * Copyright (c) YYYY YOUR NAME HERE * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ pmacct-1.7.8/include/0000755000175000017500000000000014354105275013435 5ustar paolopaolopmacct-1.7.8/include/sll.h0000644000175000017500000001264614354105275014411 0ustar paolopaolo/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#) $Header$ (LBL) */ /* * For captures on Linux cooked sockets, we construct a fake header * that includes: * * a 2-byte "packet type" which is one of: * * LINUX_SLL_HOST packet was sent to us * LINUX_SLL_BROADCAST packet was broadcast * LINUX_SLL_MULTICAST packet was multicast * LINUX_SLL_OTHERHOST packet was sent to somebody else * LINUX_SLL_OUTGOING packet was sent *by* us; * * a 2-byte Ethernet protocol field; * * a 2-byte link-layer type; * * a 2-byte link-layer address length; * * an 8-byte source link-layer address, whose actual length is * specified by the previous value. * * All fields except for the link-layer address are in network byte order. * * DO NOT change the layout of this structure, or change any of the * LINUX_SLL_ values below. If you must change the link-layer header * for a "cooked" Linux capture, introduce a new DLT_ type (ask * "tcpdump-workers@tcpdump.org" for one, so that you don't give it a * value that collides with a value already being used), and use the * new header in captures of that type, so that programs that can * handle DLT_LINUX_SLL captures will continue to handle them correctly * without any change, and so that capture files with different headers * can be told apart and programs that read them can dissect the * packets in them. * * This structure, and the #defines below, must be the same in the * libpcap and tcpdump versions of "sll.h". */ /* * A DLT_LINUX_SLL fake link-layer header. */ #define SLL_HDR_LEN 16 /* total header length */ #define SLL_ADDRLEN 8 /* length of address field */ struct sll_header { u_int16_t sll_pkttype; /* packet type */ u_int16_t sll_hatype; /* link-layer address type */ u_int16_t sll_halen; /* link-layer address length */ u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ u_int16_t sll_protocol; /* protocol */ }; /* * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the * PACKET_ values on Linux, but are defined here so that they're * available even on systems other than Linux, and so that they * don't change even if the PACKET_ values change. */ #define LINUX_SLL_HOST 0 #define LINUX_SLL_BROADCAST 1 #define LINUX_SLL_MULTICAST 2 #define LINUX_SLL_OTHERHOST 3 #define LINUX_SLL_OUTGOING 4 /* * The LINUX_SLL_ values for "sll_protocol"; these correspond to the * ETH_P_ values on Linux, but are defined here so that they're * available even on systems other than Linux. We assume, for now, * that the ETH_P_ values won't change in Linux; if they do, then: * * if we don't translate them in "pcap-linux.c", capture files * won't necessarily be readable if captured on a system that * defines ETH_P_ values that don't match these values; * * if we do translate them in "pcap-linux.c", that makes life * unpleasant for the BPF code generator, as the values you test * for in the kernel aren't the values that you test for when * reading a capture file, so the fixup code run on BPF programs * handed to the kernel ends up having to do more work. * * Add other values here as necessary, for handling packet types that * might show up on non-Ethernet, non-802.x networks. (Not all the ones * in the Linux "if_ether.h" will, I suspect, actually show up in * captures.) */ #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */ #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */ pmacct-1.7.8/include/ah.h0000644000175000017500000000454514354105275014206 0ustar paolopaolo/* $NetBSD: ah.h,v 1.12 2000/07/23 05:23:04 itojun Exp $ */ /* $KAME: ah.h,v 1.12 2000/07/20 17:41:01 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* * RFC1826/2402 authentication header. */ #ifndef _NETINET6_AH_H_ #define _NETINET6_AH_H_ struct ah { u_int8_t ah_nxt; /* Next Header */ u_int8_t ah_len; /* Length of data, in 32bit */ u_int16_t ah_reserve; /* Reserved for future use */ u_int32_t ah_spi; /* Security parameter index */ /* variable size, 32bit bound*/ /* Authentication data */ }; struct newah { u_int8_t ah_nxt; /* Next Header */ u_int8_t ah_len; /* Length of data + 1, in 32bit */ u_int16_t ah_reserve; /* Reserved for future use */ u_int32_t ah_spi; /* Security parameter index */ u_int32_t ah_seq; /* Sequence number field */ /* variable size, 32bit bound*/ /* Authentication data */ }; #endif /*_NETINET6_AH_H_*/ pmacct-1.7.8/include/ieee802_11.h0000644000175000017500000001255214354105275015255 0ustar paolopaolo/* @(#) $Header$ (LBL) */ /* * Copyright (c) 2001 * Fortress Technologies * Charlie Lenahan ( clenahan@fortresstech.com ) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #define IEEE802_11_FC_LEN 2 #define T_MGMT 0x0 /* management */ #define T_CTRL 0x1 /* control */ #define T_DATA 0x2 /* data */ #define T_RESV 0x3 /* reserved */ #define ST_ASSOC_REQUEST 0x0 #define ST_ASSOC_RESPONSE 0x1 #define ST_REASSOC_REQUEST 0x2 #define ST_REASSOC_RESPONSE 0x3 #define ST_PROBE_REQUEST 0x4 #define ST_PROBE_RESPONSE 0x5 /* RESERVED 0x6 */ /* RESERVED 0x7 */ #define ST_BEACON 0x8 #define ST_ATIM 0x9 #define ST_DISASSOC 0xA #define ST_AUTH 0xB #define ST_DEAUTH 0xC /* RESERVED 0xD */ /* RESERVED 0xE */ /* RESERVED 0xF */ #define CTRL_PS_POLL 0xA #define CTRL_RTS 0xB #define CTRL_CTS 0xC #define CTRL_ACK 0xD #define CTRL_CF_END 0xE #define CTRL_END_ACK 0xF /* * Bits in the frame control field. */ #define FC_VERSION(fc) ((fc) & 0x3) #define FC_TYPE(fc) (((fc) >> 2) & 0x3) #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) #define FC_TO_DS(fc) ((fc) & 0x0100) #define FC_FROM_DS(fc) ((fc) & 0x0200) #define FC_MORE_FLAG(fc) ((fc) & 0x0400) #define FC_RETRY(fc) ((fc) & 0x0800) #define FC_POWER_MGMT(fc) ((fc) & 0x1000) #define FC_MORE_DATA(fc) ((fc) & 0x2000) #define FC_WEP(fc) ((fc) & 0x4000) #define FC_ORDER(fc) ((fc) & 0x8000) struct mgmt_header_t { u_int16_t fc; u_int16_t duration; u_int8_t da[6]; u_int8_t sa[6]; u_int8_t bssid[6]; u_int16_t seq_ctrl; }; #define MGMT_HEADER_LEN (2+2+6+6+6+2) #define CAPABILITY_ESS(cap) ((cap) & 0x0001) #define CAPABILITY_IBSS(cap) ((cap) & 0x0002) #define CAPABILITY_CFP(cap) ((cap) & 0x0004) #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) struct ssid_t { u_int8_t element_id; u_int8_t length; u_char ssid[33]; /* 32 + 1 for null */ } ; struct rates_t { u_int8_t element_id; u_int8_t length; u_int8_t rate[8]; }; struct challenge_t { u_int8_t element_id; u_int8_t length; u_int8_t text[254]; /* 1-253 + 1 for null */ }; struct fh_t { u_int8_t element_id; u_int8_t length; u_int16_t dwell_time; u_int8_t hop_set; u_int8_t hop_pattern; u_int8_t hop_index; }; struct ds_t { u_int8_t element_id; u_int8_t length; u_int8_t channel; }; struct cf_t { u_int8_t element_id; u_int8_t length; u_int8_t count; u_int8_t period; u_int16_t max_duration; u_int16_t dur_remaing; }; struct tim_t { u_int8_t element_id; u_int8_t length; u_int8_t count; u_int8_t period; u_int8_t bitmap_control; u_int8_t bitmap[251]; }; #define E_SSID 0 #define E_RATES 1 #define E_FH 2 #define E_DS 3 #define E_CF 4 #define E_TIM 5 #define E_IBSS 6 /* reserved 7 */ /* reserved 8 */ /* reserved 9 */ /* reserved 10 */ /* reserved 11 */ /* reserved 12 */ /* reserved 13 */ /* reserved 14 */ /* reserved 15 */ /* reserved 16 */ #define E_CHALLENGE 16 /* reserved 17 */ /* reserved 18 */ /* reserved 19 */ /* reserved 16 */ /* reserved 16 */ struct mgmt_body_t { u_int8_t timestamp[8]; u_int16_t beacon_interval; u_int16_t listen_interval; u_int16_t status_code; u_int16_t aid; u_char ap[6]; u_int16_t reason_code; u_int16_t auth_alg; u_int16_t auth_trans_seq_num; struct challenge_t challenge; u_int16_t capability_info; struct ssid_t ssid; struct rates_t rates; struct ds_t ds; struct cf_t cf; struct fh_t fh; struct tim_t tim; }; struct ctrl_rts_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t ta[6]; u_int8_t fcs[4]; }; #define CTRL_RTS_LEN (2+2+6+6+4) struct ctrl_cts_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t fcs[4]; }; #define CTRL_CTS_LEN (2+2+6+4) struct ctrl_ack_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t fcs[4]; }; #define CTRL_ACK_LEN (2+2+6+4) struct ctrl_ps_poll_t { u_int16_t fc; u_int16_t aid; u_int8_t bssid[6]; u_int8_t ta[6]; u_int8_t fcs[4]; }; #define CTRL_PS_POLL_LEN (2+2+6+6+4) struct ctrl_end_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t bssid[6]; u_int8_t fcs[4]; }; #define CTRL_END_LEN (2+2+6+6+4) struct ctrl_end_ack_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t bssid[6]; u_int8_t fcs[4]; }; #define CTRL_END_ACK_LEN (2+2+6+6+4) #define IV_IV(iv) ((iv) & 0xFFFFFF) #define IV_PAD(iv) (((iv) >> 24) & 0x3F) #define IV_KEYID(iv) (((iv) >> 30) & 0x03) pmacct-1.7.8/include/extract.h0000644000175000017500000000450714354105275015266 0ustar paolopaolo/* * Copyright (c) 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#) $Header$ (LBL) */ /* Network to host order macros */ #ifdef LBL_ALIGN #define EXTRACT_16BITS(p) \ ((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \ (u_int16_t)*((const u_int8_t *)(p) + 1)) #define EXTRACT_32BITS(p) \ ((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 3)) #else #define EXTRACT_16BITS(p) \ ((u_int16_t)ntohs(*(const u_int16_t *)(p))) #define EXTRACT_32BITS(p) \ ((u_int32_t)ntohl(*(const u_int32_t *)(p))) #endif #define EXTRACT_24BITS(p) \ ((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 2)) /* Little endian protocol host order macros */ #define EXTRACT_LE_8BITS(p) (*(p)) #define EXTRACT_LE_16BITS(p) \ ((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int16_t)*((const u_int8_t *)(p) + 0)) #define EXTRACT_LE_32BITS(p) \ ((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \ (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 0)) pmacct-1.7.8/include/llc.h0000644000175000017500000000670714354105275014372 0ustar paolopaolo/* * Copyright (c) 1993, 1994, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#) $Header$ (LBL) */ /* * This stuff should come from a system header file, but there's no * obviously portable way to do that and it's not really going * to change from system to system. */ /* * A somewhat abstracted view of the LLC header */ struct llc { u_int8_t dsap; u_int8_t ssap; union { u_int8_t u_ctl; u_int16_t is_ctl; struct { u_int8_t snap_ui; u_int8_t snap_pi[5]; } snap; struct { u_int8_t snap_ui; u_int8_t snap_orgcode[3]; u_int8_t snap_ethertype[2]; } snap_ether; } ctl; }; #define llcui ctl.snap.snap_ui #define llcpi ctl.snap.snap_pi #define llc_orgcode ctl.snap_ether.snap_orgcode #define llc_ethertype ctl.snap_ether.snap_ethertype #define llcis ctl.is_ctl #define llcu ctl.u_ctl #define LLC_U_FMT 3 #define LLC_GSAP 1 #define LLC_S_FMT 1 #define LLC_U_POLL 0x10 #define LLC_IS_POLL 0x0100 #define LLC_XID_FI 0x81 #define LLC_U_CMD(u) ((u) & 0xef) #define LLC_UI 0x03 #define LLC_UA 0x63 #define LLC_DISC 0x43 #define LLC_DM 0x0f #define LLC_SABME 0x6f #define LLC_TEST 0xe3 #define LLC_XID 0xaf #define LLC_FRMR 0x87 #define LLC_S_CMD(is) (((is) >> 1) & 0x03) #define LLC_RR 0x0001 #define LLC_RNR 0x0005 #define LLC_REJ 0x0009 #define LLC_IS_NR(is) (((is) >> 9) & 0x7f) #define LLC_I_NS(is) (((is) >> 1) & 0x7f) #ifndef LLCSAP_NULL #define LLCSAP_NULL 0x00 #endif #ifndef LLCSAP_GLOBAL #define LLCSAP_GLOBAL 0xff #endif #ifndef LLCSAP_8021B_I #define LLCSAP_8021B_I 0x02 #endif #ifndef LLCSAP_8021B_G #define LLCSAP_8021B_G 0x03 #endif #ifndef LLCSAP_IP #define LLCSAP_IP 0x06 #endif #ifndef LLCSAP_PROWAYNM #define LLCSAP_PROWAYNM 0x0e #endif #ifndef LLCSAP_8021D #define LLCSAP_8021D 0x42 #endif #ifndef LLCSAP_RS511 #define LLCSAP_RS511 0x4e #endif #ifndef LLCSAP_ISO8208 #define LLCSAP_ISO8208 0x7e #endif #ifndef LLCSAP_PROWAY #define LLCSAP_PROWAY 0x8e #endif #ifndef LLCSAP_SNAP #define LLCSAP_SNAP 0xaa #endif #ifndef LLCSAP_IPX #define LLCSAP_IPX 0xe0 #endif #ifndef LLCSAP_NETBEUI #define LLCSAP_NETBEUI 0xf0 #endif #ifndef LLCSAP_ISONS #define LLCSAP_ISONS 0xfe #endif #define OUI_ENCAP_ETHER 0x000000 /* encapsulated Ethernet */ #define OUI_CISCO 0x00000c /* Cisco protocols */ #define ETHERTYPE_CISCO_CDP 0x2000 /* Cisco Discovery Protocol */ #define OUI_CISCO_90 0x0000f8 /* Cisco bridging */ #define OUI_APPLETALK 0x080007 /* Appletalk */ pmacct-1.7.8/include/ip6.h0000644000175000017500000001653514354105275014316 0ustar paolopaolo/* @(#) $Header$ (LBL) */ /* $NetBSD: ip6.h,v 1.9 2000/07/13 05:34:21 itojun Exp $ */ /* $KAME: ip6.h,v 1.9 2000/07/02 21:01:32 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ip.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP6_H_ #define _NETINET_IP6_H_ /* * Definition for internet protocol version 6. * RFC 2460 */ struct ip6_hdr { union { struct ip6_hdrctl { u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */ u_int16_t ip6_un1_plen; /* payload length */ u_int8_t ip6_un1_nxt; /* next header */ u_int8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; u_int8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ } ip6_ctlun; struct in6_addr ip6_src; /* source address */ struct in6_addr ip6_dst; /* destination address */ }; #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim #if !defined IPV6_VERSION #define IPV6_VERSION 0x60 #endif #define IPV6_VERSION_MASK 0xf0 /* in network endian */ #define IPV6_FLOWINFO_MASK ((u_int32_t)htonl(0x0fffffff)) /* flow info (28 bits) */ #define IPV6_FLOWLABEL_MASK ((u_int32_t)htonl(0x000fffff)) /* flow label (20 bits) */ #if 1 /* ECN bits proposed by Sally Floyd */ #define IP6TOS_CE 0x01 /* congestion experienced */ #define IP6TOS_ECT 0x02 /* ECN-capable transport */ #endif /* * Extension Headers */ struct ip6_ext { u_char ip6e_nxt; u_char ip6e_len; }; /* Hop-by-Hop options header */ /* XXX should we pad it to force alignment on an 8-byte boundary? */ struct ip6_hbh { u_int8_t ip6h_nxt; /* next header */ u_int8_t ip6h_len; /* length in units of 8 octets */ /* followed by options */ }; /* Destination options header */ /* XXX should we pad it to force alignment on an 8-byte boundary? */ struct ip6_dest { u_int8_t ip6d_nxt; /* next header */ u_int8_t ip6d_len; /* length in units of 8 octets */ /* followed by options */ }; /* Option types and related macros */ #define IP6OPT_PAD1 0x00 /* 00 0 00000 */ #define IP6OPT_PADN 0x01 /* 00 0 00001 */ #define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ #define IP6OPT_JUMBO_LEN 6 #define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ #define IP6OPT_RTALERT_LEN 4 #define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ #define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ #define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ #define IP6OPT_MINLEN 2 #define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */ #define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */ #define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */ #define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ #define IP6OPT_EID 0x8a /* 10 0 01010 */ #define IP6OPT_TYPE(o) ((o) & 0xC0) #define IP6OPT_TYPE_SKIP 0x00 #define IP6OPT_TYPE_DISCARD 0x40 #define IP6OPT_TYPE_FORCEICMP 0x80 #define IP6OPT_TYPE_ICMP 0xC0 #define IP6OPT_MUTABLE 0x20 /* Routing header */ struct ip6_rthdr { u_int8_t ip6r_nxt; /* next header */ u_int8_t ip6r_len; /* length in units of 8 octets */ u_int8_t ip6r_type; /* routing type */ u_int8_t ip6r_segleft; /* segments left */ /* followed by routing type specific data */ }; /* Type 0 Routing header */ struct ip6_rthdr0 { u_int8_t ip6r0_nxt; /* next header */ u_int8_t ip6r0_len; /* length in units of 8 octets */ u_int8_t ip6r0_type; /* always zero */ u_int8_t ip6r0_segleft; /* segments left */ u_int8_t ip6r0_reserved; /* reserved field */ u_int8_t ip6r0_slmap[3]; /* strict/loose bit map */ struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */ }; /* Fragment header */ struct ip6_frag { u_int8_t ip6f_nxt; /* next header */ u_int8_t ip6f_reserved; /* reserved field */ u_int16_t ip6f_offlg; /* offset, reserved, and flag */ u_int32_t ip6f_ident; /* identification */ }; #define IP6F_OFF_MASK 0xfff8 /* mask out offset from ip6f_offlg */ #define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ #define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ #endif /* not _NETINET_IP6_H_ */ pmacct-1.7.8/configure0000755000175000017500000267624314354105416013742 0ustar paolopaolo#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for pmacct 1.7.8-git. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="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 " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and paolo@pmacct.net $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pmacct' PACKAGE_TARNAME='pmacct' PACKAGE_VERSION='1.7.8-git' PACKAGE_STRING='pmacct 1.7.8-git' PACKAGE_BUGREPORT='paolo@pmacct.net' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_default_prefix=/usr/local ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS USING_ST_BINS_FALSE USING_ST_BINS_TRUE USING_BMP_BINS_FALSE USING_BMP_BINS_TRUE USING_BGP_BINS_FALSE USING_BGP_BINS_TRUE USING_TRAFFIC_BINS_FALSE USING_TRAFFIC_BINS_TRUE WITH_DLOPEN_FALSE WITH_DLOPEN_TRUE WITH_NFLOG_FALSE WITH_NFLOG_TRUE WITH_EBPF_FALSE WITH_EBPF_TRUE WITH_UNYTE_UDP_NOTIF_FALSE WITH_UNYTE_UDP_NOTIF_TRUE WITH_NDPI_FALSE WITH_NDPI_TRUE WITH_SERDES_FALSE WITH_SERDES_TRUE WITH_AVRO_FALSE WITH_AVRO_TRUE WITH_JANSSON_FALSE WITH_JANSSON_TRUE USING_SQL_FALSE USING_SQL_TRUE WITH_GNUTLS_FALSE WITH_GNUTLS_TRUE WITH_REDIS_FALSE WITH_REDIS_TRUE WITH_KAFKA_FALSE WITH_KAFKA_TRUE WITH_ZMQ_FALSE WITH_ZMQ_TRUE WITH_RABBITMQ_FALSE WITH_RABBITMQ_TRUE WITH_SQLITE3_FALSE WITH_SQLITE3_TRUE WITH_MONGODB_FALSE WITH_MONGODB_TRUE WITH_PGSQL_FALSE WITH_PGSQL_TRUE WITH_MYSQL_FALSE WITH_MYSQL_TRUE PMACCT_CFLAGS CXXCPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX configure_silent_rules_val WITH_EXTERNAL_DEPS_FALSE WITH_EXTERNAL_DEPS_TRUE NFLOG_LIBS NFLOG_CFLAGS EBPF_LIBS EBPF_CFLAGS UNYTE_UDP_NOTIF_LIBS UNYTE_UDP_NOTIF_CFLAGS NDPI_LIBS NDPI_CFLAGS SERDES_LIBS SERDES_CFLAGS AVRO_LIBS AVRO_CFLAGS JANSSON_LIBS JANSSON_CFLAGS GEOIPV2_LIBS GEOIPV2_CFLAGS GEOIP_LIBS GEOIP_CFLAGS GNUTLS_LIBS GNUTLS_CFLAGS REDIS_LIBS REDIS_CFLAGS KAFKA_LIBS KAFKA_CFLAGS ZMQ_LIBS ZMQ_CFLAGS RABBITMQ_LIBS RABBITMQ_CFLAGS SQLITE3_LIBS SQLITE3_CFLAGS MONGODB_LIBS MONGODB_CFLAGS PGSQL_LIBS PGSQL_CFLAGS MYSQL_LIBS MYSQL_CFLAGS MYSQL_VERSION MYSQL_CONFIG PCAP_CONFIG MAKE PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG PMACCT_VERSION CPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_shared enable_static with_pic enable_fast_install with_aix_soname enable_dependency_tracking with_gnu_ld with_sysroot enable_libtool_lock enable_so enable_l2 with_pcap_includes with_pcap_libs enable_mysql enable_pgsql enable_mongodb enable_sqlite3 enable_rabbitmq enable_zmq enable_kafka enable_redis enable_gnutls enable_geoip enable_geoipv2 enable_jansson enable_avro enable_serdes with_ndpi_static_lib enable_ndpi enable_unyte_udp_notif enable_ebpf enable_nflog enable_traffic_bins enable_bgp_bins enable_bmp_bins enable_st_bins with_external_deps enable_debug ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PGSQL_CFLAGS PGSQL_LIBS MONGODB_CFLAGS MONGODB_LIBS SQLITE3_CFLAGS SQLITE3_LIBS RABBITMQ_CFLAGS RABBITMQ_LIBS ZMQ_CFLAGS ZMQ_LIBS KAFKA_CFLAGS KAFKA_LIBS REDIS_CFLAGS REDIS_LIBS GNUTLS_CFLAGS GNUTLS_LIBS GEOIP_CFLAGS GEOIP_LIBS GEOIPV2_CFLAGS GEOIPV2_LIBS JANSSON_CFLAGS JANSSON_LIBS AVRO_CFLAGS AVRO_LIBS NDPI_CFLAGS NDPI_LIBS UNYTE_UDP_NOTIF_CFLAGS UNYTE_UDP_NOTIF_LIBS NFLOG_CFLAGS NFLOG_LIBS CXX CXXFLAGS CCC CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures pmacct 1.7.8-git to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/pmacct] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of pmacct 1.7.8-git:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-libtool-lock avoid locking (might break parallel builds) --disable-so Disable linking against shared objects (default: no) --enable-l2 Enable Layer-2 features and support (default: yes) --enable-mysql Enable MySQL support (default: no) --enable-pgsql Enable PostgreSQL support (default: no) --enable-mongodb Enable MongoDB support (default: no) --enable-sqlite3 Enable SQLite3 support (default: no) --enable-rabbitmq Enable RabbitMQ/AMQP support (default: no) --enable-zmq Enable ZeroMQ support (default: no) --enable-kafka Enable Kafka support (default: no) --enable-redis Enable Redis support (default: no) --enable-gnutls Enable GnuTLS support (default: no) --enable-geoip Enable GeoIP support (default: no) --enable-geoipv2 Enable GeoIPv2 (libmaxminddb) support (default: no) --enable-jansson Enable Jansson support (default: no) --enable-avro Enable Apache Avro support (default: no) --enable-serdes Enable Confluent schema-registry support (default: no) --enable-ndpi Enable nDPI support (default: no) --enable-unyte-udp-notif Enable Unyte UDP Notif support (default: no) --enable-ebpf Enable eBPF support (default: no) --enable-nflog Enable NFLOG support (default: no) --enable-traffic-bins Link IPv4/IPv6 traffic accounting binaries (default: yes) --enable-bgp-bins Link BGP daemon binaries (default: yes) --enable-bmp-bins Link BMP daemon binaries (default: yes) --enable-st-bins Link Streaming Telemetry daemon binaries (default: yes) --enable-debug Enable debugging compiler options (default: no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-pcap-includes=DIR Search the specified directory for header files --with-pcap-libs=DIR Search the specified directory for pcap library --with-ndpi-static-lib=DIR Search the specified directory for nDPI static library --without-external-deps Do not build external dependencies (git submodules), specially useful for package maintainers [default=with] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path PGSQL_CFLAGS C compiler flags for PGSQL, overriding pkg-config PGSQL_LIBS linker flags for PGSQL, overriding pkg-config MONGODB_CFLAGS C compiler flags for MONGODB, overriding pkg-config MONGODB_LIBS linker flags for MONGODB, overriding pkg-config SQLITE3_CFLAGS C compiler flags for SQLITE3, overriding pkg-config SQLITE3_LIBS linker flags for SQLITE3, overriding pkg-config RABBITMQ_CFLAGS C compiler flags for RABBITMQ, overriding pkg-config RABBITMQ_LIBS linker flags for RABBITMQ, overriding pkg-config ZMQ_CFLAGS C compiler flags for ZMQ, overriding pkg-config ZMQ_LIBS linker flags for ZMQ, overriding pkg-config KAFKA_CFLAGS C compiler flags for KAFKA, overriding pkg-config KAFKA_LIBS linker flags for KAFKA, overriding pkg-config REDIS_CFLAGS C compiler flags for REDIS, overriding pkg-config REDIS_LIBS linker flags for REDIS, overriding pkg-config GNUTLS_CFLAGS C compiler flags for GNUTLS, overriding pkg-config GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config GEOIP_CFLAGS C compiler flags for GEOIP, overriding pkg-config GEOIP_LIBS linker flags for GEOIP, overriding pkg-config GEOIPV2_CFLAGS C compiler flags for GEOIPV2, overriding pkg-config GEOIPV2_LIBS linker flags for GEOIPV2, overriding pkg-config JANSSON_CFLAGS C compiler flags for JANSSON, overriding pkg-config JANSSON_LIBS linker flags for JANSSON, overriding pkg-config AVRO_CFLAGS C compiler flags for AVRO, overriding pkg-config AVRO_LIBS linker flags for AVRO, overriding pkg-config SERDES_CFLAGS C compiler flags for SERDES, overriding pkg-config SERDES_LIBS linker flags for SEREDES, overriding pkg-config NFLOG_CFLAGS C compiler flags for NFLOG, overriding pkg-config NFLOG_LIBS linker flags for NFLOG, overriding pkg-config NDPI_CFLAGS C compiler flags for dynamic nDPI, overriding pkg-config NDPI_LIBS linker flags for dynamic nDPI, overriding pkg-config UNYTE_UDP_NOTIF_CFLAGS C compiler flags for dynamic Unyte UDP Notif, overriding pkg-config UNYTE_UDP_NOTIF_LIBS linker flags for dynamic Unyte UDP Notif, overriding pkg-config EBPF_CFLAGS C compiler flags for dynamic libbpf, overriding pkg-config EBPF_LIBS linker flags for dynamic libbpf, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF pmacct configure 1.7.8-git generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------- ## ## Report this to paolo@pmacct.net ## ## ------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by pmacct $as_me 1.7.8-git, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` 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 || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='pmacct' VERSION='1.7.8-git' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 $as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cr} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* 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 #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cr libconftest.a conftest.o" >&5 $AR cr libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[912]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*|11.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' PMACCT_VERSION=`cat $srcdir/VERSION` COMPILE_ARGS="${ac_configure_args}" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig export PKG_CONFIG_PATH if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking OS" >&5 $as_echo_n "checking OS... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $host_os" >&5 $as_echo "$host_os" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking hardware" >&5 $as_echo_n "checking hardware... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $host_cpu" >&5 $as_echo "$host_cpu" >&6; } if test "x$ac_cv_c_compiler_gnu" = xyes ; then CFLAGS="-O2 ${CFLAGS}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to disable linking against shared objects" >&5 $as_echo_n "checking whether to disable linking against shared objects... " >&6; } # Check whether --enable-so was given. if test "${enable_so+set}" = set; then : enableval=$enable_so; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : USING_DLOPEN="yes" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : USING_DLOPEN="yes" LIBS="${LIBS} -ldl" fi if test x"$USING_DLOPEN" != x"yes"; then as_fn_error $? "Unable to find dlopen(). Try with --disable-so" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test "x$ac_cv_c_compiler_gnu" = xyes ; then LDFLAGS="-static ${LDFLAGS}" fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : USING_DLOPEN="yes" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : USING_DLOPEN="yes" LIBS="${LIBS} -ldl" fi if test x"$USING_DLOPEN" != x"yes"; then as_fn_error $? "Unable to find dlopen(). Try with --disable-so" "$LINENO" 5 fi fi case "$host_os" in Sun*) $as_echo "#define SOLARIS 1" >>confdefs.h LIBS="-lresolv -lsocket -lnsl ${LIBS}" ;; *BSD) $as_echo "#define BSD 1" >>confdefs.h ;; linux*) $as_echo "#define LINUX 1" >>confdefs.h ;; esac # Extract the first word of "gmake", so it can be a program name with args. set dummy gmake; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MAKE"; then ac_cv_prog_MAKE="$MAKE" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKE="gmake" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MAKE=$ac_cv_prog_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$MAKE" = x""; then # Extract the first word of "make", so it can be a program name with args. set dummy make; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MAKE"; then ac_cv_prog_MAKE="$MAKE" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKE="make" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MAKE=$ac_cv_prog_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __progname" >&5 $as_echo_n "checking for __progname... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern char *__progname; int main () { __progname = "test"; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define PROGNAME 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_cv_endianess="unknown" if test x"$ac_cv_endianess" = x"unknown"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking endianess" >&5 $as_echo_n "checking endianess... " >&6; } if test "$cross_compiling" = yes; then : ac_cv_endianess="little" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { union { long l; char c[sizeof (long)]; } u; u.l = 1; exit (u.c[sizeof (long) - 1] == 1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_endianess="little" else ac_cv_endianess="big" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_endianess" >&5 $as_echo "$ac_cv_endianess" >&6; } fi if test x"$ac_cv_endianess" = x"big"; then $as_echo "#define IM_BIG_ENDIAN 1" >>confdefs.h fi if test x"$ac_cv_endianess" = x"little"; then $as_echo "#define IM_LITTLE_ENDIAN 1" >>confdefs.h fi ac_cv_unaligned="unknown" case "$host_cpu" in alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_unaligned="fail" { $as_echo "$as_me:${as_lineno-$LINENO}: checking unaligned accesses" >&5 $as_echo_n "checking unaligned accesses... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_unaligned" >&5 $as_echo "$ac_cv_unaligned" >&6; } ;; esac if test x"$ac_cv_unaligned" = x"unknown"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking unaligned accesses" >&5 $as_echo_n "checking unaligned accesses... " >&6; } cat > conftest.c << EOF #include #include #include #include #include unsigned char a[5] = { 1, 2, 3, 4, 5 }; int main () { unsigned int i; pid_t pid; int status; /* avoid "core dumped" message */ pid = fork(); if (pid < 0) exit(2); if (pid > 0) { /* parent */ pid = waitpid(pid, &status, 0); if (pid < 0) exit(3); exit(!WIFEXITED(status)); } /* child */ i = *(unsigned int *)&a[1]; printf("%d\n", i); exit(0); } EOF ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ conftest.c $LIBS >/dev/null 2>&1 if test ! -x conftest ; then ac_cv_unaligned="fail" else ./conftest >conftest.out if test ! -s conftest.out ; then ac_cv_unaligned="fail" else ac_cv_unaligned="ok" fi fi rm -f conftest* core core.conftest { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_unaligned" >&5 $as_echo "$ac_cv_unaligned" >&6; } fi if test x"$ac_cv_unaligned" = x"fail"; then $as_echo "#define NEED_ALIGN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable L2 features" >&5 $as_echo_n "checking whether to enable L2 features... " >&6; } # Check whether --enable-l2 was given. if test "${enable_l2+set}" = set; then : enableval=$enable_l2; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_L2 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_L2 1" >>confdefs.h COMPILE_ARGS="${COMPILE_ARGS} '--enable-l2'" fi for ac_func in inet_pton do : ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" if test "x$ac_cv_func_inet_pton" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INET_PTON 1 _ACEOF fi done if test x"$ac_cv_func_inet_pton" = x"no"; then as_fn_error $? "ERROR: missing inet_pton()" "$LINENO" 5 fi for ac_func in inet_ntop do : ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" if test "x$ac_cv_func_inet_ntop" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INET_NTOP 1 _ACEOF fi done if test x"$ac_cv_func_inet_ntop" = x"no"; then as_fn_error $? "ERROR: missing inet_ntop()" "$LINENO" 5 fi # Check whether --with-pcap-includes was given. if test "${with_pcap_includes+set}" = set; then : withval=$with_pcap_includes; absdir=`cd $withval 2>/dev/null && pwd` if test x$absdir != x ; then withval=$absdir fi INCLUDES="${INCLUDES} -I$withval" PCAPINCLS=$withval PCAPINCLUDESFOUND=1 fi if test x"$PCAPINCLS" != x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking your own pcap includes" >&5 $as_echo_n "checking your own pcap includes... " >&6; } if test -r $PCAPINCLS/pcap.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } $as_echo "#define HAVE_PCAP_H 1" >>confdefs.h PCAPINCLUDESFOUND=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "ERROR: missing pcap.h in $PCAPINCLS" "$LINENO" 5 fi fi # Extract the first word of "pcap-config", so it can be a program name with args. set dummy pcap-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PCAP_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PCAP_CONFIG"; then ac_cv_prog_PCAP_CONFIG="$PCAP_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PCAP_CONFIG="pcap-config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_PCAP_CONFIG" && ac_cv_prog_PCAP_CONFIG="no" fi fi PCAP_CONFIG=$ac_cv_prog_PCAP_CONFIG if test -n "$PCAP_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCAP_CONFIG" >&5 $as_echo "$PCAP_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$PCAPINCLUDESFOUND" = x""; then if test ${PCAP_CONFIG} = "pcap-config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking using pcap-config for pcap.h" >&5 $as_echo_n "checking using pcap-config for pcap.h... " >&6; } PCAP_CONFIG_INCLUDES=`${PCAP_CONFIG} --cflags` INCLUDES="${INCLUDES} ${PCAP_CONFIG_INCLUDES}" $as_echo "#define HAVE_PCAP_PCAP_H 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${PCAP_CONFIG_INCLUDES}" >&5 $as_echo "${PCAP_CONFIG_INCLUDES}" >&6; } PCAPINCLUDESFOUND=1 fi fi if test x"$PCAPINCLUDESFOUND" = x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for pcap.h" >&5 $as_echo_n "checking default locations for pcap.h... " >&6; } if test -r /usr/include/pcap.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/include" >&5 $as_echo "found in /usr/include" >&6; } PCAPINCLUDESFOUND=1 $as_echo "#define HAVE_PCAP_H 1" >>confdefs.h elif test -r /usr/include/pcap/pcap.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/include" >&5 $as_echo "found in /usr/include" >&6; } PCAPINCLUDESFOUND=1 $as_echo "#define HAVE_PCAP_PCAP_H 1" >>confdefs.h elif test -r /usr/local/include/pcap.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/include" >&5 $as_echo "found in /usr/local/include" >&6; } INCLUDES="${INCLUDES} -I/usr/local/include" PCAPINCLUDESFOUND=1 $as_echo "#define HAVE_PCAP_H 1" >>confdefs.h elif test -r /usr/local/include/pcap/pcap.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/include" >&5 $as_echo "found in /usr/local/include" >&6; } INCLUDES="${INCLUDES} -I/usr/local/include" PCAPINCLUDESFOUND=1 $as_echo "#define HAVE_PCAP_PCAP_H 1" >>confdefs.h fi if test x"$PCAPINCLUDESFOUND" = x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } as_fn_error $? "ERROR: missing pcap.h" "$LINENO" 5 fi fi # Check whether --with-pcap-libs was given. if test "${with_pcap_libs+set}" = set; then : withval=$with_pcap_libs; absdir=`cd $withval 2>/dev/null && pwd` if test x$absdir != x ; then withval=$absdir fi LIBS="${LIBS} -L$withval" PCAPLIB=$withval PCAPLIBFOUND=1 fi if test x"$PCAPLIB" != x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking your own pcap libraries" >&5 $as_echo_n "checking your own pcap libraries... " >&6; } if test -r $PCAPLIB/libpcap.a -o -r $PCAPLIB/libpcap.so; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } PCAP_LIB_FOUND=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PF_RING library" >&5 $as_echo_n "checking for PF_RING library... " >&6; } if test -r $PCAPLIB/libpfring.a -o -r $PCAPLIB/libpfring.so; then LIBS="${LIBS} -lpfring -lpcap" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PFRING_LIB_FOUND=1 $as_echo "#define PFRING_LIB_FOUND 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "ERROR: unable to find pcap library in $PCAPLIB" "$LINENO" 5 fi fi if test x"$PCAPLIBFOUND" = x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for libpcap" >&5 $as_echo_n "checking default locations for libpcap... " >&6; } if test -r /usr/local/lib/libpcap.a -o -r /usr/local/lib/libpcap.so; then LIBS="${LIBS} -L/usr/local/lib" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/lib" >&5 $as_echo "found in /usr/local/lib" >&6; } PCAPLIBFOUND=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PF_RING library" >&5 $as_echo_n "checking for PF_RING library... " >&6; } if test -r /usr/local/lib/libpfring.a -o -r /usr/local/lib/libpfring.so; then LIBS="${LIBS} -lpfring -lpcap" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PFRING_LIB_FOUND=1 $as_echo "#define PFRING_LIB_FOUND 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$PCAPLIBFOUND" = x""; then if test ${PCAP_CONFIG} = "pcap-config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking using pcap-config for libpcap" >&5 $as_echo_n "checking using pcap-config for libpcap... " >&6; } PCAP_CONFIG_LIBS=`${PCAP_CONFIG} --libs` INCLUDES="${INCLUDES} ${PCAP_CONFIG_LIBS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${PCAP_CONFIG_LIBS}" >&5 $as_echo "${PCAP_CONFIG_LIBS}" >&6; } PCAPLIBFOUND=1 fi fi if test x"$PFRING_LIB_FOUND" = x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_dispatch in -lpcap" >&5 $as_echo_n "checking for pcap_dispatch in -lpcap... " >&6; } if ${ac_cv_lib_pcap_pcap_dispatch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcap_dispatch (); int main () { return pcap_dispatch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_pcap_dispatch=yes else ac_cv_lib_pcap_pcap_dispatch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_dispatch" >&5 $as_echo "$ac_cv_lib_pcap_pcap_dispatch" >&6; } if test "x$ac_cv_lib_pcap_pcap_dispatch" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCAP 1 _ACEOF LIBS="-lpcap $LIBS" else as_fn_error $? " ERROR: missing pcap library. Refer to: http://www.tcpdump.org/ " "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_set_protocol in -lpcap" >&5 $as_echo_n "checking for pcap_set_protocol in -lpcap... " >&6; } if ${ac_cv_lib_pcap_pcap_set_protocol+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcap_set_protocol (); int main () { return pcap_set_protocol (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_pcap_set_protocol=yes else ac_cv_lib_pcap_pcap_set_protocol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_set_protocol" >&5 $as_echo "$ac_cv_lib_pcap_pcap_set_protocol" >&6; } if test "x$ac_cv_lib_pcap_pcap_set_protocol" = xyes; then : $as_echo "#define PCAP_SET_PROTOCOL 1" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for numa_bind in -lnuma" >&5 $as_echo_n "checking for numa_bind in -lnuma... " >&6; } if ${ac_cv_lib_numa_numa_bind+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnuma $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char numa_bind (); int main () { return numa_bind (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_numa_numa_bind=yes else ac_cv_lib_numa_numa_bind=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_numa_numa_bind" >&5 $as_echo "$ac_cv_lib_numa_numa_bind" >&6; } if test "x$ac_cv_lib_numa_numa_bind" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNUMA 1 _ACEOF LIBS="-lnuma $LIBS" else as_fn_error $? " ERROR: missing libnuma. Requirement for building PF_RING. " "$LINENO" 5 fi #AC_CHECK_LIB([rt], [clock_gettime], [], [AC_MSG_ERROR([ # ERROR: missing librt devel. Requirement for building PF_RING. #])]) LIBS="${LIBS} -lrt -lnuma" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_setdirection in -lpcap" >&5 $as_echo_n "checking for pcap_setdirection in -lpcap... " >&6; } if ${ac_cv_lib_pcap_pcap_setdirection+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcap_setdirection (); int main () { return pcap_setdirection (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_pcap_setdirection=yes else ac_cv_lib_pcap_pcap_setdirection=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_setdirection" >&5 $as_echo "$ac_cv_lib_pcap_pcap_setdirection" >&6; } if test "x$ac_cv_lib_pcap_pcap_setdirection" = xyes; then : $as_echo "#define PCAP_SET_DIRECTION 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MySQL support" >&5 $as_echo_n "checking whether to enable MySQL support... " >&6; } # Check whether --enable-mysql was given. if test "${enable_mysql+set}" = set; then : enableval=$enable_mysql; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # Extract the first word of "mysql_config", so it can be a program name with args. set dummy mysql_config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MYSQL_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MYSQL_CONFIG"; then ac_cv_prog_MYSQL_CONFIG="$MYSQL_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MYSQL_CONFIG="mysql_config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_MYSQL_CONFIG" && ac_cv_prog_MYSQL_CONFIG="no" fi fi MYSQL_CONFIG=$ac_cv_prog_MYSQL_CONFIG if test -n "$MYSQL_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5 $as_echo "$MYSQL_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x${MYSQL_CONFIG}" = "xno"; then as_fn_error $? "ERROR: missing mysql_config program" "$LINENO" 5 fi MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags` MYSQL_LIBS=`$MYSQL_CONFIG --libs` if test "$MYSQL_CONFIG" != "no"; then MYSQL_VERSION=`$MYSQL_CONFIG --version` found_mysql="yes" else found_mysql="no" fi mysql_version_req=5.6.3 if test "$found_mysql" = "yes" -a -n "$mysql_version_req"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MySQL version is >= $mysql_version_req" >&5 $as_echo_n "checking if MySQL version is >= $mysql_version_req... " >&6; } mysql_version_req_major=`expr $mysql_version_req : '\([0-9]*\)'` mysql_version_req_minor=`expr $mysql_version_req : '[0-9]*\.\([0-9]*\)'` mysql_version_req_micro=`expr $mysql_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` if test "x$mysql_version_req_micro" = "x"; then mysql_version_req_micro="0" fi mysql_version_req_number=`expr $mysql_version_req_major \* 1000000 \ \+ $mysql_version_req_minor \* 1000 \ \+ $mysql_version_req_micro` mysql_version_major=`expr $MYSQL_VERSION : '\([0-9]*\)'` mysql_version_minor=`expr $MYSQL_VERSION : '[0-9]*\.\([0-9]*\)'` mysql_version_micro=`expr $MYSQL_VERSION : '[0-9]*\.[0-9]*\.\([0-9]*\)'` if test "x$mysql_version_micro" = "x"; then mysql_version_micro="0" fi mysql_version_number=`expr $mysql_version_major \* 1000000 \ \+ $mysql_version_minor \* 1000 \ \+ $mysql_version_micro` mysql_version_check=`expr $mysql_version_number \>\= $mysql_version_req_number` if test "$mysql_version_check" = "1"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi PLUGINS="${PLUGINS} mysql" USING_SQL="yes" USING_MYSQL="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $MYSQL_CFLAGS" $as_echo "#define WITH_MYSQL 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $MYSQL_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_query in -lmysqlclient" >&5 $as_echo_n "checking for mysql_query in -lmysqlclient... " >&6; } if ${ac_cv_lib_mysqlclient_mysql_query+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_query (); int main () { return mysql_query (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mysqlclient_mysql_query=yes else ac_cv_lib_mysqlclient_mysql_query=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_query" >&5 $as_echo "$ac_cv_lib_mysqlclient_mysql_query" >&6; } if test "x$ac_cv_lib_mysqlclient_mysql_query" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMYSQLCLIENT 1 _ACEOF LIBS="-lmysqlclient $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MYSQL_CFLAGS" for ac_header in mysql.h mysql/mysql.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CFLAGS="$_save_CFLAGS" case "$host_os" in linux*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for numa_bind in -lnuma" >&5 $as_echo_n "checking for numa_bind in -lnuma... " >&6; } if ${ac_cv_lib_numa_numa_bind+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnuma $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char numa_bind (); int main () { return numa_bind (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_numa_numa_bind=yes else ac_cv_lib_numa_numa_bind=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_numa_numa_bind" >&5 $as_echo "$ac_cv_lib_numa_numa_bind" >&6; } if test "x$ac_cv_lib_numa_numa_bind" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNUMA 1 _ACEOF LIBS="-lnuma $LIBS" else as_fn_error $? " ERROR: missing libnuma. Requirement for building MySQL. " "$LINENO" 5 fi ;; esac ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable PostgreSQL support" >&5 $as_echo_n "checking whether to enable PostgreSQL support... " >&6; } # Check whether --enable-pgsql was given. if test "${enable_pgsql+set}" = set; then : enableval=$enable_pgsql; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpq >= 8.4" >&5 $as_echo_n "checking for libpq >= 8.4... " >&6; } if test -n "$PGSQL_CFLAGS"; then pkg_cv_PGSQL_CFLAGS="$PGSQL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq >= 8.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpq >= 8.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PGSQL_CFLAGS=`$PKG_CONFIG --cflags "libpq >= 8.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$PGSQL_LIBS"; then pkg_cv_PGSQL_LIBS="$PGSQL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq >= 8.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpq >= 8.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PGSQL_LIBS=`$PKG_CONFIG --libs "libpq >= 8.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then PGSQL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpq >= 8.4" 2>&1` else PGSQL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpq >= 8.4" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$PGSQL_PKG_ERRORS" >&5 as_fn_error $? "Missing PQ library. Refer to: http://www.postgresql.org/download/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing PQ library. Refer to: http://www.postgresql.org/download/" "$LINENO" 5 else PGSQL_CFLAGS=$pkg_cv_PGSQL_CFLAGS PGSQL_LIBS=$pkg_cv_PGSQL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PLUGINS="${PLUGINS} pgsql" USING_SQL="yes" USING_PGSQL="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $PGSQL_CFLAGS" $as_echo "#define WITH_PGSQL 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $PGSQL_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQexec in -lpq" >&5 $as_echo_n "checking for PQexec in -lpq... " >&6; } if ${ac_cv_lib_pq_PQexec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpq $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char PQexec (); int main () { return PQexec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pq_PQexec=yes else ac_cv_lib_pq_PQexec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQexec" >&5 $as_echo "$ac_cv_lib_pq_PQexec" >&6; } if test "x$ac_cv_lib_pq_PQexec" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPQ 1 _ACEOF LIBS="-lpq $LIBS" fi for ac_func in PQlibVersion do : ac_fn_c_check_func "$LINENO" "PQlibVersion" "ac_cv_func_PQlibVersion" if test "x$ac_cv_func_PQlibVersion" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PQLIBVERSION 1 _ACEOF fi done LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PGSQL_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_libpq_fe_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MongoDB support" >&5 $as_echo_n "checking whether to enable MongoDB support... " >&6; } # Check whether --enable-mongodb was given. if test "${enable_mongodb+set}" = set; then : enableval=$enable_mongodb; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmongoc" >&5 $as_echo_n "checking for libmongoc... " >&6; } if test -n "$MONGODB_CFLAGS"; then pkg_cv_MONGODB_CFLAGS="$MONGODB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmongoc\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmongoc") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_MONGODB_CFLAGS=`$PKG_CONFIG --cflags "libmongoc" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$MONGODB_LIBS"; then pkg_cv_MONGODB_LIBS="$MONGODB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmongoc\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmongoc") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_MONGODB_LIBS=`$PKG_CONFIG --libs "libmongoc" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then MONGODB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libmongoc" 2>&1` else MONGODB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libmongoc" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$MONGODB_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for libmongoc" >&5 $as_echo_n "checking default locations for libmongoc... " >&6; } if test -r /usr/lib/libmongoc.a -o -r /usr/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/lib -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/lib" >&5 $as_echo "found in /usr/lib" >&6; } elif test -r /usr/lib64/libmongoc.a -o -r /usr/lib64/libmongoc.so; then MONGODB_LIBS="-L/usr/lib64 -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/lib64" >&5 $as_echo "found in /usr/lib64" >&6; } elif test -r /usr/local/lib/libmongoc.a -o -r /usr/local/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/local/lib -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/lib" >&5 $as_echo "found in /usr/local/lib" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } _save_LIBS="$LIBS" LIBS="$LIBS $MONGODB_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mongo_connect in -lmongoc" >&5 $as_echo_n "checking for mongo_connect in -lmongoc... " >&6; } if ${ac_cv_lib_mongoc_mongo_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmongoc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mongo_connect (); int main () { return mongo_connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mongoc_mongo_connect=yes else ac_cv_lib_mongoc_mongo_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mongoc_mongo_connect" >&5 $as_echo "$ac_cv_lib_mongoc_mongo_connect" >&6; } if test "x$ac_cv_lib_mongoc_mongo_connect" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMONGOC 1 _ACEOF LIBS="-lmongoc $LIBS" else as_fn_error $? " ERROR: missing MongoDB library (0.8 version). Refer to: https://github.com/mongodb/mongo-c-driver-legacy " "$LINENO" 5 fi LIBS="$_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for mongo.h" >&5 $as_echo_n "checking default locations for mongo.h... " >&6; } if test -r /usr/include/mongo.h; then MONGODB_CFLAGS="-I/usr/include" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/include" >&5 $as_echo "found in /usr/include" >&6; } elif test -r /usr/local/include/mongo.h; then MONGODB_CFLAGS="-I/usr/local/include" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/include" >&5 $as_echo "found in /usr/local/include" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MONGODB_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "mongo.h" "ac_cv_header_mongo_h" "$ac_includes_default" if test "x$ac_cv_header_mongo_h" = xyes; then : else as_fn_error $? "ERROR: missing MongoDB headers" "$LINENO" 5 fi CFLAGS="$_save_CFLAGS" fi elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for libmongoc" >&5 $as_echo_n "checking default locations for libmongoc... " >&6; } if test -r /usr/lib/libmongoc.a -o -r /usr/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/lib -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/lib" >&5 $as_echo "found in /usr/lib" >&6; } elif test -r /usr/lib64/libmongoc.a -o -r /usr/lib64/libmongoc.so; then MONGODB_LIBS="-L/usr/lib64 -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/lib64" >&5 $as_echo "found in /usr/lib64" >&6; } elif test -r /usr/local/lib/libmongoc.a -o -r /usr/local/lib/libmongoc.so; then MONGODB_LIBS="-L/usr/local/lib -lmongoc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/lib" >&5 $as_echo "found in /usr/local/lib" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } _save_LIBS="$LIBS" LIBS="$LIBS $MONGODB_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mongo_connect in -lmongoc" >&5 $as_echo_n "checking for mongo_connect in -lmongoc... " >&6; } if ${ac_cv_lib_mongoc_mongo_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmongoc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mongo_connect (); int main () { return mongo_connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mongoc_mongo_connect=yes else ac_cv_lib_mongoc_mongo_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mongoc_mongo_connect" >&5 $as_echo "$ac_cv_lib_mongoc_mongo_connect" >&6; } if test "x$ac_cv_lib_mongoc_mongo_connect" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMONGOC 1 _ACEOF LIBS="-lmongoc $LIBS" else as_fn_error $? " ERROR: missing MongoDB library (0.8 version). Refer to: https://github.com/mongodb/mongo-c-driver-legacy " "$LINENO" 5 fi LIBS="$_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locations for mongo.h" >&5 $as_echo_n "checking default locations for mongo.h... " >&6; } if test -r /usr/include/mongo.h; then MONGODB_CFLAGS="-I/usr/include" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/include" >&5 $as_echo "found in /usr/include" >&6; } elif test -r /usr/local/include/mongo.h; then MONGODB_CFLAGS="-I/usr/local/include" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in /usr/local/include" >&5 $as_echo "found in /usr/local/include" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MONGODB_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "mongo.h" "ac_cv_header_mongo_h" "$ac_includes_default" if test "x$ac_cv_header_mongo_h" = xyes; then : else as_fn_error $? "ERROR: missing MongoDB headers" "$LINENO" 5 fi CFLAGS="$_save_CFLAGS" fi else MONGODB_CFLAGS=$pkg_cv_MONGODB_CFLAGS MONGODB_LIBS=$pkg_cv_MONGODB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi PLUGINS="${PLUGINS} mongodb" USING_MONGODB="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $MONGODB_CFLAGS" $as_echo "#define WITH_MONGODB 1" >>confdefs.h ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable SQLite3 support" >&5 $as_echo_n "checking whether to enable SQLite3 support... " >&6; } # Check whether --enable-sqlite3 was given. if test "${enable_sqlite3+set}" = set; then : enableval=$enable_sqlite3; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3 >= 3.7.13" >&5 $as_echo_n "checking for sqlite3 >= 3.7.13... " >&6; } if test -n "$SQLITE3_CFLAGS"; then pkg_cv_SQLITE3_CFLAGS="$SQLITE3_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.13\""; } >&5 ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.13") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SQLITE3_CFLAGS=`$PKG_CONFIG --cflags "sqlite3 >= 3.7.13" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SQLITE3_LIBS"; then pkg_cv_SQLITE3_LIBS="$SQLITE3_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.13\""; } >&5 ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.13") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SQLITE3_LIBS=`$PKG_CONFIG --libs "sqlite3 >= 3.7.13" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SQLITE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3 >= 3.7.13" 2>&1` else SQLITE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3 >= 3.7.13" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SQLITE3_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (sqlite3 >= 3.7.13) were not met: $SQLITE3_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables SQLITE3_CFLAGS and SQLITE3_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables SQLITE3_CFLAGS and SQLITE3_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else SQLITE3_CFLAGS=$pkg_cv_SQLITE3_CFLAGS SQLITE3_LIBS=$pkg_cv_SQLITE3_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PLUGINS="${PLUGINS} sqlite3" USING_SQL="yes" USING_SQLITE3="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $SQLITE3_CFLAGS" $as_echo "#define WITH_SQLITE3 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $SQLITE3_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_exec in -lsqlite3" >&5 $as_echo_n "checking for sqlite3_exec in -lsqlite3... " >&6; } if ${ac_cv_lib_sqlite3_sqlite3_exec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsqlite3 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqlite3_exec (); int main () { return sqlite3_exec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sqlite3_sqlite3_exec=yes else ac_cv_lib_sqlite3_sqlite3_exec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_exec" >&5 $as_echo "$ac_cv_lib_sqlite3_sqlite3_exec" >&6; } if test "x$ac_cv_lib_sqlite3_sqlite3_exec" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSQLITE3 1 _ACEOF LIBS="-lsqlite3 $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SQLITE3_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable RabbitMQ/AMQP support" >&5 $as_echo_n "checking whether to enable RabbitMQ/AMQP support... " >&6; } # Check whether --enable-rabbitmq was given. if test "${enable_rabbitmq+set}" = set; then : enableval=$enable_rabbitmq; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for librabbitmq >= 0.8.0" >&5 $as_echo_n "checking for librabbitmq >= 0.8.0... " >&6; } if test -n "$RABBITMQ_CFLAGS"; then pkg_cv_RABBITMQ_CFLAGS="$RABBITMQ_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librabbitmq >= 0.8.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "librabbitmq >= 0.8.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RABBITMQ_CFLAGS=`$PKG_CONFIG --cflags "librabbitmq >= 0.8.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$RABBITMQ_LIBS"; then pkg_cv_RABBITMQ_LIBS="$RABBITMQ_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librabbitmq >= 0.8.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "librabbitmq >= 0.8.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RABBITMQ_LIBS=`$PKG_CONFIG --libs "librabbitmq >= 0.8.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then RABBITMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "librabbitmq >= 0.8.0" 2>&1` else RABBITMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "librabbitmq >= 0.8.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$RABBITMQ_PKG_ERRORS" >&5 as_fn_error $? "Missing RabbitMQ C API. Refer to: https://github.com/alanxz/rabbitmq-c/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing RabbitMQ C API. Refer to: https://github.com/alanxz/rabbitmq-c/" "$LINENO" 5 else RABBITMQ_CFLAGS=$pkg_cv_RABBITMQ_CFLAGS RABBITMQ_LIBS=$pkg_cv_RABBITMQ_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PLUGINS="${PLUGINS} rabbitmq" USING_RABBITMQ="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $RABBITMQ_CFLAGS" $as_echo "#define WITH_RABBITMQ 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $RABBITMQ_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for amqp_basic_publish in -lrabbitmq" >&5 $as_echo_n "checking for amqp_basic_publish in -lrabbitmq... " >&6; } if ${ac_cv_lib_rabbitmq_amqp_basic_publish+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrabbitmq $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char amqp_basic_publish (); int main () { return amqp_basic_publish (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rabbitmq_amqp_basic_publish=yes else ac_cv_lib_rabbitmq_amqp_basic_publish=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rabbitmq_amqp_basic_publish" >&5 $as_echo "$ac_cv_lib_rabbitmq_amqp_basic_publish" >&6; } if test "x$ac_cv_lib_rabbitmq_amqp_basic_publish" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRABBITMQ 1 _ACEOF LIBS="-lrabbitmq $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $RABBITMQ_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "amqp.h" "ac_cv_header_amqp_h" "$ac_includes_default" if test "x$ac_cv_header_amqp_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ZeroMQ support" >&5 $as_echo_n "checking whether to enable ZeroMQ support... " >&6; } # Check whether --enable-zmq was given. if test "${enable_zmq+set}" = set; then : enableval=$enable_zmq; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzmq >= 4.2.0" >&5 $as_echo_n "checking for libzmq >= 4.2.0... " >&6; } if test -n "$ZMQ_CFLAGS"; then pkg_cv_ZMQ_CFLAGS="$ZMQ_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzmq >= 4.2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libzmq >= 4.2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_ZMQ_CFLAGS=`$PKG_CONFIG --cflags "libzmq >= 4.2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$ZMQ_LIBS"; then pkg_cv_ZMQ_LIBS="$ZMQ_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzmq >= 4.2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libzmq >= 4.2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_ZMQ_LIBS=`$PKG_CONFIG --libs "libzmq >= 4.2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then ZMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzmq >= 4.2.0" 2>&1` else ZMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzmq >= 4.2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$ZMQ_PKG_ERRORS" >&5 as_fn_error $? "Missing ZeroMQ. Refer to: http://zeromq.org/intro:get-the-software" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing ZeroMQ. Refer to: http://zeromq.org/intro:get-the-software" "$LINENO" 5 else ZMQ_CFLAGS=$pkg_cv_ZMQ_CFLAGS ZMQ_LIBS=$pkg_cv_ZMQ_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} zmq" USING_ZMQ="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $ZMQ_CFLAGS" $as_echo "#define WITH_ZMQ 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $ZMQ_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zmq_send in -lzmq" >&5 $as_echo_n "checking for zmq_send in -lzmq... " >&6; } if ${ac_cv_lib_zmq_zmq_send+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lzmq $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char zmq_send (); int main () { return zmq_send (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_zmq_zmq_send=yes else ac_cv_lib_zmq_zmq_send=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zmq_zmq_send" >&5 $as_echo "$ac_cv_lib_zmq_zmq_send" >&6; } if test "x$ac_cv_lib_zmq_zmq_send" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZMQ 1 _ACEOF LIBS="-lzmq $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ZMQ_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "zmq.h" "ac_cv_header_zmq_h" "$ac_includes_default" if test "x$ac_cv_header_zmq_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Kafka support" >&5 $as_echo_n "checking whether to enable Kafka support... " >&6; } # Check whether --enable-kafka was given. if test "${enable_kafka+set}" = set; then : enableval=$enable_kafka; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rdkafka >= 0.9.2" >&5 $as_echo_n "checking for rdkafka >= 0.9.2... " >&6; } if test -n "$KAFKA_CFLAGS"; then pkg_cv_KAFKA_CFLAGS="$KAFKA_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_KAFKA_CFLAGS=`$PKG_CONFIG --cflags "rdkafka >= 0.9.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$KAFKA_LIBS"; then pkg_cv_KAFKA_LIBS="$KAFKA_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_KAFKA_LIBS=`$PKG_CONFIG --libs "rdkafka >= 0.9.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then KAFKA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "rdkafka >= 0.9.2" 2>&1` else KAFKA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "rdkafka >= 0.9.2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$KAFKA_PKG_ERRORS" >&5 as_fn_error $? "Missing librdkafka. Refer to: https://github.com/edenhill/librdkafka/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing librdkafka. Refer to: https://github.com/edenhill/librdkafka/" "$LINENO" 5 else KAFKA_CFLAGS=$pkg_cv_KAFKA_CFLAGS KAFKA_LIBS=$pkg_cv_KAFKA_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } PLUGINS="${PLUGINS} kafka" USING_KAFKA="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $KAFKA_CFLAGS" $as_echo "#define WITH_KAFKA 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $KAFKA_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_produce in -lrdkafka" >&5 $as_echo_n "checking for rd_kafka_produce in -lrdkafka... " >&6; } if ${ac_cv_lib_rdkafka_rd_kafka_produce+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrdkafka $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rd_kafka_produce (); int main () { return rd_kafka_produce (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rdkafka_rd_kafka_produce=yes else ac_cv_lib_rdkafka_rd_kafka_produce=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdkafka_rd_kafka_produce" >&5 $as_echo "$ac_cv_lib_rdkafka_rd_kafka_produce" >&6; } if test "x$ac_cv_lib_rdkafka_rd_kafka_produce" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRDKAFKA 1 _ACEOF LIBS="-lrdkafka $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $KAFKA_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "librdkafka/rdkafka.h" "ac_cv_header_librdkafka_rdkafka_h" "$ac_includes_default" if test "x$ac_cv_header_librdkafka_rdkafka_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Redis support" >&5 $as_echo_n "checking whether to enable Redis support... " >&6; } # Check whether --enable-redis was given. if test "${enable_redis+set}" = set; then : enableval=$enable_redis; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hiredis >= 0.13.0" >&5 $as_echo_n "checking for hiredis >= 0.13.0... " >&6; } if test -n "$REDIS_CFLAGS"; then pkg_cv_REDIS_CFLAGS="$REDIS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hiredis >= 0.13.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "hiredis >= 0.13.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_REDIS_CFLAGS=`$PKG_CONFIG --cflags "hiredis >= 0.13.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$REDIS_LIBS"; then pkg_cv_REDIS_LIBS="$REDIS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hiredis >= 0.13.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "hiredis >= 0.13.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_REDIS_LIBS=`$PKG_CONFIG --libs "hiredis >= 0.13.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then REDIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "hiredis >= 0.13.0" 2>&1` else REDIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "hiredis >= 0.13.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$REDIS_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (hiredis >= 0.13.0) were not met: $REDIS_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables REDIS_CFLAGS and REDIS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables REDIS_CFLAGS and REDIS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else REDIS_CFLAGS=$pkg_cv_REDIS_CFLAGS REDIS_LIBS=$pkg_cv_REDIS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} redis" USING_REDIS="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $REDIS_CFLAGS" $as_echo "#define WITH_REDIS 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $REDIS_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for redisConnect in -lhiredis" >&5 $as_echo_n "checking for redisConnect in -lhiredis... " >&6; } if ${ac_cv_lib_hiredis_redisConnect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lhiredis $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char redisConnect (); int main () { return redisConnect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_hiredis_redisConnect=yes else ac_cv_lib_hiredis_redisConnect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hiredis_redisConnect" >&5 $as_echo "$ac_cv_lib_hiredis_redisConnect" >&6; } if test "x$ac_cv_lib_hiredis_redisConnect" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBHIREDIS 1 _ACEOF LIBS="-lhiredis $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $REDIS_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "hiredis/hiredis.h" "ac_cv_header_hiredis_hiredis_h" "$ac_includes_default" if test "x$ac_cv_header_hiredis_hiredis_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable GnuTLS support" >&5 $as_echo_n "checking whether to enable GnuTLS support... " >&6; } # Check whether --enable-gnutls was given. if test "${enable_gnutls+set}" = set; then : enableval=$enable_gnutls; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls >= 3.6" >&5 $as_echo_n "checking for gnutls >= 3.6... " >&6; } if test -n "$GNUTLS_CFLAGS"; then pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.6\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 3.6") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 3.6" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GNUTLS_LIBS"; then pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.6\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 3.6") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 3.6" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 3.6" 2>&1` else GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 3.6" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GNUTLS_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (gnutls >= 3.6) were not met: $GNUTLS_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GNUTLS_CFLAGS and GNUTLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GNUTLS_CFLAGS and GNUTLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} gnutls" USING_GNUTLS="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GNUTLS_CFLAGS" $as_echo "#define WITH_GNUTLS 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $GNUTLS_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls_global_init in -lgnutls" >&5 $as_echo_n "checking for gnutls_global_init in -lgnutls... " >&6; } if ${ac_cv_lib_gnutls_gnutls_global_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_global_init (); int main () { return gnutls_global_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_gnutls_global_init=yes else ac_cv_lib_gnutls_gnutls_global_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_gnutls_global_init" >&5 $as_echo "$ac_cv_lib_gnutls_gnutls_global_init" >&6; } if test "x$ac_cv_lib_gnutls_gnutls_global_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGNUTLS 1 _ACEOF LIBS="-lgnutls $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $GNUTLS_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "gnutls/gnutls.h" "ac_cv_header_gnutls_gnutls_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_gnutls_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable GeoIP support" >&5 $as_echo_n "checking whether to enable GeoIP support... " >&6; } # Check whether --enable-geoip was given. if test "${enable_geoip+set}" = set; then : enableval=$enable_geoip; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for geoip >= 1.0.0" >&5 $as_echo_n "checking for geoip >= 1.0.0... " >&6; } if test -n "$GEOIP_CFLAGS"; then pkg_cv_GEOIP_CFLAGS="$GEOIP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip >= 1.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "geoip >= 1.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GEOIP_CFLAGS=`$PKG_CONFIG --cflags "geoip >= 1.0.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GEOIP_LIBS"; then pkg_cv_GEOIP_LIBS="$GEOIP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip >= 1.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "geoip >= 1.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GEOIP_LIBS=`$PKG_CONFIG --libs "geoip >= 1.0.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GEOIP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "geoip >= 1.0.0" 2>&1` else GEOIP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "geoip >= 1.0.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GEOIP_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (geoip >= 1.0.0) were not met: $GEOIP_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GEOIP_CFLAGS and GEOIP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GEOIP_CFLAGS and GEOIP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else GEOIP_CFLAGS=$pkg_cv_GEOIP_CFLAGS GEOIP_LIBS=$pkg_cv_GEOIP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} geoip" USING_MMGEOIP="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GEOIP_CFLAGS" $as_echo "#define WITH_GEOIP 1" >>confdefs.h fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable GeoIPv2 (libmaxminddb) support" >&5 $as_echo_n "checking whether to enable GeoIPv2 (libmaxminddb) support... " >&6; } # Check whether --enable-geoipv2 was given. if test "${enable_geoipv2+set}" = set; then : enableval=$enable_geoipv2; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmaxminddb >= 1.2" >&5 $as_echo_n "checking for libmaxminddb >= 1.2... " >&6; } if test -n "$GEOIPV2_CFLAGS"; then pkg_cv_GEOIPV2_CFLAGS="$GEOIPV2_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb >= 1.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmaxminddb >= 1.2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GEOIPV2_CFLAGS=`$PKG_CONFIG --cflags "libmaxminddb >= 1.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GEOIPV2_LIBS"; then pkg_cv_GEOIPV2_LIBS="$GEOIPV2_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb >= 1.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmaxminddb >= 1.2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GEOIPV2_LIBS=`$PKG_CONFIG --libs "libmaxminddb >= 1.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GEOIPV2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libmaxminddb >= 1.2" 2>&1` else GEOIPV2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libmaxminddb >= 1.2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GEOIPV2_PKG_ERRORS" >&5 as_fn_error $? "Missing Maxmind libmaxminddb C library. Refer to: http://www.maxmind.com/download/geoip/api/c/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing Maxmind libmaxminddb C library. Refer to: http://www.maxmind.com/download/geoip/api/c/" "$LINENO" 5 else GEOIPV2_CFLAGS=$pkg_cv_GEOIPV2_CFLAGS GEOIPV2_LIBS=$pkg_cv_GEOIPV2_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} geoipv2" USING_MMGEOIPV2="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $GEOIPV2_CFLAGS" $as_echo "#define WITH_GEOIPV2 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $GEOIPV2_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB_open in -lmaxminddb" >&5 $as_echo_n "checking for MMDB_open in -lmaxminddb... " >&6; } if ${ac_cv_lib_maxminddb_MMDB_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmaxminddb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char MMDB_open (); int main () { return MMDB_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_maxminddb_MMDB_open=yes else ac_cv_lib_maxminddb_MMDB_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_maxminddb_MMDB_open" >&5 $as_echo "$ac_cv_lib_maxminddb_MMDB_open" >&6; } if test "x$ac_cv_lib_maxminddb_MMDB_open" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMAXMINDDB 1 _ACEOF LIBS="-lmaxminddb $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $GEOIPV2_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default" if test "x$ac_cv_header_maxminddb_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Jansson support" >&5 $as_echo_n "checking whether to enable Jansson support... " >&6; } # Check whether --enable-jansson was given. if test "${enable_jansson+set}" = set; then : enableval=$enable_jansson; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jansson >= 2.5" >&5 $as_echo_n "checking for jansson >= 2.5... " >&6; } if test -n "$JANSSON_CFLAGS"; then pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_JANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson >= 2.5" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$JANSSON_LIBS"; then pkg_cv_JANSSON_LIBS="$JANSSON_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_JANSSON_LIBS=`$PKG_CONFIG --libs "jansson >= 2.5" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then JANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "jansson >= 2.5" 2>&1` else JANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "jansson >= 2.5" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$JANSSON_PKG_ERRORS" >&5 as_fn_error $? "Missing libjansson. Refer to: http://www.digip.org/jansson/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing libjansson. Refer to: http://www.digip.org/jansson/" "$LINENO" 5 else JANSSON_CFLAGS=$pkg_cv_JANSSON_CFLAGS JANSSON_LIBS=$pkg_cv_JANSSON_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} jansson" USING_JANSSON="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $JANSSON_CFLAGS" $as_echo "#define WITH_JANSSON 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $JANSSON_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object in -ljansson" >&5 $as_echo_n "checking for json_object in -ljansson... " >&6; } if ${ac_cv_lib_jansson_json_object+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljansson $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char json_object (); int main () { return json_object (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jansson_json_object=yes else ac_cv_lib_jansson_json_object=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jansson_json_object" >&5 $as_echo "$ac_cv_lib_jansson_json_object" >&6; } if test "x$ac_cv_lib_jansson_json_object" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBJANSSON 1 _ACEOF LIBS="-ljansson $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $JANSSON_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "jansson.h" "ac_cv_header_jansson_h" "$ac_includes_default" if test "x$ac_cv_header_jansson_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Avro support" >&5 $as_echo_n "checking whether to enable Avro support... " >&6; } # Check whether --enable-avro was given. if test "${enable_avro+set}" = set; then : enableval=$enable_avro; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avro-c >= 1.8" >&5 $as_echo_n "checking for avro-c >= 1.8... " >&6; } if test -n "$AVRO_CFLAGS"; then pkg_cv_AVRO_CFLAGS="$AVRO_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avro-c >= 1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "avro-c >= 1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVRO_CFLAGS=`$PKG_CONFIG --cflags "avro-c >= 1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$AVRO_LIBS"; then pkg_cv_AVRO_LIBS="$AVRO_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avro-c >= 1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "avro-c >= 1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVRO_LIBS=`$PKG_CONFIG --libs "avro-c >= 1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVRO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "avro-c >= 1.8" 2>&1` else AVRO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "avro-c >= 1.8" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$AVRO_PKG_ERRORS" >&5 as_fn_error $? "Missing Apache Avro C library. Refer to: http://www.apache.org/dyn/closer.cgi/avro/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing Apache Avro C library. Refer to: http://www.apache.org/dyn/closer.cgi/avro/" "$LINENO" 5 else AVRO_CFLAGS=$pkg_cv_AVRO_CFLAGS AVRO_LIBS=$pkg_cv_AVRO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} avro" USING_AVRO="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $AVRO_CFLAGS" $as_echo "#define WITH_AVRO 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $AVRO_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avro_record_get in -lavro" >&5 $as_echo_n "checking for avro_record_get in -lavro... " >&6; } if ${ac_cv_lib_avro_avro_record_get+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lavro $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char avro_record_get (); int main () { return avro_record_get (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_avro_avro_record_get=yes else ac_cv_lib_avro_avro_record_get=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avro_avro_record_get" >&5 $as_echo "$ac_cv_lib_avro_avro_record_get" >&6; } if test "x$ac_cv_lib_avro_avro_record_get" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBAVRO 1 _ACEOF LIBS="-lavro $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $AVRO_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "avro.h" "ac_cv_header_avro_h" "$ac_includes_default" if test "x$ac_cv_header_avro_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Confluent schema-registry support" >&5 $as_echo_n "checking whether to enable Confluent schema-registry support... " >&6; } # Check whether --enable-serdes was given. if test "${enable_serdes+set}" = set; then : enableval=$enable_serdes; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} serdes" USING_SERDES="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $SERDES_CFLAGS" SERDES_LIBS="$SERDES_LIBS -lserdes" $as_echo "#define WITH_SERDES 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $SERDES_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for serdes_new in -lserdes" >&5 $as_echo_n "checking for serdes_new in -lserdes... " >&6; } if ${ac_cv_lib_serdes_serdes_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lserdes $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char serdes_new (); int main () { return serdes_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_serdes_serdes_new=yes else ac_cv_lib_serdes_serdes_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_serdes_serdes_new" >&5 $as_echo "$ac_cv_lib_serdes_serdes_new" >&6; } if test "x$ac_cv_lib_serdes_serdes_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSERDES 1 _ACEOF LIBS="-lserdes $LIBS" else as_fn_error $? "Missing Confluent serdes library. Refer to: https://github.com/confluentinc/libserdes" "$LINENO" 5 fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SERDES_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "libserdes/serdes.h" "ac_cv_header_libserdes_serdes_h" "$ac_includes_default" if test "x$ac_cv_header_libserdes_serdes_h" = xyes; then : else as_fn_error $? "Missing Confluent serdes headers. Refer to: https://github.com/confluentinc/libserdes" "$LINENO" 5 fi CFLAGS="$_save_CFLAGS" ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-ndpi-static-lib was given. if test "${with_ndpi_static_lib+set}" = set; then : withval=$with_ndpi_static_lib; absdir=`cd $withval 2>/dev/null && pwd` if test x$absdir != x ; then withval=$absdir fi NDPI_CUST_STATIC_LIB=$withval fi if test x"$NDPI_CUST_STATIC_LIB" != x""; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking your own nDPI library" >&5 $as_echo_n "checking your own nDPI library... " >&6; } if test -r $NDPI_CUST_STATIC_LIB/libndpi.a; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } NDPI_CUST_STATIC_LIB_FOUND="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "ERROR: unable to find nDPI library in $NDPI_CUST_STATIC_LIB" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable nDPI support" >&5 $as_echo_n "checking whether to enable nDPI support... " >&6; } # Check whether --enable-ndpi was given. if test "${enable_ndpi+set}" = set; then : enableval=$enable_ndpi; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libndpi >= 4.0" >&5 $as_echo_n "checking for libndpi >= 4.0... " >&6; } if test -n "$NDPI_CFLAGS"; then pkg_cv_NDPI_CFLAGS="$NDPI_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libndpi >= 4.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libndpi >= 4.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NDPI_CFLAGS=`$PKG_CONFIG --cflags "libndpi >= 4.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$NDPI_LIBS"; then pkg_cv_NDPI_LIBS="$NDPI_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libndpi >= 4.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libndpi >= 4.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NDPI_LIBS=`$PKG_CONFIG --libs "libndpi >= 4.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then NDPI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libndpi >= 4.0" 2>&1` else NDPI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libndpi >= 4.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$NDPI_PKG_ERRORS" >&5 as_fn_error $? "Missing nDPI API. Refer to: https://github.com/ntop/nDPI/" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Missing nDPI API. Refer to: https://github.com/ntop/nDPI/" "$LINENO" 5 else NDPI_CFLAGS=$pkg_cv_NDPI_CFLAGS NDPI_LIBS=$pkg_cv_NDPI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} ndpi" USING_NDPI="yes" if test x"$NDPI_CFLAGS" != x""; then NDPI_CFLAGS_INST=`echo $NDPI_CFLAGS | sed 's/ $//'` NDPI_CFLAGS_INST="$NDPI_CFLAGS_INST/libndpi" else NDPI_CFLAGS_INST="" fi PMACCT_CFLAGS="$PMACCT_CFLAGS $NDPI_CFLAGS $NDPI_CFLAGS_INST" $as_echo "#define WITH_NDPI 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $NDPI_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ndpi_init_detection_module in -lndpi" >&5 $as_echo_n "checking for ndpi_init_detection_module in -lndpi... " >&6; } if ${ac_cv_lib_ndpi_ndpi_init_detection_module+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lndpi $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ndpi_init_detection_module (); int main () { return ndpi_init_detection_module (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ndpi_ndpi_init_detection_module=yes else ac_cv_lib_ndpi_ndpi_init_detection_module=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ndpi_ndpi_init_detection_module" >&5 $as_echo "$ac_cv_lib_ndpi_ndpi_init_detection_module" >&6; } if test "x$ac_cv_lib_ndpi_ndpi_init_detection_module" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNDPI 1 _ACEOF LIBS="-lndpi $LIBS" fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $NDPI_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "libndpi/ndpi_main.h" "ac_cv_header_libndpi_ndpi_main_h" "$ac_includes_default" if test "x$ac_cv_header_libndpi_ndpi_main_h" = xyes; then : fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Unyte UDP-Notif support" >&5 $as_echo_n "checking whether to enable Unyte UDP-Notif support... " >&6; } # Check whether --enable-unyte-udp-notif was given. if test "${enable_unyte_udp_notif+set}" = set; then : enableval=$enable_unyte_udp_notif; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unyte-udp-notif >= 0.6.0" >&5 $as_echo_n "checking for unyte-udp-notif >= 0.6.0... " >&6; } if test -n "$UNYTE_UDP_NOTIF_CFLAGS"; then pkg_cv_UNYTE_UDP_NOTIF_CFLAGS="$UNYTE_UDP_NOTIF_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"unyte-udp-notif >= 0.6.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "unyte-udp-notif >= 0.6.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_UNYTE_UDP_NOTIF_CFLAGS=`$PKG_CONFIG --cflags "unyte-udp-notif >= 0.6.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$UNYTE_UDP_NOTIF_LIBS"; then pkg_cv_UNYTE_UDP_NOTIF_LIBS="$UNYTE_UDP_NOTIF_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"unyte-udp-notif >= 0.6.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "unyte-udp-notif >= 0.6.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_UNYTE_UDP_NOTIF_LIBS=`$PKG_CONFIG --libs "unyte-udp-notif >= 0.6.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then UNYTE_UDP_NOTIF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "unyte-udp-notif >= 0.6.0" 2>&1` else UNYTE_UDP_NOTIF_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "unyte-udp-notif >= 0.6.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$UNYTE_UDP_NOTIF_PKG_ERRORS" >&5 as_fn_error $? "ERROR: missing unyte-udp-notif pkg-config. Refer to: https://github.com/insa-unyte/udp-notif-c-collector" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "ERROR: missing unyte-udp-notif pkg-config. Refer to: https://github.com/insa-unyte/udp-notif-c-collector" "$LINENO" 5 else UNYTE_UDP_NOTIF_CFLAGS=$pkg_cv_UNYTE_UDP_NOTIF_CFLAGS UNYTE_UDP_NOTIF_LIBS=$pkg_cv_UNYTE_UDP_NOTIF_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} unyte-udp-notif" USING_UNYTE_UDP_NOTIF="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $UNYTE_UDP_NOTIF_CFLAGS" UNYTE_UDP_NOTIF_LIBS="$UNYTE_UDP_NOTIF_LIBS -lunyte-udp-notif" $as_echo "#define WITH_UNYTE_UDP_NOTIF 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $UNYTE_UDP_NOTIF_LIBS -lpthread" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unyte_udp_start_collector in -lunyte-udp-notif" >&5 $as_echo_n "checking for unyte_udp_start_collector in -lunyte-udp-notif... " >&6; } if ${ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lunyte-udp-notif $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char unyte_udp_start_collector (); int main () { return unyte_udp_start_collector (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector=yes else ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector" >&5 $as_echo "$ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector" >&6; } if test "x$ac_cv_lib_unyte_udp_notif_unyte_udp_start_collector" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBUNYTE_UDP_NOTIF 1 _ACEOF LIBS="-lunyte-udp-notif $LIBS" else as_fn_error $? " ERROR: missing unyte-udp-notif library. Refer to: https://github.com/insa-unyte/udp-notif-c-collector " "$LINENO" 5 fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $UNYTE_UDP_NOTIF_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "unyte-udp-notif/unyte_udp_collector.h" "ac_cv_header_unyte_udp_notif_unyte_udp_collector_h" "$ac_includes_default" if test "x$ac_cv_header_unyte_udp_notif_unyte_udp_collector_h" = xyes; then : else as_fn_error $? "ERROR: missing unyte-udp-notif headers" "$LINENO" 5 fi CFLAGS="$_save_CFLAGS" fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable eBPF support" >&5 $as_echo_n "checking whether to enable eBPF support... " >&6; } # Check whether --enable-ebpf was given. if test "${enable_ebpf+set}" = set; then : enableval=$enable_ebpf; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} ebpf" USING_EBPF="yes" PMACCT_CFLAGS="$PMACCT_CFLAGS $EBPF_CFLAGS" EBPF_LIBS="$EBPF_LIBS -lbpf" $as_echo "#define WITH_EBPF 1" >>confdefs.h _save_LIBS="$LIBS" LIBS="$LIBS $EBPF_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bpf_object__open_file in -lbpf" >&5 $as_echo_n "checking for bpf_object__open_file in -lbpf... " >&6; } if ${ac_cv_lib_bpf_bpf_object__open_file+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbpf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char bpf_object__open_file (); int main () { return bpf_object__open_file (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bpf_bpf_object__open_file=yes else ac_cv_lib_bpf_bpf_object__open_file=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bpf_bpf_object__open_file" >&5 $as_echo "$ac_cv_lib_bpf_bpf_object__open_file" >&6; } if test "x$ac_cv_lib_bpf_bpf_object__open_file" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBPF 1 _ACEOF LIBS="-lbpf $LIBS" else as_fn_error $? " ERROR: missing libbpf library. Refer to: https://github.com/libbpf/libbpf " "$LINENO" 5 fi LIBS="$_save_LIBS" _save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $EBPF_CFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "bpf/libbpf.h" "ac_cv_header_bpf_libbpf_h" "$ac_includes_default" if test "x$ac_cv_header_bpf_libbpf_h" = xyes; then : else as_fn_error $? "ERROR: missing libbpf headers" "$LINENO" 5 fi CFLAGS="$_save_CFLAGS" ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$USING_DLOPEN" = x"yes"; then $as_echo "#define HAVE_DLOPEN 1" >>confdefs.h else # Adding linking to libdl here 1) if required and 2) in case of --disable-so if test x"$USING_MYSQL" = x"yes" -o x"$USING_SQLITE3" = x"yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : LIBS="${LIBS} -ldl" else as_fn_error $? " ERROR: missing libdl devel. " "$LINENO" 5 fi fi fi if test x"$USING_SQL" = x"yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlibVersion in -lz" >&5 $as_echo_n "checking for zlibVersion in -lz... " >&6; } if ${ac_cv_lib_z_zlibVersion+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char zlibVersion (); int main () { return zlibVersion (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_zlibVersion=yes else ac_cv_lib_z_zlibVersion=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_zlibVersion" >&5 $as_echo "$ac_cv_lib_z_zlibVersion" >&6; } if test "x$ac_cv_lib_z_zlibVersion" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" else as_fn_error $? "ERROR: missing zlib. Requirement for building SQL plugins." "$LINENO" 5 fi fi LIBS="${LIBS} -lm -lpthread" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in arpa/inet.h assert.h ctype.h dirent.h dlfcn.h errno.h fcntl.h getopt.h grp.h inttypes.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in limits.h malloc.h math.h netdb.h net/if.h netinet/in.h netinet/in_systm.h netinet/ip.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in netinet/udp.h pthread.h pwd.h signal.h string.h sys/ansi.h sys/errno.h sys/file.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/ioctl.h syslog.h sys/mbuf.h sys/mman.h sys/param.h sys/poll.h sys/resource.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/select.h sys/socket.h sys/stat.h sys/time.h sys/types.h sys/un.h sys/utsname.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/wait.h time.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$ac_includes_default" if test "x$ac_cv_type_u_int64_t" = xyes; then : $as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default" if test "x$ac_cv_type_u_int32_t" = xyes; then : $as_echo "#define HAVE_U_INT32_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default" if test "x$ac_cv_type_u_int16_t" = xyes; then : $as_echo "#define HAVE_U_INT16_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default" if test "x$ac_cv_type_u_int8_t" = xyes; then : $as_echo "#define HAVE_U_INT8_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" if test "x$ac_cv_type_uint64_t" = xyes; then : $as_echo "#define HAVE_UINT64_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" if test "x$ac_cv_type_uint32_t" = xyes; then : $as_echo "#define HAVE_UINT32_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" if test "x$ac_cv_type_uint16_t" = xyes; then : $as_echo "#define HAVE_UINT16_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" if test "x$ac_cv_type_uint8_t" = xyes; then : $as_echo "#define HAVE_UINT8_T 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable NFLOG support" >&5 $as_echo_n "checking whether to enable NFLOG support... " >&6; } # Check whether --enable-nflog was given. if test "${enable_nflog+set}" = set; then : enableval=$enable_nflog; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnetfilter_log >= 1" >&5 $as_echo_n "checking for libnetfilter_log >= 1... " >&6; } if test -n "$NFLOG_CFLAGS"; then pkg_cv_NFLOG_CFLAGS="$NFLOG_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_log >= 1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libnetfilter_log >= 1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NFLOG_CFLAGS=`$PKG_CONFIG --cflags "libnetfilter_log >= 1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$NFLOG_LIBS"; then pkg_cv_NFLOG_LIBS="$NFLOG_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnetfilter_log >= 1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libnetfilter_log >= 1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NFLOG_LIBS=`$PKG_CONFIG --libs "libnetfilter_log >= 1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then NFLOG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnetfilter_log >= 1" 2>&1` else NFLOG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnetfilter_log >= 1" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$NFLOG_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libnetfilter_log >= 1) were not met: $NFLOG_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables NFLOG_CFLAGS and NFLOG_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables NFLOG_CFLAGS and NFLOG_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else NFLOG_CFLAGS=$pkg_cv_NFLOG_CFLAGS NFLOG_LIBS=$pkg_cv_NFLOG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUPPORTS="${SUPPORTS} nflog" USING_NFLOG="yes" $as_echo "#define WITH_NFLOG 1" >>confdefs.h fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to link IPv4/IPv6 traffic accounting accounting binaries" >&5 $as_echo_n "checking whether to link IPv4/IPv6 traffic accounting accounting binaries... " >&6; } # Check whether --enable-traffic-bins was given. if test "${enable_traffic_bins+set}" = set; then : enableval=$enable_traffic_bins; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_TRAFFIC_BINS 1" >>confdefs.h USING_TRAFFIC_BINS="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_TRAFFIC_BINS 1" >>confdefs.h USING_TRAFFIC_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-traffic-bins'" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to link BGP daemon binaries" >&5 $as_echo_n "checking whether to link BGP daemon binaries... " >&6; } # Check whether --enable-bgp-bins was given. if test "${enable_bgp_bins+set}" = set; then : enableval=$enable_bgp_bins; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_BGP_BINS 1" >>confdefs.h USING_BGP_BINS="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_BGP_BINS 1" >>confdefs.h USING_BGP_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-bgp-bins'" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to link BMP daemon binaries" >&5 $as_echo_n "checking whether to link BMP daemon binaries... " >&6; } # Check whether --enable-bmp-bins was given. if test "${enable_bmp_bins+set}" = set; then : enableval=$enable_bmp_bins; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_BMP_BINS 1" >>confdefs.h USING_BMP_BINS="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_BMP_BINS 1" >>confdefs.h USING_BMP_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-bmp-bins'" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to link Streaming Telemetry daemon binaries" >&5 $as_echo_n "checking whether to link Streaming Telemetry daemon binaries... " >&6; } # Check whether --enable-st-bins was given. if test "${enable_st_bins+set}" = set; then : enableval=$enable_st_bins; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_ST_BINS 1" >>confdefs.h USING_ST_BINS="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_ST_BINS 1" >>confdefs.h USING_ST_BINS="yes" COMPILE_ARGS="${COMPILE_ARGS} '--enable-st-bins'" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF for ac_func in setproctitle mallopt tdestroy strlcpy vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "SO_BINDTODEVICE" "ac_cv_have_decl_SO_BINDTODEVICE" " #include " if test "x$ac_cv_have_decl_SO_BINDTODEVICE" = xyes; then : $as_echo "#define HAVE_SO_BINDTODEVICE 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "SO_REUSEPORT" "ac_cv_have_decl_SO_REUSEPORT" " #include #include " if test "x$ac_cv_have_decl_SO_REUSEPORT" = xyes; then : $as_echo "#define HAVE_SO_REUSEPORT 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "SO_ATTACH_REUSEPORT_EBPF" "ac_cv_have_decl_SO_ATTACH_REUSEPORT_EBPF" " #include #include " if test "x$ac_cv_have_decl_SO_ATTACH_REUSEPORT_EBPF" = xyes; then : $as_echo "#define HAVE_SO_ATTACH_REUSEPORT_EBPF 1" >>confdefs.h fi WITH_EXTERNAL_DEPS_DEFAULT=yes if test ! -f "$srcdir/src/external_libs/libcdada/include/cdada.h" && test -z `git rev-parse HEAD 2> /dev/null` ; then WITH_EXTERNAL_DEPS_DEFAULT=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether external dependencies (git submodules) should be compiled" >&5 $as_echo_n "checking whether external dependencies (git submodules) should be compiled... " >&6; } # Check whether --with-external-deps was given. if test "${with_external_deps+set}" = set; then : withval=$with_external_deps; WITH_EXTERNAL_DEPS="$withval" else WITH_EXTERNAL_DEPS="$WITH_EXTERNAL_DEPS_DEFAULT" fi if test x"$WITH_EXTERNAL_DEPS" = x"yes"; then INCLUDES="-I${ac_pwd}/src/external_libs/rootfs/include ${INCLUDES} " LDFLAGS="-L${ac_pwd}/src/external_libs/rootfs/lib ${LDFLAGS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$WITH_EXTERNAL_DEPS" = "xyes"; then WITH_EXTERNAL_DEPS_TRUE= WITH_EXTERNAL_DEPS_FALSE='#' else WITH_EXTERNAL_DEPS_TRUE='#' WITH_EXTERNAL_DEPS_FALSE= fi case "$AM_DEFAULT_VERBOSITY" in #( 0) : configure_silent_rules_val=--enable-silent-rules ;; #( 1) : configure_silent_rules_val=--disable-silent-rules ;; #( *) : configure_silent_rules_val=--enable-silent-rules ;; esac ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a valid C++ compiler" >&5 $as_echo_n "checking for a valid C++ compiler... " >&6; } ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else as_fn_error $? "No C++ compiler found" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu LIBS="-lcdada -lstdc++ ${LIBS}" case "$WITH_EXTERNAL_DEPS" in #( yes) : ;; #( no) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cdada_get_ver in -lcdada" >&5 $as_echo_n "checking for cdada_get_ver in -lcdada... " >&6; } if ${ac_cv_lib_cdada_cdada_get_ver+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcdada $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char cdada_get_ver (); int main () { return cdada_get_ver (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_cdada_cdada_get_ver=yes else ac_cv_lib_cdada_cdada_get_ver=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cdada_cdada_get_ver" >&5 $as_echo "$ac_cv_lib_cdada_cdada_get_ver" >&6; } if test "x$ac_cv_lib_cdada_cdada_get_ver" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCDADA 1 _ACEOF LIBS="-lcdada $LIBS" else as_fn_error $? "Could not find libcdada" "$LINENO" 5 fi ;; #( *) : ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable debugging compiler options" >&5 $as_echo_n "checking whether to enable debugging compiler options... " >&6; } # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; if test x$enableval = x"yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } tmp_CFLAGS=`echo $CFLAGS | sed 's/O2/O0/g'` CFLAGS="$tmp_CFLAGS" CFLAGS="$CFLAGS -g -Wall -Werror" else CFLAGS="$CFLAGS -Wall -Werror" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi INCLUDES="${INCLUDES} -I$(pwd)/src" cat >>confdefs.h <<_ACEOF #define COMPILE_ARGS "$COMPILE_ARGS" _ACEOF CFLAGS="${CFLAGS} ${INCLUDES}" INCLUDES="" echo " PLATFORM ..... : `uname -m` OS ........... : `uname -rs` (`uname -n`) COMPILER ..... : ${CC} CFLAGS ....... : ${CFLAGS} LIBS ......... : ${LIBS} LDFLAGS ...... : ${LDFLAGS} PLUGINS ...... : ${PLUGINS} SUPPORTS ..... : ${SUPPORTS} Now type 'make' to compile the source code. Wanting to get in touch with other pmacct users? Join the pmacct mailing-list with an email to pmacct-discussion-subscribe@pmacct.net Need for documentation and examples? Start by reading the README.md file Star, watch or contribute to the project on GitHub: https://github.com/pmacct/pmacct " if test x"$USING_MYSQL" = x"yes"; then WITH_MYSQL_TRUE= WITH_MYSQL_FALSE='#' else WITH_MYSQL_TRUE='#' WITH_MYSQL_FALSE= fi if test x"$USING_PGSQL" = x"yes"; then WITH_PGSQL_TRUE= WITH_PGSQL_FALSE='#' else WITH_PGSQL_TRUE='#' WITH_PGSQL_FALSE= fi if test x"$USING_MONGODB" = x"yes"; then WITH_MONGODB_TRUE= WITH_MONGODB_FALSE='#' else WITH_MONGODB_TRUE='#' WITH_MONGODB_FALSE= fi if test x"$USING_SQLITE3" = x"yes"; then WITH_SQLITE3_TRUE= WITH_SQLITE3_FALSE='#' else WITH_SQLITE3_TRUE='#' WITH_SQLITE3_FALSE= fi if test x"$USING_RABBITMQ" = x"yes"; then WITH_RABBITMQ_TRUE= WITH_RABBITMQ_FALSE='#' else WITH_RABBITMQ_TRUE='#' WITH_RABBITMQ_FALSE= fi if test x"$USING_ZMQ" = x"yes"; then WITH_ZMQ_TRUE= WITH_ZMQ_FALSE='#' else WITH_ZMQ_TRUE='#' WITH_ZMQ_FALSE= fi if test x"$USING_KAFKA" = x"yes"; then WITH_KAFKA_TRUE= WITH_KAFKA_FALSE='#' else WITH_KAFKA_TRUE='#' WITH_KAFKA_FALSE= fi if test x"$USING_REDIS" = x"yes"; then WITH_REDIS_TRUE= WITH_REDIS_FALSE='#' else WITH_REDIS_TRUE='#' WITH_REDIS_FALSE= fi if test x"$USING_GNUTLS" = x"yes"; then WITH_GNUTLS_TRUE= WITH_GNUTLS_FALSE='#' else WITH_GNUTLS_TRUE='#' WITH_GNUTLS_FALSE= fi if test x"$USING_SQL" = x"yes"; then USING_SQL_TRUE= USING_SQL_FALSE='#' else USING_SQL_TRUE='#' USING_SQL_FALSE= fi if test x"$USING_JANSSON" = x"yes"; then WITH_JANSSON_TRUE= WITH_JANSSON_FALSE='#' else WITH_JANSSON_TRUE='#' WITH_JANSSON_FALSE= fi if test x"$USING_AVRO" = x"yes"; then WITH_AVRO_TRUE= WITH_AVRO_FALSE='#' else WITH_AVRO_TRUE='#' WITH_AVRO_FALSE= fi if test x"$USING_SERDES" = x"yes"; then WITH_SERDES_TRUE= WITH_SERDES_FALSE='#' else WITH_SERDES_TRUE='#' WITH_SERDES_FALSE= fi if test x"$USING_NDPI" = x"yes"; then WITH_NDPI_TRUE= WITH_NDPI_FALSE='#' else WITH_NDPI_TRUE='#' WITH_NDPI_FALSE= fi if test x"$USING_UNYTE_UDP_NOTIF" = x"yes"; then WITH_UNYTE_UDP_NOTIF_TRUE= WITH_UNYTE_UDP_NOTIF_FALSE='#' else WITH_UNYTE_UDP_NOTIF_TRUE='#' WITH_UNYTE_UDP_NOTIF_FALSE= fi if test x"$USING_EBPF" = x"yes"; then WITH_EBPF_TRUE= WITH_EBPF_FALSE='#' else WITH_EBPF_TRUE='#' WITH_EBPF_FALSE= fi if test x"$USING_NFLOG" = x"yes"; then WITH_NFLOG_TRUE= WITH_NFLOG_FALSE='#' else WITH_NFLOG_TRUE='#' WITH_NFLOG_FALSE= fi if test x"$USING_DLOPEN" = x"yes"; then WITH_DLOPEN_TRUE= WITH_DLOPEN_FALSE='#' else WITH_DLOPEN_TRUE='#' WITH_DLOPEN_FALSE= fi if test x"$USING_TRAFFIC_BINS" = x"yes"; then USING_TRAFFIC_BINS_TRUE= USING_TRAFFIC_BINS_FALSE='#' else USING_TRAFFIC_BINS_TRUE='#' USING_TRAFFIC_BINS_FALSE= fi if test x"$USING_BGP_BINS" = x"yes"; then USING_BGP_BINS_TRUE= USING_BGP_BINS_FALSE='#' else USING_BGP_BINS_TRUE='#' USING_BGP_BINS_FALSE= fi if test x"$USING_BMP_BINS" = x"yes"; then USING_BMP_BINS_TRUE= USING_BMP_BINS_FALSE='#' else USING_BMP_BINS_TRUE='#' USING_BMP_BINS_FALSE= fi if test x"$USING_ST_BINS" = x"yes"; then USING_ST_BINS_TRUE= USING_ST_BINS_FALSE='#' else USING_ST_BINS_TRUE='#' USING_ST_BINS_FALSE= fi ac_config_files="$ac_config_files src/pmacct-version.h" ac_config_files="$ac_config_files Makefile src/Makefile src/external_libs/Makefile src/nfprobe_plugin/Makefile src/sfprobe_plugin/Makefile src/bgp/Makefile src/tee_plugin/Makefile src/isis/Makefile src/bmp/Makefile src/rpki/Makefile src/telemetry/Makefile src/ndpi/Makefile src/filters/Makefile examples/lg/Makefile src/ebpf/Makefile examples/custom/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_EXTERNAL_DEPS_TRUE}" && test -z "${WITH_EXTERNAL_DEPS_FALSE}"; then as_fn_error $? "conditional \"WITH_EXTERNAL_DEPS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_MYSQL_TRUE}" && test -z "${WITH_MYSQL_FALSE}"; then as_fn_error $? "conditional \"WITH_MYSQL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_PGSQL_TRUE}" && test -z "${WITH_PGSQL_FALSE}"; then as_fn_error $? "conditional \"WITH_PGSQL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_MONGODB_TRUE}" && test -z "${WITH_MONGODB_FALSE}"; then as_fn_error $? "conditional \"WITH_MONGODB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_SQLITE3_TRUE}" && test -z "${WITH_SQLITE3_FALSE}"; then as_fn_error $? "conditional \"WITH_SQLITE3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_RABBITMQ_TRUE}" && test -z "${WITH_RABBITMQ_FALSE}"; then as_fn_error $? "conditional \"WITH_RABBITMQ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_ZMQ_TRUE}" && test -z "${WITH_ZMQ_FALSE}"; then as_fn_error $? "conditional \"WITH_ZMQ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_KAFKA_TRUE}" && test -z "${WITH_KAFKA_FALSE}"; then as_fn_error $? "conditional \"WITH_KAFKA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_REDIS_TRUE}" && test -z "${WITH_REDIS_FALSE}"; then as_fn_error $? "conditional \"WITH_REDIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_GNUTLS_TRUE}" && test -z "${WITH_GNUTLS_FALSE}"; then as_fn_error $? "conditional \"WITH_GNUTLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_SQL_TRUE}" && test -z "${USING_SQL_FALSE}"; then as_fn_error $? "conditional \"USING_SQL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_JANSSON_TRUE}" && test -z "${WITH_JANSSON_FALSE}"; then as_fn_error $? "conditional \"WITH_JANSSON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_AVRO_TRUE}" && test -z "${WITH_AVRO_FALSE}"; then as_fn_error $? "conditional \"WITH_AVRO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_SERDES_TRUE}" && test -z "${WITH_SERDES_FALSE}"; then as_fn_error $? "conditional \"WITH_SERDES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_NDPI_TRUE}" && test -z "${WITH_NDPI_FALSE}"; then as_fn_error $? "conditional \"WITH_NDPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_UNYTE_UDP_NOTIF_TRUE}" && test -z "${WITH_UNYTE_UDP_NOTIF_FALSE}"; then as_fn_error $? "conditional \"WITH_UNYTE_UDP_NOTIF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_EBPF_TRUE}" && test -z "${WITH_EBPF_FALSE}"; then as_fn_error $? "conditional \"WITH_EBPF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_NFLOG_TRUE}" && test -z "${WITH_NFLOG_FALSE}"; then as_fn_error $? "conditional \"WITH_NFLOG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_DLOPEN_TRUE}" && test -z "${WITH_DLOPEN_FALSE}"; then as_fn_error $? "conditional \"WITH_DLOPEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_TRAFFIC_BINS_TRUE}" && test -z "${USING_TRAFFIC_BINS_FALSE}"; then as_fn_error $? "conditional \"USING_TRAFFIC_BINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_BGP_BINS_TRUE}" && test -z "${USING_BGP_BINS_FALSE}"; then as_fn_error $? "conditional \"USING_BGP_BINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_BMP_BINS_TRUE}" && test -z "${USING_BMP_BINS_FALSE}"; then as_fn_error $? "conditional \"USING_BMP_BINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_ST_BINS_TRUE}" && test -z "${USING_ST_BINS_FALSE}"; then as_fn_error $? "conditional \"USING_ST_BINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by pmacct $as_me 1.7.8-git, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ pmacct config.status 1.7.8-git configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "src/pmacct-version.h") CONFIG_FILES="$CONFIG_FILES src/pmacct-version.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/external_libs/Makefile") CONFIG_FILES="$CONFIG_FILES src/external_libs/Makefile" ;; "src/nfprobe_plugin/Makefile") CONFIG_FILES="$CONFIG_FILES src/nfprobe_plugin/Makefile" ;; "src/sfprobe_plugin/Makefile") CONFIG_FILES="$CONFIG_FILES src/sfprobe_plugin/Makefile" ;; "src/bgp/Makefile") CONFIG_FILES="$CONFIG_FILES src/bgp/Makefile" ;; "src/tee_plugin/Makefile") CONFIG_FILES="$CONFIG_FILES src/tee_plugin/Makefile" ;; "src/isis/Makefile") CONFIG_FILES="$CONFIG_FILES src/isis/Makefile" ;; "src/bmp/Makefile") CONFIG_FILES="$CONFIG_FILES src/bmp/Makefile" ;; "src/rpki/Makefile") CONFIG_FILES="$CONFIG_FILES src/rpki/Makefile" ;; "src/telemetry/Makefile") CONFIG_FILES="$CONFIG_FILES src/telemetry/Makefile" ;; "src/ndpi/Makefile") CONFIG_FILES="$CONFIG_FILES src/ndpi/Makefile" ;; "src/filters/Makefile") CONFIG_FILES="$CONFIG_FILES src/filters/Makefile" ;; "examples/lg/Makefile") CONFIG_FILES="$CONFIG_FILES examples/lg/Makefile" ;; "src/ebpf/Makefile") CONFIG_FILES="$CONFIG_FILES src/ebpf/Makefile" ;; "examples/custom/Makefile") CONFIG_FILES="$CONFIG_FILES examples/custom/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 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 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 . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi pmacct-1.7.8/.dockerignore0000644000175000017500000000132614354105275014470 0ustar paolopaolo*~ # Generated by ./autogen.sh Makefile.in /aclocal.m4 /autom4te.cache/ /compile /configure /depcomp /install-sh /ltmain.sh /missing /mkinstalldirs /config.guess /config.sub /m4/libtool.m4 /m4/lt*.m4 # Generated by ./configure Makefile /config.log /config.status /libtool # Generated by make *.[oa] *.l[oa] .deps/ .libs/ /src/pmacct-version.h /src/pmacct-build.h /src/.pmacct-build.h /src/pmacct /src/pmacctd /src/nfacctd /src/sfacctd /src/uacctd /src/pmtelemetryd /src/pmbgpd /src/pmbmpd /examples/lg/pmbgp # JetBrains IDE files .idea/ # Submodule deps build marks src/external_libs/.*mark # Submodule deps tmp install directory src/external_libs/rootfs # Dockerfiles makes no sense in the build context **/Dockerfile pmacct-1.7.8/telemetry/0000755000175000017500000000000014354105275014024 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/0000755000175000017500000000000014354105275015614 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/0000755000175000017500000000000014354105633016142 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/pmgrpcd.py0000644000175000017500000004414014354105275020155 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from optparse import OptionParser import configparser import os from datetime import datetime import sys # TODO we'll move the next into more appropiate places from lib_pmgrpcd import ( SCRIPTVERSION, init_pmgrpcdlog, PMGRPCDLOG, FileNotFound, init_serializelog, signalhandler, ) import lib_pmgrpcd import signal from concurrent import futures # gRPC and Protobuf imports import grpc import cisco_grpc_dialout_pb2_grpc import huawei_grpc_dialout_pb2_grpc import time from config import configure from file_modules.file_input import FileInput from pathlib import Path import os # from gnmi_pmgrpcd import GNMIClient from kafka_modules.kafka_avro_exporter import manually_serialize _ONE_DAY_IN_SECONDS = 60 * 60 * 24 # This is the default location for auxiliary files (config, gmaps, and others) FOLDER_EXTRA_FILES = Path("config_files") ABSOLUTE_FILE = Path(__file__).resolve() CONFIGDIR = ABSOLUTE_FILE.parent / FOLDER_EXTRA_FILES DEFAULT_CONFIGFILE = CONFIGDIR / "telemetry.conf" CONFIGFILE = str(DEFAULT_CONFIGFILE) # Config arguments # There seems to be no maintained library allowing for env-config-arg configuration. # We are simulating this here using the next function: # Inspired by https://stackoverflow.com/questions/10551117/setting-options-from-environment-variables-when-using-argparse class OptionParserEnv(OptionParser): def add_option(self, *arg, **kargs): envvar = kargs.get("env_name", None) try: del kargs["env_name"] except: pass can_be_none = kargs.get("can_be_none", False) try: del kargs["can_be_none"] except: pass if envvar is not None: new_help = kargs.get("help", "") new_help = new_help + " [Env variable {}]".format(envvar) kargs["help"] = new_help # Modify the default to be the one ine the env_name if envvar in os.environ: PMGRPCDLOG.debug("Getting data from %s from the env variable %s", arg[0], envvar) kargs["default"] = os.environ[envvar] if not can_be_none and "default" in kargs and kargs["default"] is None: raise Exception("Parameter with env %s is None", envvar) super().add_option(*arg, **kargs) def main(): global CONFIGFILE usage_str = "%prog [options]" version_str = "%prog " + SCRIPTVERSION # We go over arguments very simply and obtaining the config file, if this one is available. config_file_flag = "-c" extra_argv = sys.argv[1:] config_file_args = None if extra_argv: if config_file_flag in extra_argv: index = extra_argv.index(config_file_flag) file_index = index + 1 try: config_file_args = extra_argv[file_index] except: pass if config_file_args is not None: CONFIGFILE = config_file_args # Load config. And make sure other files exists. config = configparser.ConfigParser() if os.path.isfile(CONFIGFILE): config.read(CONFIGFILE) if "PMGRPCD" not in config.sections(): raise FileNotFound("There is no PMGRPCD on configuration file") else: raise FileNotFound( "We could not find configuration file in {}".format(CONFIGFILE) ) # Parse arguments. Default must be a named argument! parser = OptionParserEnv(usage=usage_str, version=version_str) # the next one is not really used, but important to avoid errors. parser.add_option( config_file_flag, default=str(DEFAULT_CONFIGFILE), dest="configuration", help="Path to configuration file", ) #gnmi options #parser.add_option( # "-g", # "--gnmi_enable", # default=config.getboolean("PMGRPCD", "gnmi_enable", fallback=False), # help="Boolean defining whether gnmi is enable (this disables the rest of collectrors)", #) #parser.add_option( # "--gnmi_target", # env_name = "GNMI_SERVER", # default=config.get("PMGRPCD", "gnmi_target", fallback=None), # help="The url of the gnmi target", #) parser.add_option( "-T", "--topic", env_name = "PM_TOPIC", default=config.get("PMGRPCD", "topic", fallback=None), dest="topic", help="the json data are serialized to this topic", ) parser.add_option( "-B", "--bsservers", default=config.get("PMGRPCD", "bsservers", fallback=None), env_name = "BSSERVERS", dest="bsservers", help="bootstrap servers url with port to reach kafka", ) parser.add_option( "-S", "--secproto", default=config.get("PMGRPCD", "secproto", fallback="ssl"), dest="secproto", help="security protocol (is normaly ssl)", ) parser.add_option( "-O", "--sslcertloc", env_name = "SSLCERTLOC", default=config.get("PMGRPCD", "sslcertloc", fallback=None), dest="sslcertloc", help="path/file to ssl certification location", ) parser.add_option( "-K", "--sslkeyloc", env_name = "SSLKEYLOC", default=config.get("PMGRPCD", "sslkeyloc", fallback=None), dest="sslkeyloc", help="path/file to ssl key location", ) parser.add_option( "-U", "--urlscreg", env_name="URLSCREG", default=config.get("PMGRPCD", "urlscreg", fallback=None), dest="urlscreg", help="the url to the schema-registry", ) parser.add_option( "-L", "--calocation", env_name="CALOCATION", default=config.get("PMGRPCD", "calocation", fallback=None), dest="calocation", help="the ca_location used to connect to schema-registry", ) parser.add_option( "-G", "--gpbmapfile", env_name="GPBMAPFILE", default=config.get("PMGRPCD", "gpbmapfile", fallback=None), dest="gpbmapfile", help="change path/name of gpbmapfile [default: %default]", ) parser.add_option( "-M", "--avscmapfile", env_name="AVSCMALFILE", default=config.get("PMGRPCD", "avscmapfile", fallback=None), dest="avscmapfile", help="path/name to the avscmapfile", ) parser.add_option( "-m", "--mitigation", action="store_true", default=config.getboolean("PMGRPCD", "mitigation"), dest="mitigation", help="enable plugin mitigation mod_result_dict from python module mitigation.py", ) parser.add_option( "-d", "--debug", action="store_true", default=config.getboolean("PMGRPCD", "debug"), dest="debug", help="enable debug messages on the logfile", ) parser.add_option( "-l", "--PMGRPCDLOGfile", default=config.get("PMGRPCD", "PMGRPCDLOGfile"), dest="PMGRPCDLOGfile", help="PMGRPCDLOGfile the logfile on the collector face with path/name [default: %default]", ) parser.add_option( "-a", "--serializelogfile", default=config.get("PMGRPCD", "serializelogfile"), dest="serializelogfile", help="serializelogfile with path/name for kafka avro and zmq messages [default: %default]", ) parser.add_option( "-I", "--ipport", action="store", type="string", default=config.get("PMGRPCD", "ipport"), dest="ipport", help="change the ipport the daemon is listen on [default: %default]", ) parser.add_option( "-w", "--workers", action="store", type="int", default=config.get("PMGRPCD", "workers"), dest="workers", help="change the nr of paralell working processes [default: %default]", ) parser.add_option( "-b", "--processpool", action="store", type="int", default=config.get("PMGRPCD", "processpool"), dest="ProcessPool", help="change the nr of processes within the ProcessPool of Kafka [default: %default]", ) parser.add_option( "-C", "--cisco", action="store_true", default=config.getboolean("PMGRPCD", "cisco"), dest="cisco", help="enable the grpc messages comming from Cisco [default: %default]", ) parser.add_option( "-H", "--huawei", action="store_true", default=config.getboolean("PMGRPCD", "huawei"), dest="huawei", help="enable the grpc messages comming from Huawei [default: %default]", ) parser.add_option( "-t", "--cenctype", action="store", type="string", default=config.get("PMGRPCD", "cenctype"), dest="cenctype", help="cenctype is the type of encoding for cisco. This is because some protofiles are incompatible. With cenctype=gpbkv only cisco is enabled. The encoding type can be json, gpbcomp, gpbkv [default: %default]", ) parser.add_option( "-e", "--example", action="store_true", default=config.getboolean("PMGRPCD", "example"), dest="example", help="Enable writing Example Json-Data-Files [default: %default]", ) parser.add_option( "-E", "--examplepath", default=config.get("PMGRPCD", "examplepath"), dest="examplepath", help="dump a json example of each proto/path to this examplepath", ) parser.add_option( "-j", "--jsondatadumpfile", dest="jsondatadumpfile", help="writing the output to the jsondatadumpfile path/name", ) parser.add_option( "-r", "--rawdatadumpfile", default=config.get("PMGRPCD", "rawdatadumpfile", fallback=None), dest="rawdatadumpfile", help="writing the raw data from the routers to the rowdatafile path/name", ) parser.add_option( "-z", "--zmq", action="store_true", default=config.getboolean("PMGRPCD", "zmq"), dest="zmq", help="enable forwarding to ZMQ [default: %default]", ) parser.add_option( "-p", "--zmqipport", default=config.get("PMGRPCD", "zmqipport"), dest="zmqipport", help="define proto://ip:port of zmq socket bind [default: %default]", ) parser.add_option( "-k", "--kafkaavro", action="store_true", default=config.getboolean("PMGRPCD", "kafkaavro"), dest="kafkaavro", help="enable forwarding to Kafka kafkaavro (with schema-registry) [default: %default]", ) parser.add_option( "-o", "--onlyopenconfig", action="store_true", default=config.getboolean("PMGRPCD", "onlyopenconfig"), dest="onlyopenconfig", help="only accept pakets of openconfig", ) parser.add_option( "-i", "--ip", dest="ip", help="only accept pakets of this single ip" ) parser.add_option( "-A", "--avscid", dest="avscid", help="this is to serialize manually with avscid and jsondatafile (for development)", ) parser.add_option( "-J", "--jsondatafile", dest="jsondatafile", help="this is to serialize manually with avscid and jsondatafile (for development)", ) parser.add_option( "-R", "--rawdatafile", dest="rawdatafile", help="this is to process manually (via mitigation) process a rawdatafile with a single rawrecord (for development)", ) parser.add_option( "-N", "--console", action="store_true", dest="console", help="this is to display all log-messages also on console (for development)", ) parser.add_option( "-v", action="store_true", dest="version", help="print version of this script" ) parser.add_option( "-F", "--no-flatten", action="store_false", default=config.getboolean("PMGRPCD", "flatten"), dest="flatten", help="disable data flattening [default: %default]", ) parser.add_option( "-s", "--kafkasimple", default=config.getboolean("PMGRPCD", "kafkasimple", fallback=False), dest="kafkasimple", help="Boolean if kafkasimple should be enabled.", ) parser.add_option( "--file_exporter_file", default=config.get("PMGRPCD", "file_exporter_file", fallback=None), dest="file_exporter_file", help="Name of file for file exporter.", ) parser.add_option( "--file_importer_file", default=config.get("PMGRPCD", "file_importer_file", fallback=None), dest="file_importer_file", help="Name of the file to import. If set, we will ignore the rest of the importers.", ) (lib_pmgrpcd.OPTIONS, args) = parser.parse_args() init_pmgrpcdlog() init_serializelog() if lib_pmgrpcd.OPTIONS.version: print(parser.get_version()) raise SystemExit PMGRPCDLOG.info("Using %s as config file", CONFIGFILE) PMGRPCDLOG.info("startoptions of this script: %s", str(lib_pmgrpcd.OPTIONS)) # Test-Statements Logging # ----------------------- # PMGRPCDLOG.debug('debug message') # PMGRPCDLOG.info('info message') # PMGRPCDLOG.warning('warn message') # PMGRPCDLOG.error('error message') # PMGRPCDLOG.critical('critical message') # serializelog.debug('debug message') # serializelog.info('info message') # serializelog.warning('warn message') # serializelog.error('error message') # serializelog.critical('critical message') configure() PMGRPCDLOG.info("enable listening to SIGNAL USR1 with Signalhandler") signal.signal(signal.SIGUSR1, signalhandler) PMGRPCDLOG.info("enable listening to SIGNAL USR2 with Signalhandler") signal.signal(signal.SIGUSR2, signalhandler) # I am going to comment the manually export of data from now, this could go into other script. if lib_pmgrpcd.OPTIONS.avscid and lib_pmgrpcd.OPTIONS.jsondatafile: manually_serialize() elif lib_pmgrpcd.OPTIONS.file_importer_file: file_importer = FileInput(lib_pmgrpcd.OPTIONS.file_importer_file) PMGRPCDLOG.info("Starting file import") file_importer.generate() PMGRPCDLOG.info("No more data, sleeping 3 secs") time.sleep(3) PMGRPCDLOG.info("Finalizing file import") elif lib_pmgrpcd.OPTIONS.avscid or lib_pmgrpcd.OPTIONS.jsondatafile: PMGRPCDLOG.info( "manually serialize need both lib_pmgrpcd.OPTIONS avscid and jsondatafile" ) parser.print_help() #elif lib_pmgrpcd.OPTIONS.gnmi_enable: # if lib_pmgrpcd.OPTIONS.gnmi_target is None: # error = "gnmi target not configured, but gnmi enabled" # PMGRPCDLOG.error(error) # raise Exception(error) # # PMGRPCDLOG.info("Starting contact with gnmi server %s. Other functions will be ignored", lib_pmgrpcd.OPTIONS.gnmi_target) # channel = grpc.insecure_channel(lib_pmgrpcd.OPTIONS.gnmi_target) # gnmi_client = GNMIClient(channel) # breakpoint() else: # make sure some important files exist if not os.path.isfile(lib_pmgrpcd.OPTIONS.gpbmapfile): raise FileNotFound("No gpbmapfile file found in {}".format(lib_pmgrpcd.OPTIONS.gpbmapfile)) # TODO: Do we really need this always? if not os.path.isfile(lib_pmgrpcd.OPTIONS.avscmapfile): raise FileNotFound("No avscmapfile file found in {}".format(lib_pmgrpcd.OPTIONS.avscmapfile)) PMGRPCDLOG.info("pmgrpsd.py is started at %s", str(datetime.now())) serve() def serve(): gRPCserver = grpc.server( futures.ThreadPoolExecutor(max_workers=lib_pmgrpcd.OPTIONS.workers) ) if lib_pmgrpcd.OPTIONS.huawei: if lib_pmgrpcd.OPTIONS.cenctype == 'gpbkv': PMGRPCDLOG.info("Huawei is disabled because cenctype=gpbkv") else: PMGRPCDLOG.info("Huawei is enabled") # Ugly, but we have to load just here because if not there is an exception due to a conflict between the cisco and huawei protos. from huawei_pmgrpcd import gRPCDataserviceServicer huawei_grpc_dialout_pb2_grpc.add_gRPCDataserviceServicer_to_server( gRPCDataserviceServicer(), gRPCserver ) else: PMGRPCDLOG.info("Huawei is disabled") if lib_pmgrpcd.OPTIONS.cisco: PMGRPCDLOG.info("Cisco is enabled") # Ugly, but we have to load just here because if not there is an exception due to a conflict between the cisco and huawei protos. from cisco_pmgrpcd import gRPCMdtDialoutServicer cisco_grpc_dialout_pb2_grpc.add_gRPCMdtDialoutServicer_to_server( gRPCMdtDialoutServicer(), gRPCserver ) else: PMGRPCDLOG.info("Cisco is disabled") gRPCserver.add_insecure_port(lib_pmgrpcd.OPTIONS.ipport) gRPCserver.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: gRPCserver.stop(0) PMGRPCDLOG.info("Stopping server") time.sleep(1) if __name__ == "__main__": main() pmacct-1.7.8/telemetry/decoders/v3/__init__.py0000644000175000017500000000000014354105275020243 0ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/zmq_modules/0000755000175000017500000000000014354105275020503 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/zmq_modules/__init__.py0000644000175000017500000000000014354105275022602 0ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/zmq_modules/zmq_exporter.py0000644000175000017500000000340614354105275023617 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from zmq import ZMQError import zmq import lib_pmgrpcd from export_pmgrpcd import Exporter class ZmqExporter(Exporter): def __init__(self): zmqContext = zmq.Context() self.zmqSock = zmqContext.socket(zmq.PUSH) self.zmqSock.bind(lib_pmgrpcd.OPTIONS.zmqipport) self.flags = zmq.NOBLOCK def process_metric(self, datajsonstring): if not self.zmqSock.closed: try: self.zmqSock.send_string("%s" % datajsonstring, self.flags) except ZMQError: lib_pmgrpcd.SERIALIZELOG.debug( "ZMQError: %s" % (lib_pmgrpcd.OPTIONS.jsondatafile) ) pmacct-1.7.8/telemetry/decoders/v3/protos/0000755000175000017500000000000014354105275017472 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/protos/cisco_telemetry_pb2.py0000644000175000017500000004126414354105275024010 0ustar paolopaolo# Generated by the protocol buffer compiler. DO NOT EDIT! # source: cisco_telemetry.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='cisco_telemetry.proto', package='telemetry', syntax='proto3', serialized_pb=_b('\n\x15\x63isco_telemetry.proto\x12\ttelemetry\"\xbc\x02\n\tTelemetry\x12\x15\n\x0bnode_id_str\x18\x01 \x01(\tH\x00\x12\x1d\n\x13subscription_id_str\x18\x03 \x01(\tH\x01\x12\x15\n\rencoding_path\x18\x06 \x01(\t\x12\x15\n\rcollection_id\x18\x08 \x01(\x04\x12\x1d\n\x15\x63ollection_start_time\x18\t \x01(\x04\x12\x15\n\rmsg_timestamp\x18\n \x01(\x04\x12-\n\ndata_gpbkv\x18\x0b \x03(\x0b\x32\x19.telemetry.TelemetryField\x12.\n\x08\x64\x61ta_gpb\x18\x0c \x01(\x0b\x32\x1c.telemetry.TelemetryGPBTable\x12\x1b\n\x13\x63ollection_end_time\x18\r \x01(\x04\x42\t\n\x07node_idB\x0e\n\x0csubscription\"\xc1\x02\n\x0eTelemetryField\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x15\n\x0b\x62ytes_value\x18\x04 \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\x05 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x06 \x01(\x08H\x00\x12\x16\n\x0cuint32_value\x18\x07 \x01(\rH\x00\x12\x16\n\x0cuint64_value\x18\x08 \x01(\x04H\x00\x12\x16\n\x0csint32_value\x18\t \x01(\x11H\x00\x12\x16\n\x0csint64_value\x18\n \x01(\x12H\x00\x12\x16\n\x0c\x64ouble_value\x18\x0b \x01(\x01H\x00\x12\x15\n\x0b\x66loat_value\x18\x0c \x01(\x02H\x00\x12)\n\x06\x66ields\x18\x0f \x03(\x0b\x32\x19.telemetry.TelemetryFieldB\x0f\n\rvalue_by_type\"<\n\x11TelemetryGPBTable\x12\'\n\x03row\x18\x01 \x03(\x0b\x32\x1a.telemetry.TelemetryRowGPB\"C\n\x0fTelemetryRowGPB\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0c\n\x04keys\x18\n \x01(\x0c\x12\x0f\n\x07\x63ontent\x18\x0b \x01(\x0c\x62\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _TELEMETRY = _descriptor.Descriptor( name='Telemetry', full_name='telemetry.Telemetry', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='node_id_str', full_name='telemetry.Telemetry.node_id_str', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='subscription_id_str', full_name='telemetry.Telemetry.subscription_id_str', index=1, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='encoding_path', full_name='telemetry.Telemetry.encoding_path', index=2, number=6, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='collection_id', full_name='telemetry.Telemetry.collection_id', index=3, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='collection_start_time', full_name='telemetry.Telemetry.collection_start_time', index=4, number=9, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='msg_timestamp', full_name='telemetry.Telemetry.msg_timestamp', index=5, number=10, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='data_gpbkv', full_name='telemetry.Telemetry.data_gpbkv', index=6, number=11, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='data_gpb', full_name='telemetry.Telemetry.data_gpb', index=7, number=12, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='collection_end_time', full_name='telemetry.Telemetry.collection_end_time', index=8, number=13, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='node_id', full_name='telemetry.Telemetry.node_id', index=0, containing_type=None, fields=[]), _descriptor.OneofDescriptor( name='subscription', full_name='telemetry.Telemetry.subscription', index=1, containing_type=None, fields=[]), ], serialized_start=37, serialized_end=353, ) _TELEMETRYFIELD = _descriptor.Descriptor( name='TelemetryField', full_name='telemetry.TelemetryField', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='timestamp', full_name='telemetry.TelemetryField.timestamp', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='name', full_name='telemetry.TelemetryField.name', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='bytes_value', full_name='telemetry.TelemetryField.bytes_value', index=2, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='string_value', full_name='telemetry.TelemetryField.string_value', index=3, number=5, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='bool_value', full_name='telemetry.TelemetryField.bool_value', index=4, number=6, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='uint32_value', full_name='telemetry.TelemetryField.uint32_value', index=5, number=7, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='uint64_value', full_name='telemetry.TelemetryField.uint64_value', index=6, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='sint32_value', full_name='telemetry.TelemetryField.sint32_value', index=7, number=9, type=17, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='sint64_value', full_name='telemetry.TelemetryField.sint64_value', index=8, number=10, type=18, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='double_value', full_name='telemetry.TelemetryField.double_value', index=9, number=11, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='float_value', full_name='telemetry.TelemetryField.float_value', index=10, number=12, type=2, cpp_type=6, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='fields', full_name='telemetry.TelemetryField.fields', index=11, number=15, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='value_by_type', full_name='telemetry.TelemetryField.value_by_type', index=0, containing_type=None, fields=[]), ], serialized_start=356, serialized_end=677, ) _TELEMETRYGPBTABLE = _descriptor.Descriptor( name='TelemetryGPBTable', full_name='telemetry.TelemetryGPBTable', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='row', full_name='telemetry.TelemetryGPBTable.row', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=679, serialized_end=739, ) _TELEMETRYROWGPB = _descriptor.Descriptor( name='TelemetryRowGPB', full_name='telemetry.TelemetryRowGPB', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='timestamp', full_name='telemetry.TelemetryRowGPB.timestamp', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='keys', full_name='telemetry.TelemetryRowGPB.keys', index=1, number=10, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='content', full_name='telemetry.TelemetryRowGPB.content', index=2, number=11, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=741, serialized_end=808, ) _TELEMETRY.fields_by_name['data_gpbkv'].message_type = _TELEMETRYFIELD _TELEMETRY.fields_by_name['data_gpb'].message_type = _TELEMETRYGPBTABLE _TELEMETRY.oneofs_by_name['node_id'].fields.append( _TELEMETRY.fields_by_name['node_id_str']) _TELEMETRY.fields_by_name['node_id_str'].containing_oneof = _TELEMETRY.oneofs_by_name['node_id'] _TELEMETRY.oneofs_by_name['subscription'].fields.append( _TELEMETRY.fields_by_name['subscription_id_str']) _TELEMETRY.fields_by_name['subscription_id_str'].containing_oneof = _TELEMETRY.oneofs_by_name['subscription'] _TELEMETRYFIELD.fields_by_name['fields'].message_type = _TELEMETRYFIELD _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['bytes_value']) _TELEMETRYFIELD.fields_by_name['bytes_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['string_value']) _TELEMETRYFIELD.fields_by_name['string_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['bool_value']) _TELEMETRYFIELD.fields_by_name['bool_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['uint32_value']) _TELEMETRYFIELD.fields_by_name['uint32_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['uint64_value']) _TELEMETRYFIELD.fields_by_name['uint64_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['sint32_value']) _TELEMETRYFIELD.fields_by_name['sint32_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['sint64_value']) _TELEMETRYFIELD.fields_by_name['sint64_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['double_value']) _TELEMETRYFIELD.fields_by_name['double_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYFIELD.oneofs_by_name['value_by_type'].fields.append( _TELEMETRYFIELD.fields_by_name['float_value']) _TELEMETRYFIELD.fields_by_name['float_value'].containing_oneof = _TELEMETRYFIELD.oneofs_by_name['value_by_type'] _TELEMETRYGPBTABLE.fields_by_name['row'].message_type = _TELEMETRYROWGPB DESCRIPTOR.message_types_by_name['Telemetry'] = _TELEMETRY DESCRIPTOR.message_types_by_name['TelemetryField'] = _TELEMETRYFIELD DESCRIPTOR.message_types_by_name['TelemetryGPBTable'] = _TELEMETRYGPBTABLE DESCRIPTOR.message_types_by_name['TelemetryRowGPB'] = _TELEMETRYROWGPB Telemetry = _reflection.GeneratedProtocolMessageType('Telemetry', (_message.Message,), dict( DESCRIPTOR = _TELEMETRY, __module__ = 'cisco_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.Telemetry) )) _sym_db.RegisterMessage(Telemetry) TelemetryField = _reflection.GeneratedProtocolMessageType('TelemetryField', (_message.Message,), dict( DESCRIPTOR = _TELEMETRYFIELD, __module__ = 'cisco_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.TelemetryField) )) _sym_db.RegisterMessage(TelemetryField) TelemetryGPBTable = _reflection.GeneratedProtocolMessageType('TelemetryGPBTable', (_message.Message,), dict( DESCRIPTOR = _TELEMETRYGPBTABLE, __module__ = 'cisco_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.TelemetryGPBTable) )) _sym_db.RegisterMessage(TelemetryGPBTable) TelemetryRowGPB = _reflection.GeneratedProtocolMessageType('TelemetryRowGPB', (_message.Message,), dict( DESCRIPTOR = _TELEMETRYROWGPB, __module__ = 'cisco_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.TelemetryRowGPB) )) _sym_db.RegisterMessage(TelemetryRowGPB) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/huawei_grpc_dialout_pb2_grpc.py0000755000175000017500000000302414354105275025642 0ustar paolopaolo# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! import grpc import huawei_grpc_dialout_pb2 as huawei__grpc__dialout__pb2 class gRPCDataserviceStub(object): # missing associated documentation comment in .proto file pass def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.dataPublish = channel.stream_stream( '/huawei_dialout.gRPCDataservice/dataPublish', request_serializer=huawei__grpc__dialout__pb2.serviceArgs.SerializeToString, response_deserializer=huawei__grpc__dialout__pb2.serviceArgs.FromString, ) class gRPCDataserviceServicer(object): # missing associated documentation comment in .proto file pass def dataPublish(self, request_iterator, context): # missing associated documentation comment in .proto file pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_gRPCDataserviceServicer_to_server(servicer, server): rpc_method_handlers = { 'dataPublish': grpc.stream_stream_rpc_method_handler( servicer.dataPublish, request_deserializer=huawei__grpc__dialout__pb2.serviceArgs.FromString, response_serializer=huawei__grpc__dialout__pb2.serviceArgs.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'huawei_dialout.gRPCDataservice', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) pmacct-1.7.8/telemetry/decoders/v3/protos/cisco_telemetry.proto0000644000175000017500000001777314354105275023770 0ustar paolopaolo/* ---------------------------------------------------------------------------- * telemetry_bis.proto - Telemetry protobuf definitions * * August 2016 * * Copyright (c) 2016 by Cisco Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ---------------------------------------------------------------------------- */ syntax = "proto3"; package telemetry; // Telemetry message is the outermost payload message used to stream // telemetry in a Model Driven Telemetry (MDT) system. MDT provides a // mechanism for an external entity to subscribe to a data set defined in // a Yang model and receive periodic or event-based updates of the data // set from an MDT-capable device. message Telemetry { // // node_id_str is a string encoded unique node ID of the MDT-capable // device producing the message. (node_id_uuid alternative is not currently // produced in IOS-XR) oneof node_id { string node_id_str = 1; // bytes node_id_uuid = 2; } // // subscription_id_str is the name of the subscription against which // this content is being produced. (subscription_id alternative is not // currently produced in IOS-XR) oneof subscription { string subscription_id_str = 3; // uint32 subscription_id = 4; } // // sensor_path is not currently produced in IOS-XR // string sensor_path = 5; // // encoding_path is the Yang path leading to the content in this message. // The Yang tree encoded in the content section of this message is rooted // at the point described by the encoding_path. string encoding_path = 6; // // model_version is not currently produced in IOS-XR // string model_version = 7; // // collection_id identifies messages belonging to a collection round. // Multiple message may be generated from a collection round. uint64 collection_id = 8; // // collection_start_time is the time when the collection identified by // the collection_id begins - encoded as milliseconds since the epoch. // If a single collection is spread over multiple Telemetry Messages, // collection_start_time may be encoded in the first Telemetry Message // for the collection only. uint64 collection_start_time = 9; // // msg_timestamp is the time when the data encoded in the Telemetry // message is generated - encoded as milliseconds since the epoch. uint64 msg_timestamp = 10; // // data_gpbkv contains the payload data if data is being encoded in the // self-describing GPB-KV format. repeated TelemetryField data_gpbkv = 11; // // data_gpb contains the payload data if data is being encoded as // serialised GPB messages. TelemetryGPBTable data_gpb = 12; // // collection_end_time is the timestamp when the last Telemetry message // for a collection has been encoded - encoded as milliseconds since the // epoch. If a single collection is spread over multiple Telemetry // messages, collection_end_time is encoded in the last Telemetry Message // for the collection only. uint64 collection_end_time = 13; // // heartbeat_sequence_number is not currently produced in IOS-XR // uint64 heartbeat_sequence_number = 14; // not produced } // // TelemetryField messages are used to export content in the self // describing GPB KV form. The TelemetryField message is sufficient to // decode telemetry messages for all models. KV-GPB encoding is very // similar in concept, to JSON encoding message TelemetryField { // // timestamp represents the starting time of the generation of data // starting from this key, value pair in this message - encoded as // milliseconds since the epoch. It is encoded when different from the // msg_timestamp in the containing Telemetry Message. This field can be // omitted if the value is the same as a TelemetryField message up the // hierarchy within the same Telemetry Message as well. uint64 timestamp = 1; // // name: string encoding of the name in the key, value pair. It is // the corresponding YANG element name. string name = 2; // // value_by_type, if present, for the corresponding YANG element // represented by the name field in the same TelemetryField message. The // value is encoded to the matching type as defined in the YANG model. // YANG models often define new types (derived types) using one or more // base types. The types included in the oneof grouping is sufficient to // represent such derived types. Derived types represented as a Yang // container are encoded using the nesting primitive defined in this // encoding proposal. oneof value_by_type { bytes bytes_value = 4; string string_value = 5; bool bool_value = 6; uint32 uint32_value = 7; uint64 uint64_value = 8; sint32 sint32_value = 9; sint64 sint64_value = 10; double double_value = 11; float float_value = 12; } // // The Yang model may include nesting (e.g hierarchy of containers). The // next level of nesting, if present, is encoded, starting from fields. repeated TelemetryField fields = 15; } // TelemetryGPBTable contains a repeated number of TelemetryRowGPB, // each of which represents content from a subtree instance in the // the YANG model. For example; a TelemetryGPBTable might contain // the interface statistics of a collection of interfaces. message TelemetryGPBTable { repeated TelemetryRowGPB row = 1; } // // TelemetryRowGPB, in conjunction with the Telemetry encoding_path and // model_version, unambiguously represents the root of a subtree in // the YANG model, and content from that subtree encoded in serialised // GPB messages. For example; a TelemetryRowGPB might contain the // interface statistics of one interface. Per encoding-path .proto // messages are required to decode keys/content pairs below. message TelemetryRowGPB { // // timestamp at which the data for this instance of the TelemetryRowGPB // message was generated by an MDT-capable device - encoded as // milliseconds since the epoch. When included, this is typically // different from the msg_timestamp in the containing Telemetry message. uint64 timestamp = 1; // // keys: if the encoding-path includes one or more list elements, and/or // ends in a list element, the keys field is a GPB encoded message that // contains the sequence of key values for each such list element in the // encoding-path traversed starting from the root. The set of keys // unambiguously identifies the instance of data encoded in the // TelemetryRowGPB message. Corresponding protobuf message definition will // be required to decode the byte stream. The encoding_path field in // Telemetry message, together with model_version field should be // sufficient to identify the corresponding protobuf message. bytes keys = 10; // // content: the content field is a GPB encoded message that contains the // data for the corresponding encoding-path. A separate decoding pass // would be performed by consumer with the content field as a GPB message // and the matching .proto used to decode the message. Corresponding // protobuf message definition will be required to decode the byte // stream. The encoding_path field in Telemetry message, together with // model_version field should be sufficient to identify the corresponding // protobuf message. The decoded combination of keys (when present) and // content, unambiguously represents an instance of the data set, as // defined in the Yang model, identified by the encoding-path in the // containing Telemetry message. bytes content = 11; } pmacct-1.7.8/telemetry/decoders/v3/protos/gnmi_ext_pb2.py0000644000175000017500000002350414354105275022425 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: gnmi_ext.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf.internal import enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='gnmi_ext.proto', package='gnmi_ext', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x0egnmi_ext.proto\x12\x08gnmi_ext\"\x86\x01\n\tExtension\x12\x37\n\x0eregistered_ext\x18\x01 \x01(\x0b\x32\x1d.gnmi_ext.RegisteredExtensionH\x00\x12\x39\n\x12master_arbitration\x18\x02 \x01(\x0b\x32\x1b.gnmi_ext.MasterArbitrationH\x00\x42\x05\n\x03\x65xt\"E\n\x13RegisteredExtension\x12!\n\x02id\x18\x01 \x01(\x0e\x32\x15.gnmi_ext.ExtensionID\x12\x0b\n\x03msg\x18\x02 \x01(\x0c\"Y\n\x11MasterArbitration\x12\x1c\n\x04role\x18\x01 \x01(\x0b\x32\x0e.gnmi_ext.Role\x12&\n\x0b\x65lection_id\x18\x02 \x01(\x0b\x32\x11.gnmi_ext.Uint128\"$\n\x07Uint128\x12\x0c\n\x04high\x18\x01 \x01(\x04\x12\x0b\n\x03low\x18\x02 \x01(\x04\"\x12\n\x04Role\x12\n\n\x02id\x18\x01 \x01(\t*3\n\x0b\x45xtensionID\x12\r\n\tEID_UNSET\x10\x00\x12\x15\n\x10\x45ID_EXPERIMENTAL\x10\xe7\x07\x62\x06proto3') ) _EXTENSIONID = _descriptor.EnumDescriptor( name='ExtensionID', full_name='gnmi_ext.ExtensionID', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='EID_UNSET', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='EID_EXPERIMENTAL', index=1, number=999, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=385, serialized_end=436, ) _sym_db.RegisterEnumDescriptor(_EXTENSIONID) ExtensionID = enum_type_wrapper.EnumTypeWrapper(_EXTENSIONID) EID_UNSET = 0 EID_EXPERIMENTAL = 999 _EXTENSION = _descriptor.Descriptor( name='Extension', full_name='gnmi_ext.Extension', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='registered_ext', full_name='gnmi_ext.Extension.registered_ext', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='master_arbitration', full_name='gnmi_ext.Extension.master_arbitration', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='ext', full_name='gnmi_ext.Extension.ext', index=0, containing_type=None, fields=[]), ], serialized_start=29, serialized_end=163, ) _REGISTEREDEXTENSION = _descriptor.Descriptor( name='RegisteredExtension', full_name='gnmi_ext.RegisteredExtension', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='gnmi_ext.RegisteredExtension.id', index=0, number=1, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='msg', full_name='gnmi_ext.RegisteredExtension.msg', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=165, serialized_end=234, ) _MASTERARBITRATION = _descriptor.Descriptor( name='MasterArbitration', full_name='gnmi_ext.MasterArbitration', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='role', full_name='gnmi_ext.MasterArbitration.role', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='election_id', full_name='gnmi_ext.MasterArbitration.election_id', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=236, serialized_end=325, ) _UINT128 = _descriptor.Descriptor( name='Uint128', full_name='gnmi_ext.Uint128', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='high', full_name='gnmi_ext.Uint128.high', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='low', full_name='gnmi_ext.Uint128.low', index=1, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=327, serialized_end=363, ) _ROLE = _descriptor.Descriptor( name='Role', full_name='gnmi_ext.Role', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='gnmi_ext.Role.id', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=365, serialized_end=383, ) _EXTENSION.fields_by_name['registered_ext'].message_type = _REGISTEREDEXTENSION _EXTENSION.fields_by_name['master_arbitration'].message_type = _MASTERARBITRATION _EXTENSION.oneofs_by_name['ext'].fields.append( _EXTENSION.fields_by_name['registered_ext']) _EXTENSION.fields_by_name['registered_ext'].containing_oneof = _EXTENSION.oneofs_by_name['ext'] _EXTENSION.oneofs_by_name['ext'].fields.append( _EXTENSION.fields_by_name['master_arbitration']) _EXTENSION.fields_by_name['master_arbitration'].containing_oneof = _EXTENSION.oneofs_by_name['ext'] _REGISTEREDEXTENSION.fields_by_name['id'].enum_type = _EXTENSIONID _MASTERARBITRATION.fields_by_name['role'].message_type = _ROLE _MASTERARBITRATION.fields_by_name['election_id'].message_type = _UINT128 DESCRIPTOR.message_types_by_name['Extension'] = _EXTENSION DESCRIPTOR.message_types_by_name['RegisteredExtension'] = _REGISTEREDEXTENSION DESCRIPTOR.message_types_by_name['MasterArbitration'] = _MASTERARBITRATION DESCRIPTOR.message_types_by_name['Uint128'] = _UINT128 DESCRIPTOR.message_types_by_name['Role'] = _ROLE DESCRIPTOR.enum_types_by_name['ExtensionID'] = _EXTENSIONID _sym_db.RegisterFileDescriptor(DESCRIPTOR) Extension = _reflection.GeneratedProtocolMessageType('Extension', (_message.Message,), dict( DESCRIPTOR = _EXTENSION, __module__ = 'gnmi_ext_pb2' # @@protoc_insertion_point(class_scope:gnmi_ext.Extension) )) _sym_db.RegisterMessage(Extension) RegisteredExtension = _reflection.GeneratedProtocolMessageType('RegisteredExtension', (_message.Message,), dict( DESCRIPTOR = _REGISTEREDEXTENSION, __module__ = 'gnmi_ext_pb2' # @@protoc_insertion_point(class_scope:gnmi_ext.RegisteredExtension) )) _sym_db.RegisterMessage(RegisteredExtension) MasterArbitration = _reflection.GeneratedProtocolMessageType('MasterArbitration', (_message.Message,), dict( DESCRIPTOR = _MASTERARBITRATION, __module__ = 'gnmi_ext_pb2' # @@protoc_insertion_point(class_scope:gnmi_ext.MasterArbitration) )) _sym_db.RegisterMessage(MasterArbitration) Uint128 = _reflection.GeneratedProtocolMessageType('Uint128', (_message.Message,), dict( DESCRIPTOR = _UINT128, __module__ = 'gnmi_ext_pb2' # @@protoc_insertion_point(class_scope:gnmi_ext.Uint128) )) _sym_db.RegisterMessage(Uint128) Role = _reflection.GeneratedProtocolMessageType('Role', (_message.Message,), dict( DESCRIPTOR = _ROLE, __module__ = 'gnmi_ext_pb2' # @@protoc_insertion_point(class_scope:gnmi_ext.Role) )) _sym_db.RegisterMessage(Role) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/openconfig_interfaces_pb2.py0000755000175000017500000016217614354105275025161 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: openconfig-interfaces.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='openconfig-interfaces.proto', package='openconfig_interfaces', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x1bopenconfig-interfaces.proto\x12\x15openconfig_interfaces\"\xc8\x1a\n\nInterfaces\x12>\n\tinterface\x18\x01 \x03(\x0b\x32+.openconfig_interfaces.Interfaces.Interface\x1a\xf9\x19\n\tInterface\x12\x42\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x32.openconfig_interfaces.Interfaces.Interface.Config\x12G\n\thold_time\x18\x02 \x01(\x0b\x32\x34.openconfig_interfaces.Interfaces.Interface.HoldTime\x12\x0c\n\x04name\x18\x03 \x01(\t\x12@\n\x05state\x18\x04 \x01(\x0b\x32\x31.openconfig_interfaces.Interfaces.Interface.State\x12P\n\rsubinterfaces\x18\x05 \x01(\x0b\x32\x39.openconfig_interfaces.Interfaces.Interface.Subinterfaces\x1an\n\x06\x43onfig\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12\x15\n\rloopback_mode\x18\x03 \x01(\x08\x12\x0b\n\x03mtu\x18\x04 \x01(\r\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x0c\n\x04type\x18\x06 \x01(\t\x1a\xe9\x01\n\x08HoldTime\x12K\n\x06\x63onfig\x18\x01 \x01(\x0b\x32;.openconfig_interfaces.Interfaces.Interface.HoldTime.Config\x12I\n\x05state\x18\x02 \x01(\x0b\x32:.openconfig_interfaces.Interfaces.Interface.HoldTime.State\x1a\"\n\x06\x43onfig\x12\x0c\n\x04\x64own\x18\x01 \x01(\r\x12\n\n\x02up\x18\x02 \x01(\r\x1a!\n\x05State\x12\x0c\n\x04\x64own\x18\x01 \x01(\r\x12\n\n\x02up\x18\x02 \x01(\r\x1a\xd2\x08\n\x05State\x12S\n\x0c\x61\x64min_status\x18\x01 \x01(\x0e\x32=.openconfig_interfaces.Interfaces.Interface.State.AdminStatus\x12L\n\x08\x63ounters\x18\x02 \x01(\x0b\x32:.openconfig_interfaces.Interfaces.Interface.State.Counters\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x0f\n\x07ifindex\x18\x05 \x01(\r\x12\x13\n\x0blast_change\x18\x06 \x01(\x04\x12\x15\n\rloopback_mode\x18\x07 \x01(\x08\x12\x0b\n\x03mtu\x18\x08 \x01(\r\x12\x0c\n\x04name\x18\t \x01(\t\x12Q\n\x0boper_status\x18\n \x01(\x0e\x32<.openconfig_interfaces.Interfaces.Interface.State.OperStatus\x12\x0c\n\x04type\x18\x0b \x01(\t\x1a\x87\x03\n\x08\x43ounters\x12\x1b\n\x13\x63\x61rrier_transitions\x18\x01 \x01(\x04\x12\x19\n\x11in_broadcast_pkts\x18\x02 \x01(\x04\x12\x13\n\x0bin_discards\x18\x03 \x01(\x04\x12\x11\n\tin_errors\x18\x04 \x01(\x04\x12\x15\n\rin_fcs_errors\x18\x05 \x01(\x04\x12\x19\n\x11in_multicast_pkts\x18\x06 \x01(\x04\x12\x11\n\tin_octets\x18\x07 \x01(\x04\x12\x17\n\x0fin_unicast_pkts\x18\x08 \x01(\x04\x12\x19\n\x11in_unknown_protos\x18\t \x01(\x04\x12\x12\n\nlast_clear\x18\n \x01(\x04\x12\x1a\n\x12out_broadcast_pkts\x18\x0b \x01(\x04\x12\x14\n\x0cout_discards\x18\x0c \x01(\x04\x12\x12\n\nout_errors\x18\r \x01(\x04\x12\x1a\n\x12out_multicast_pkts\x18\x0e \x01(\x04\x12\x12\n\nout_octets\x18\x0f \x01(\x04\x12\x18\n\x10out_unicast_pkts\x18\x10 \x01(\x04\"i\n\x0b\x41\x64minStatus\x12\x17\n\x13\x41\x64minStatus_INVALID\x10\x00\x12\x12\n\x0e\x41\x64minStatus_UP\x10\x01\x12\x14\n\x10\x41\x64minStatus_DOWN\x10\x02\x12\x17\n\x13\x41\x64minStatus_TESTING\x10\x03\"\xd1\x01\n\nOperStatus\x12\x16\n\x12OperStatus_INVALID\x10\x00\x12\x11\n\rOperStatus_UP\x10\x01\x12\x13\n\x0fOperStatus_DOWN\x10\x02\x12\x16\n\x12OperStatus_TESTING\x10\x03\x12\x16\n\x12OperStatus_UNKNOWN\x10\x04\x12\x16\n\x12OperStatus_DORMANT\x10\x05\x12\x1a\n\x16OperStatus_NOT_PRESENT\x10\x06\x12\x1f\n\x1bOperStatus_LOWER_LAYER_DOWN\x10\x07\x1a\x8b\x0c\n\rSubinterfaces\x12\\\n\x0csubinterface\x18\x01 \x03(\x0b\x32\x46.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface\x1a\x9b\x0b\n\x0cSubinterface\x12]\n\x06\x63onfig\x18\x01 \x01(\x0b\x32M.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config\x12\r\n\x05index\x18\x02 \x01(\r\x12[\n\x05state\x18\x03 \x01(\x0b\x32L.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State\x1a=\n\x06\x43onfig\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12\r\n\x05index\x18\x03 \x01(\r\x1a\x80\t\n\x05State\x12n\n\x0c\x61\x64min_status\x18\x01 \x01(\x0e\x32X.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.AdminStatus\x12g\n\x08\x63ounters\x18\x02 \x01(\x0b\x32U.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x0f\n\x07ifindex\x18\x05 \x01(\r\x12\r\n\x05index\x18\x06 \x01(\r\x12\x13\n\x0blast_change\x18\x07 \x01(\x04\x12\x0c\n\x04name\x18\x08 \x01(\t\x12l\n\x0boper_status\x18\t \x01(\x0e\x32W.openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.OperStatus\x1a\x87\x03\n\x08\x43ounters\x12\x1b\n\x13\x63\x61rrier_transitions\x18\x01 \x01(\x04\x12\x19\n\x11in_broadcast_pkts\x18\x02 \x01(\x04\x12\x13\n\x0bin_discards\x18\x03 \x01(\x04\x12\x11\n\tin_errors\x18\x04 \x01(\x04\x12\x15\n\rin_fcs_errors\x18\x05 \x01(\x04\x12\x19\n\x11in_multicast_pkts\x18\x06 \x01(\x04\x12\x11\n\tin_octets\x18\x07 \x01(\x04\x12\x17\n\x0fin_unicast_pkts\x18\x08 \x01(\x04\x12\x19\n\x11in_unknown_protos\x18\t \x01(\x04\x12\x12\n\nlast_clear\x18\n \x01(\x04\x12\x1a\n\x12out_broadcast_pkts\x18\x0b \x01(\x04\x12\x14\n\x0cout_discards\x18\x0c \x01(\x04\x12\x12\n\nout_errors\x18\r \x01(\x04\x12\x1a\n\x12out_multicast_pkts\x18\x0e \x01(\x04\x12\x12\n\nout_octets\x18\x0f \x01(\x04\x12\x18\n\x10out_unicast_pkts\x18\x10 \x01(\x04\"i\n\x0b\x41\x64minStatus\x12\x17\n\x13\x41\x64minStatus_INVALID\x10\x00\x12\x12\n\x0e\x41\x64minStatus_UP\x10\x01\x12\x14\n\x10\x41\x64minStatus_DOWN\x10\x02\x12\x17\n\x13\x41\x64minStatus_TESTING\x10\x03\"\xd1\x01\n\nOperStatus\x12\x16\n\x12OperStatus_INVALID\x10\x00\x12\x11\n\rOperStatus_UP\x10\x01\x12\x13\n\x0fOperStatus_DOWN\x10\x02\x12\x16\n\x12OperStatus_TESTING\x10\x03\x12\x16\n\x12OperStatus_UNKNOWN\x10\x04\x12\x16\n\x12OperStatus_DORMANT\x10\x05\x12\x1a\n\x16OperStatus_NOT_PRESENT\x10\x06\x12\x1f\n\x1bOperStatus_LOWER_LAYER_DOWN\x10\x07\x62\x06proto3') ) _INTERFACES_INTERFACE_STATE_ADMINSTATUS = _descriptor.EnumDescriptor( name='AdminStatus', full_name='openconfig_interfaces.Interfaces.Interface.State.AdminStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='AdminStatus_INVALID', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_UP', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_DOWN', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_TESTING', index=3, number=3, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1588, serialized_end=1693, ) _sym_db.RegisterEnumDescriptor(_INTERFACES_INTERFACE_STATE_ADMINSTATUS) _INTERFACES_INTERFACE_STATE_OPERSTATUS = _descriptor.EnumDescriptor( name='OperStatus', full_name='openconfig_interfaces.Interfaces.Interface.State.OperStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='OperStatus_INVALID', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_UP', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_DOWN', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_TESTING', index=3, number=3, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_UNKNOWN', index=4, number=4, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_DORMANT', index=5, number=5, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_NOT_PRESENT', index=6, number=6, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_LOWER_LAYER_DOWN', index=7, number=7, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1696, serialized_end=1905, ) _sym_db.RegisterEnumDescriptor(_INTERFACES_INTERFACE_STATE_OPERSTATUS) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_ADMINSTATUS = _descriptor.EnumDescriptor( name='AdminStatus', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.AdminStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='AdminStatus_INVALID', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_UP', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_DOWN', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='AdminStatus_TESTING', index=3, number=3, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1588, serialized_end=1693, ) _sym_db.RegisterEnumDescriptor(_INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_ADMINSTATUS) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_OPERSTATUS = _descriptor.EnumDescriptor( name='OperStatus', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.OperStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='OperStatus_INVALID', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_UP', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_DOWN', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_TESTING', index=3, number=3, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_UNKNOWN', index=4, number=4, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_DORMANT', index=5, number=5, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_NOT_PRESENT', index=6, number=6, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OperStatus_LOWER_LAYER_DOWN', index=7, number=7, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1696, serialized_end=1905, ) _sym_db.RegisterEnumDescriptor(_INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_OPERSTATUS) _INTERFACES_INTERFACE_CONFIG = _descriptor.Descriptor( name='Config', full_name='openconfig_interfaces.Interfaces.Interface.Config', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='description', full_name='openconfig_interfaces.Interfaces.Interface.Config.description', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='enabled', full_name='openconfig_interfaces.Interfaces.Interface.Config.enabled', index=1, number=2, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='loopback_mode', full_name='openconfig_interfaces.Interfaces.Interface.Config.loopback_mode', index=2, number=3, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mtu', full_name='openconfig_interfaces.Interfaces.Interface.Config.mtu', index=3, number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='name', full_name='openconfig_interfaces.Interfaces.Interface.Config.name', index=4, number=5, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='type', full_name='openconfig_interfaces.Interfaces.Interface.Config.type', index=5, number=6, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=450, serialized_end=560, ) _INTERFACES_INTERFACE_HOLDTIME_CONFIG = _descriptor.Descriptor( name='Config', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.Config', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='down', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.Config.down', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='up', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.Config.up', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=727, serialized_end=761, ) _INTERFACES_INTERFACE_HOLDTIME_STATE = _descriptor.Descriptor( name='State', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.State', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='down', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.State.down', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='up', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.State.up', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=763, serialized_end=796, ) _INTERFACES_INTERFACE_HOLDTIME = _descriptor.Descriptor( name='HoldTime', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='config', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.config', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='state', full_name='openconfig_interfaces.Interfaces.Interface.HoldTime.state', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_HOLDTIME_CONFIG, _INTERFACES_INTERFACE_HOLDTIME_STATE, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=563, serialized_end=796, ) _INTERFACES_INTERFACE_STATE_COUNTERS = _descriptor.Descriptor( name='Counters', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='carrier_transitions', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.carrier_transitions', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_broadcast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_broadcast_pkts', index=1, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_discards', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_discards', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_errors', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_errors', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_fcs_errors', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_fcs_errors', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_multicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_multicast_pkts', index=5, number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_octets', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_octets', index=6, number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_unicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_unicast_pkts', index=7, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_unknown_protos', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.in_unknown_protos', index=8, number=9, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='last_clear', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.last_clear', index=9, number=10, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_broadcast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_broadcast_pkts', index=10, number=11, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_discards', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_discards', index=11, number=12, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_errors', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_errors', index=12, number=13, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_multicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_multicast_pkts', index=13, number=14, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_octets', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_octets', index=14, number=15, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_unicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.State.Counters.out_unicast_pkts', index=15, number=16, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1195, serialized_end=1586, ) _INTERFACES_INTERFACE_STATE = _descriptor.Descriptor( name='State', full_name='openconfig_interfaces.Interfaces.Interface.State', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='admin_status', full_name='openconfig_interfaces.Interfaces.Interface.State.admin_status', index=0, number=1, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='counters', full_name='openconfig_interfaces.Interfaces.Interface.State.counters', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='description', full_name='openconfig_interfaces.Interfaces.Interface.State.description', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='enabled', full_name='openconfig_interfaces.Interfaces.Interface.State.enabled', index=3, number=4, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifindex', full_name='openconfig_interfaces.Interfaces.Interface.State.ifindex', index=4, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='last_change', full_name='openconfig_interfaces.Interfaces.Interface.State.last_change', index=5, number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='loopback_mode', full_name='openconfig_interfaces.Interfaces.Interface.State.loopback_mode', index=6, number=7, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mtu', full_name='openconfig_interfaces.Interfaces.Interface.State.mtu', index=7, number=8, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='name', full_name='openconfig_interfaces.Interfaces.Interface.State.name', index=8, number=9, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='oper_status', full_name='openconfig_interfaces.Interfaces.Interface.State.oper_status', index=9, number=10, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='type', full_name='openconfig_interfaces.Interfaces.Interface.State.type', index=10, number=11, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_STATE_COUNTERS, ], enum_types=[ _INTERFACES_INTERFACE_STATE_ADMINSTATUS, _INTERFACES_INTERFACE_STATE_OPERSTATUS, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=799, serialized_end=1905, ) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_CONFIG = _descriptor.Descriptor( name='Config', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='description', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config.description', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='enabled', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config.enabled', index=1, number=2, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='index', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config.index', index=2, number=3, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2239, serialized_end=2300, ) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_COUNTERS = _descriptor.Descriptor( name='Counters', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='carrier_transitions', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.carrier_transitions', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_broadcast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_broadcast_pkts', index=1, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_discards', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_discards', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_errors', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_errors', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_fcs_errors', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_fcs_errors', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_multicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_multicast_pkts', index=5, number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_octets', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_octets', index=6, number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_unicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_unicast_pkts', index=7, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='in_unknown_protos', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.in_unknown_protos', index=8, number=9, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='last_clear', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.last_clear', index=9, number=10, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_broadcast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_broadcast_pkts', index=10, number=11, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_discards', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_discards', index=11, number=12, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_errors', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_errors', index=12, number=13, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_multicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_multicast_pkts', index=13, number=14, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_octets', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_octets', index=14, number=15, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='out_unicast_pkts', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters.out_unicast_pkts', index=15, number=16, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1195, serialized_end=1586, ) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE = _descriptor.Descriptor( name='State', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='admin_status', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.admin_status', index=0, number=1, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='counters', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.counters', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='description', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.description', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='enabled', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.enabled', index=3, number=4, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifindex', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.ifindex', index=4, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='index', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.index', index=5, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='last_change', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.last_change', index=6, number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='name', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.name', index=7, number=8, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='oper_status', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.oper_status', index=8, number=9, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_COUNTERS, ], enum_types=[ _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_ADMINSTATUS, _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_OPERSTATUS, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2303, serialized_end=3455, ) _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE = _descriptor.Descriptor( name='Subinterface', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='config', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.config', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='index', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.index', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='state', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.state', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_CONFIG, _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2020, serialized_end=3455, ) _INTERFACES_INTERFACE_SUBINTERFACES = _descriptor.Descriptor( name='Subinterfaces', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='subinterface', full_name='openconfig_interfaces.Interfaces.Interface.Subinterfaces.subinterface', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1908, serialized_end=3455, ) _INTERFACES_INTERFACE = _descriptor.Descriptor( name='Interface', full_name='openconfig_interfaces.Interfaces.Interface', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='config', full_name='openconfig_interfaces.Interfaces.Interface.config', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='hold_time', full_name='openconfig_interfaces.Interfaces.Interface.hold_time', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='name', full_name='openconfig_interfaces.Interfaces.Interface.name', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='state', full_name='openconfig_interfaces.Interfaces.Interface.state', index=3, number=4, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='subinterfaces', full_name='openconfig_interfaces.Interfaces.Interface.subinterfaces', index=4, number=5, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE_CONFIG, _INTERFACES_INTERFACE_HOLDTIME, _INTERFACES_INTERFACE_STATE, _INTERFACES_INTERFACE_SUBINTERFACES, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=134, serialized_end=3455, ) _INTERFACES = _descriptor.Descriptor( name='Interfaces', full_name='openconfig_interfaces.Interfaces', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='interface', full_name='openconfig_interfaces.Interfaces.interface', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_INTERFACES_INTERFACE, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=55, serialized_end=3455, ) _INTERFACES_INTERFACE_CONFIG.containing_type = _INTERFACES_INTERFACE _INTERFACES_INTERFACE_HOLDTIME_CONFIG.containing_type = _INTERFACES_INTERFACE_HOLDTIME _INTERFACES_INTERFACE_HOLDTIME_STATE.containing_type = _INTERFACES_INTERFACE_HOLDTIME _INTERFACES_INTERFACE_HOLDTIME.fields_by_name['config'].message_type = _INTERFACES_INTERFACE_HOLDTIME_CONFIG _INTERFACES_INTERFACE_HOLDTIME.fields_by_name['state'].message_type = _INTERFACES_INTERFACE_HOLDTIME_STATE _INTERFACES_INTERFACE_HOLDTIME.containing_type = _INTERFACES_INTERFACE _INTERFACES_INTERFACE_STATE_COUNTERS.containing_type = _INTERFACES_INTERFACE_STATE _INTERFACES_INTERFACE_STATE.fields_by_name['admin_status'].enum_type = _INTERFACES_INTERFACE_STATE_ADMINSTATUS _INTERFACES_INTERFACE_STATE.fields_by_name['counters'].message_type = _INTERFACES_INTERFACE_STATE_COUNTERS _INTERFACES_INTERFACE_STATE.fields_by_name['oper_status'].enum_type = _INTERFACES_INTERFACE_STATE_OPERSTATUS _INTERFACES_INTERFACE_STATE.containing_type = _INTERFACES_INTERFACE _INTERFACES_INTERFACE_STATE_ADMINSTATUS.containing_type = _INTERFACES_INTERFACE_STATE _INTERFACES_INTERFACE_STATE_OPERSTATUS.containing_type = _INTERFACES_INTERFACE_STATE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_CONFIG.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_COUNTERS.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE.fields_by_name['admin_status'].enum_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_ADMINSTATUS _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE.fields_by_name['counters'].message_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_COUNTERS _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE.fields_by_name['oper_status'].enum_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_OPERSTATUS _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_ADMINSTATUS.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_OPERSTATUS.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE.fields_by_name['config'].message_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_CONFIG _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE.fields_by_name['state'].message_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE.containing_type = _INTERFACES_INTERFACE_SUBINTERFACES _INTERFACES_INTERFACE_SUBINTERFACES.fields_by_name['subinterface'].message_type = _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE _INTERFACES_INTERFACE_SUBINTERFACES.containing_type = _INTERFACES_INTERFACE _INTERFACES_INTERFACE.fields_by_name['config'].message_type = _INTERFACES_INTERFACE_CONFIG _INTERFACES_INTERFACE.fields_by_name['hold_time'].message_type = _INTERFACES_INTERFACE_HOLDTIME _INTERFACES_INTERFACE.fields_by_name['state'].message_type = _INTERFACES_INTERFACE_STATE _INTERFACES_INTERFACE.fields_by_name['subinterfaces'].message_type = _INTERFACES_INTERFACE_SUBINTERFACES _INTERFACES_INTERFACE.containing_type = _INTERFACES _INTERFACES.fields_by_name['interface'].message_type = _INTERFACES_INTERFACE DESCRIPTOR.message_types_by_name['Interfaces'] = _INTERFACES _sym_db.RegisterFileDescriptor(DESCRIPTOR) Interfaces = _reflection.GeneratedProtocolMessageType('Interfaces', (_message.Message,), { 'Interface' : _reflection.GeneratedProtocolMessageType('Interface', (_message.Message,), { 'Config' : _reflection.GeneratedProtocolMessageType('Config', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_CONFIG, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Config) }) , 'HoldTime' : _reflection.GeneratedProtocolMessageType('HoldTime', (_message.Message,), { 'Config' : _reflection.GeneratedProtocolMessageType('Config', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_HOLDTIME_CONFIG, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.HoldTime.Config) }) , 'State' : _reflection.GeneratedProtocolMessageType('State', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_HOLDTIME_STATE, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.HoldTime.State) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE_HOLDTIME, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.HoldTime) }) , 'State' : _reflection.GeneratedProtocolMessageType('State', (_message.Message,), { 'Counters' : _reflection.GeneratedProtocolMessageType('Counters', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_STATE_COUNTERS, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.State.Counters) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE_STATE, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.State) }) , 'Subinterfaces' : _reflection.GeneratedProtocolMessageType('Subinterfaces', (_message.Message,), { 'Subinterface' : _reflection.GeneratedProtocolMessageType('Subinterface', (_message.Message,), { 'Config' : _reflection.GeneratedProtocolMessageType('Config', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_CONFIG, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.Config) }) , 'State' : _reflection.GeneratedProtocolMessageType('State', (_message.Message,), { 'Counters' : _reflection.GeneratedProtocolMessageType('Counters', (_message.Message,), { 'DESCRIPTOR' : _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE_COUNTERS, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State.Counters) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE_STATE, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface.State) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE_SUBINTERFACES_SUBINTERFACE, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Subinterfaces.Subinterface) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE_SUBINTERFACES, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface.Subinterfaces) }) , 'DESCRIPTOR' : _INTERFACES_INTERFACE, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces.Interface) }) , 'DESCRIPTOR' : _INTERFACES, '__module__' : 'openconfig_interfaces_pb2' # @@protoc_insertion_point(class_scope:openconfig_interfaces.Interfaces) }) _sym_db.RegisterMessage(Interfaces) _sym_db.RegisterMessage(Interfaces.Interface) _sym_db.RegisterMessage(Interfaces.Interface.Config) _sym_db.RegisterMessage(Interfaces.Interface.HoldTime) _sym_db.RegisterMessage(Interfaces.Interface.HoldTime.Config) _sym_db.RegisterMessage(Interfaces.Interface.HoldTime.State) _sym_db.RegisterMessage(Interfaces.Interface.State) _sym_db.RegisterMessage(Interfaces.Interface.State.Counters) _sym_db.RegisterMessage(Interfaces.Interface.Subinterfaces) _sym_db.RegisterMessage(Interfaces.Interface.Subinterfaces.Subinterface) _sym_db.RegisterMessage(Interfaces.Interface.Subinterfaces.Subinterface.Config) _sym_db.RegisterMessage(Interfaces.Interface.Subinterfaces.Subinterface.State) _sym_db.RegisterMessage(Interfaces.Interface.Subinterfaces.Subinterface.State.Counters) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/huawei-telemetry.proto0000755000175000017500000000127514354105275024061 0ustar paolopaolosyntax = "proto3"; package telemetry; message Telemetry { string node_id_str = 1; string subscription_id_str = 2; string sensor_path = 3; uint64 collection_id = 4; uint64 collection_start_time = 5; // 生æˆè¿™ä¸ªTelemetryçš„messageæ•°æ®çš„æ—¶é—´æˆ³ uint64 msg_timestamp = 6; TelemetryGPBTable data_gpb = 7; uint64 collection_end_time = 8; uint32 current_period = 9; string except_desc = 10; } //å¤šä»½å®žä¾‹æ•°æ® message TelemetryGPBTable { repeated TelemetryRowGPB row = 1; } message TelemetryRowGPB { //æ¯ä¸ªå®žä¾‹æ•°æ®å¯¹åº”的采集时间戳 uint64 timestamp = 1; //GPBç¼–ç åŽçš„ä¸€ä»½å®žä¾‹æ•°æ® bytes content = 11; } pmacct-1.7.8/telemetry/decoders/v3/protos/huawei_grpc_dialout_pb2.py0000755000175000017500000000676314354105275024644 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: huawei-grpc-dialout.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='huawei-grpc-dialout.proto', package='huawei_dialout', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x19huawei-grpc-dialout.proto\x12\x0ehuawei_dialout\":\n\x0bserviceArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t2`\n\x0fgRPCDataservice\x12M\n\x0b\x64\x61taPublish\x12\x1b.huawei_dialout.serviceArgs\x1a\x1b.huawei_dialout.serviceArgs\"\x00(\x01\x30\x01\x62\x06proto3') ) _SERVICEARGS = _descriptor.Descriptor( name='serviceArgs', full_name='huawei_dialout.serviceArgs', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ReqId', full_name='huawei_dialout.serviceArgs.ReqId', index=0, number=1, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='data', full_name='huawei_dialout.serviceArgs.data', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='errors', full_name='huawei_dialout.serviceArgs.errors', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=45, serialized_end=103, ) DESCRIPTOR.message_types_by_name['serviceArgs'] = _SERVICEARGS _sym_db.RegisterFileDescriptor(DESCRIPTOR) serviceArgs = _reflection.GeneratedProtocolMessageType('serviceArgs', (_message.Message,), { 'DESCRIPTOR' : _SERVICEARGS, '__module__' : 'huawei_grpc_dialout_pb2' # @@protoc_insertion_point(class_scope:huawei_dialout.serviceArgs) }) _sym_db.RegisterMessage(serviceArgs) _GRPCDATASERVICE = _descriptor.ServiceDescriptor( name='gRPCDataservice', full_name='huawei_dialout.gRPCDataservice', file=DESCRIPTOR, index=0, serialized_options=None, serialized_start=105, serialized_end=201, methods=[ _descriptor.MethodDescriptor( name='dataPublish', full_name='huawei_dialout.gRPCDataservice.dataPublish', index=0, containing_service=None, input_type=_SERVICEARGS, output_type=_SERVICEARGS, serialized_options=None, ), ]) _sym_db.RegisterServiceDescriptor(_GRPCDATASERVICE) DESCRIPTOR.services_by_name['gRPCDataservice'] = _GRPCDATASERVICE # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/cisco_grpc_dialout_pb2.py0000755000175000017500000000676414354105275024463 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: cisco_grpc_dialout.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='cisco_grpc_dialout.proto', package='mdt_dialout', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x18\x63isco_grpc_dialout.proto\x12\x0bmdt_dialout\"=\n\x0eMdtDialoutArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t2^\n\x0egRPCMdtDialout\x12L\n\nMdtDialout\x12\x1b.mdt_dialout.MdtDialoutArgs\x1a\x1b.mdt_dialout.MdtDialoutArgs\"\x00(\x01\x30\x01\x62\x06proto3') ) _MDTDIALOUTARGS = _descriptor.Descriptor( name='MdtDialoutArgs', full_name='mdt_dialout.MdtDialoutArgs', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ReqId', full_name='mdt_dialout.MdtDialoutArgs.ReqId', index=0, number=1, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='data', full_name='mdt_dialout.MdtDialoutArgs.data', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='errors', full_name='mdt_dialout.MdtDialoutArgs.errors', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=41, serialized_end=102, ) DESCRIPTOR.message_types_by_name['MdtDialoutArgs'] = _MDTDIALOUTARGS _sym_db.RegisterFileDescriptor(DESCRIPTOR) MdtDialoutArgs = _reflection.GeneratedProtocolMessageType('MdtDialoutArgs', (_message.Message,), { 'DESCRIPTOR' : _MDTDIALOUTARGS, '__module__' : 'cisco_grpc_dialout_pb2' # @@protoc_insertion_point(class_scope:mdt_dialout.MdtDialoutArgs) }) _sym_db.RegisterMessage(MdtDialoutArgs) _GRPCMDTDIALOUT = _descriptor.ServiceDescriptor( name='gRPCMdtDialout', full_name='mdt_dialout.gRPCMdtDialout', file=DESCRIPTOR, index=0, serialized_options=None, serialized_start=104, serialized_end=198, methods=[ _descriptor.MethodDescriptor( name='MdtDialout', full_name='mdt_dialout.gRPCMdtDialout.MdtDialout', index=0, containing_service=None, input_type=_MDTDIALOUTARGS, output_type=_MDTDIALOUTARGS, serialized_options=None, ), ]) _sym_db.RegisterServiceDescriptor(_GRPCMDTDIALOUT) DESCRIPTOR.services_by_name['gRPCMdtDialout'] = _GRPCMDTDIALOUT # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/huawei_ifm_pb2.py0000755000175000017500000004663714354105275022747 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: huawei-ifm.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='huawei-ifm.proto', package='huawei_ifm', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x10huawei-ifm.proto\x12\nhuawei_ifm\"\xc1\x08\n\x03Ifm\x12.\n\ninterfaces\x18\x05 \x01(\x0b\x32\x1a.huawei_ifm.Ifm.Interfaces\x1a\x89\x08\n\nInterfaces\x12\x37\n\tinterface\x18\x01 \x03(\x0b\x32$.huawei_ifm.Ifm.Interfaces.Interface\x1a\xc1\x07\n\tInterface\x12I\n\rifAdminStatus\x18\x05 \x01(\x0e\x32\x32.huawei_ifm.Ifm.Interfaces.Interface.IfAdminStatus\x12I\n\rifClearedStat\x18\t \x01(\x0b\x32\x32.huawei_ifm.Ifm.Interfaces.Interface.IfClearedStat\x12I\n\rifDynamicInfo\x18\r \x01(\x0b\x32\x32.huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo\x12\x0f\n\x07ifIndex\x18\x10 \x01(\r\x12\x0e\n\x06ifName\x18\x19 \x01(\t\x12G\n\x0cifStatistics\x18# \x01(\x0b\x32\x31.huawei_ifm.Ifm.Interfaces.Interface.IfStatistics\x1a\x35\n\rIfClearedStat\x12\x10\n\x08sendByte\x18\x1d \x01(\x04\x12\x12\n\nsendPacket\x18$ \x01(\x04\x1a\xa2\x01\n\rIfDynamicInfo\x12U\n\x0cifOperStatus\x18\x05 \x01(\x0e\x32?.huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo.IfOperStatus\":\n\x0cIfOperStatus\x12\x15\n\x11IfOperStatus_DOWN\x10\x00\x12\x13\n\x0fIfOperStatus_UP\x10\x01\x1a\xcd\x02\n\x0cIfStatistics\x12\x16\n\x0ercvBroadPacket\x18\x02 \x01(\x04\x12\x15\n\rrcvDropPacket\x18\x03 \x01(\x04\x12\x16\n\x0ercvErrorPacket\x18\x04 \x01(\x04\x12\x15\n\rrcvMutiPacket\x18\x05 \x01(\x04\x12\x14\n\x0crcvUniPacket\x18\x06 \x01(\x04\x12\x13\n\x0breceiveByte\x18\x07 \x01(\x04\x12\x15\n\rreceivePacket\x18\x08 \x01(\x04\x12\x17\n\x0fsendBroadPacket\x18\t \x01(\x04\x12\x10\n\x08sendByte\x18\n \x01(\x04\x12\x16\n\x0esendDropPacket\x18\x0b \x01(\x04\x12\x17\n\x0fsendErrorPacket\x18\x0c \x01(\x04\x12\x16\n\x0esendMutiPacket\x18\r \x01(\x04\x12\x12\n\nsendPacket\x18\x0e \x01(\x04\x12\x15\n\rsendUniPacket\x18\x0f \x01(\x04\"=\n\rIfAdminStatus\x12\x16\n\x12IfAdminStatus_DOWN\x10\x00\x12\x14\n\x10IfAdminStatus_UP\x10\x01\x62\x06proto3') ) _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO_IFOPERSTATUS = _descriptor.EnumDescriptor( name='IfOperStatus', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo.IfOperStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='IfOperStatus_DOWN', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='IfOperStatus_UP', index=1, number=1, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=665, serialized_end=723, ) _sym_db.RegisterEnumDescriptor(_IFM_INTERFACES_INTERFACE_IFDYNAMICINFO_IFOPERSTATUS) _IFM_INTERFACES_INTERFACE_IFADMINSTATUS = _descriptor.EnumDescriptor( name='IfAdminStatus', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfAdminStatus', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='IfAdminStatus_DOWN', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='IfAdminStatus_UP', index=1, number=1, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1061, serialized_end=1122, ) _sym_db.RegisterEnumDescriptor(_IFM_INTERFACES_INTERFACE_IFADMINSTATUS) _IFM_INTERFACES_INTERFACE_IFCLEAREDSTAT = _descriptor.Descriptor( name='IfClearedStat', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfClearedStat', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='sendByte', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfClearedStat.sendByte', index=0, number=29, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfClearedStat.sendPacket', index=1, number=36, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=505, serialized_end=558, ) _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO = _descriptor.Descriptor( name='IfDynamicInfo', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ifOperStatus', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo.ifOperStatus', index=0, number=5, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO_IFOPERSTATUS, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=561, serialized_end=723, ) _IFM_INTERFACES_INTERFACE_IFSTATISTICS = _descriptor.Descriptor( name='IfStatistics', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='rcvBroadPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.rcvBroadPacket', index=0, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='rcvDropPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.rcvDropPacket', index=1, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='rcvErrorPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.rcvErrorPacket', index=2, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='rcvMutiPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.rcvMutiPacket', index=3, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='rcvUniPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.rcvUniPacket', index=4, number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='receiveByte', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.receiveByte', index=5, number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='receivePacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.receivePacket', index=6, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendBroadPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendBroadPacket', index=7, number=9, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendByte', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendByte', index=8, number=10, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendDropPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendDropPacket', index=9, number=11, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendErrorPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendErrorPacket', index=10, number=12, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendMutiPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendMutiPacket', index=11, number=13, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendPacket', index=12, number=14, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendUniPacket', full_name='huawei_ifm.Ifm.Interfaces.Interface.IfStatistics.sendUniPacket', index=13, number=15, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=726, serialized_end=1059, ) _IFM_INTERFACES_INTERFACE = _descriptor.Descriptor( name='Interface', full_name='huawei_ifm.Ifm.Interfaces.Interface', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ifAdminStatus', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifAdminStatus', index=0, number=5, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifClearedStat', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifClearedStat', index=1, number=9, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifDynamicInfo', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifDynamicInfo', index=2, number=13, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifIndex', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifIndex', index=3, number=16, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifName', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifName', index=4, number=25, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ifStatistics', full_name='huawei_ifm.Ifm.Interfaces.Interface.ifStatistics', index=5, number=35, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_IFM_INTERFACES_INTERFACE_IFCLEAREDSTAT, _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO, _IFM_INTERFACES_INTERFACE_IFSTATISTICS, ], enum_types=[ _IFM_INTERFACES_INTERFACE_IFADMINSTATUS, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=161, serialized_end=1122, ) _IFM_INTERFACES = _descriptor.Descriptor( name='Interfaces', full_name='huawei_ifm.Ifm.Interfaces', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='interface', full_name='huawei_ifm.Ifm.Interfaces.interface', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_IFM_INTERFACES_INTERFACE, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=89, serialized_end=1122, ) _IFM = _descriptor.Descriptor( name='Ifm', full_name='huawei_ifm.Ifm', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='interfaces', full_name='huawei_ifm.Ifm.interfaces', index=0, number=5, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_IFM_INTERFACES, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=33, serialized_end=1122, ) _IFM_INTERFACES_INTERFACE_IFCLEAREDSTAT.containing_type = _IFM_INTERFACES_INTERFACE _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO.fields_by_name['ifOperStatus'].enum_type = _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO_IFOPERSTATUS _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO.containing_type = _IFM_INTERFACES_INTERFACE _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO_IFOPERSTATUS.containing_type = _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO _IFM_INTERFACES_INTERFACE_IFSTATISTICS.containing_type = _IFM_INTERFACES_INTERFACE _IFM_INTERFACES_INTERFACE.fields_by_name['ifAdminStatus'].enum_type = _IFM_INTERFACES_INTERFACE_IFADMINSTATUS _IFM_INTERFACES_INTERFACE.fields_by_name['ifClearedStat'].message_type = _IFM_INTERFACES_INTERFACE_IFCLEAREDSTAT _IFM_INTERFACES_INTERFACE.fields_by_name['ifDynamicInfo'].message_type = _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO _IFM_INTERFACES_INTERFACE.fields_by_name['ifStatistics'].message_type = _IFM_INTERFACES_INTERFACE_IFSTATISTICS _IFM_INTERFACES_INTERFACE.containing_type = _IFM_INTERFACES _IFM_INTERFACES_INTERFACE_IFADMINSTATUS.containing_type = _IFM_INTERFACES_INTERFACE _IFM_INTERFACES.fields_by_name['interface'].message_type = _IFM_INTERFACES_INTERFACE _IFM_INTERFACES.containing_type = _IFM _IFM.fields_by_name['interfaces'].message_type = _IFM_INTERFACES DESCRIPTOR.message_types_by_name['Ifm'] = _IFM _sym_db.RegisterFileDescriptor(DESCRIPTOR) Ifm = _reflection.GeneratedProtocolMessageType('Ifm', (_message.Message,), { 'Interfaces' : _reflection.GeneratedProtocolMessageType('Interfaces', (_message.Message,), { 'Interface' : _reflection.GeneratedProtocolMessageType('Interface', (_message.Message,), { 'IfClearedStat' : _reflection.GeneratedProtocolMessageType('IfClearedStat', (_message.Message,), { 'DESCRIPTOR' : _IFM_INTERFACES_INTERFACE_IFCLEAREDSTAT, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm.Interfaces.Interface.IfClearedStat) }) , 'IfDynamicInfo' : _reflection.GeneratedProtocolMessageType('IfDynamicInfo', (_message.Message,), { 'DESCRIPTOR' : _IFM_INTERFACES_INTERFACE_IFDYNAMICINFO, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm.Interfaces.Interface.IfDynamicInfo) }) , 'IfStatistics' : _reflection.GeneratedProtocolMessageType('IfStatistics', (_message.Message,), { 'DESCRIPTOR' : _IFM_INTERFACES_INTERFACE_IFSTATISTICS, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm.Interfaces.Interface.IfStatistics) }) , 'DESCRIPTOR' : _IFM_INTERFACES_INTERFACE, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm.Interfaces.Interface) }) , 'DESCRIPTOR' : _IFM_INTERFACES, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm.Interfaces) }) , 'DESCRIPTOR' : _IFM, '__module__' : 'huawei_ifm_pb2' # @@protoc_insertion_point(class_scope:huawei_ifm.Ifm) }) _sym_db.RegisterMessage(Ifm) _sym_db.RegisterMessage(Ifm.Interfaces) _sym_db.RegisterMessage(Ifm.Interfaces.Interface) _sym_db.RegisterMessage(Ifm.Interfaces.Interface.IfClearedStat) _sym_db.RegisterMessage(Ifm.Interfaces.Interface.IfDynamicInfo) _sym_db.RegisterMessage(Ifm.Interfaces.Interface.IfStatistics) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/huawei_telemetry_pb2.py0000755000175000017500000002120714354105275024170 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: huawei-telemetry.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='huawei-telemetry.proto', package='telemetry', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x16huawei-telemetry.proto\x12\ttelemetry\"\x99\x02\n\tTelemetry\x12\x13\n\x0bnode_id_str\x18\x01 \x01(\t\x12\x1b\n\x13subscription_id_str\x18\x02 \x01(\t\x12\x13\n\x0bsensor_path\x18\x03 \x01(\t\x12\x15\n\rcollection_id\x18\x04 \x01(\x04\x12\x1d\n\x15\x63ollection_start_time\x18\x05 \x01(\x04\x12\x15\n\rmsg_timestamp\x18\x06 \x01(\x04\x12.\n\x08\x64\x61ta_gpb\x18\x07 \x01(\x0b\x32\x1c.telemetry.TelemetryGPBTable\x12\x1b\n\x13\x63ollection_end_time\x18\x08 \x01(\x04\x12\x16\n\x0e\x63urrent_period\x18\t \x01(\r\x12\x13\n\x0b\x65xcept_desc\x18\n \x01(\t\"<\n\x11TelemetryGPBTable\x12\'\n\x03row\x18\x01 \x03(\x0b\x32\x1a.telemetry.TelemetryRowGPB\"5\n\x0fTelemetryRowGPB\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0f\n\x07\x63ontent\x18\x0b \x01(\x0c\x62\x06proto3') ) _TELEMETRY = _descriptor.Descriptor( name='Telemetry', full_name='telemetry.Telemetry', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='node_id_str', full_name='telemetry.Telemetry.node_id_str', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='subscription_id_str', full_name='telemetry.Telemetry.subscription_id_str', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sensor_path', full_name='telemetry.Telemetry.sensor_path', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='collection_id', full_name='telemetry.Telemetry.collection_id', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='collection_start_time', full_name='telemetry.Telemetry.collection_start_time', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='msg_timestamp', full_name='telemetry.Telemetry.msg_timestamp', index=5, number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='data_gpb', full_name='telemetry.Telemetry.data_gpb', index=6, number=7, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='collection_end_time', full_name='telemetry.Telemetry.collection_end_time', index=7, number=8, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='current_period', full_name='telemetry.Telemetry.current_period', index=8, number=9, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='except_desc', full_name='telemetry.Telemetry.except_desc', index=9, number=10, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=38, serialized_end=319, ) _TELEMETRYGPBTABLE = _descriptor.Descriptor( name='TelemetryGPBTable', full_name='telemetry.TelemetryGPBTable', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='row', full_name='telemetry.TelemetryGPBTable.row', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=321, serialized_end=381, ) _TELEMETRYROWGPB = _descriptor.Descriptor( name='TelemetryRowGPB', full_name='telemetry.TelemetryRowGPB', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='timestamp', full_name='telemetry.TelemetryRowGPB.timestamp', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='content', full_name='telemetry.TelemetryRowGPB.content', index=1, number=11, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=383, serialized_end=436, ) _TELEMETRY.fields_by_name['data_gpb'].message_type = _TELEMETRYGPBTABLE _TELEMETRYGPBTABLE.fields_by_name['row'].message_type = _TELEMETRYROWGPB DESCRIPTOR.message_types_by_name['Telemetry'] = _TELEMETRY DESCRIPTOR.message_types_by_name['TelemetryGPBTable'] = _TELEMETRYGPBTABLE DESCRIPTOR.message_types_by_name['TelemetryRowGPB'] = _TELEMETRYROWGPB _sym_db.RegisterFileDescriptor(DESCRIPTOR) Telemetry = _reflection.GeneratedProtocolMessageType('Telemetry', (_message.Message,), { 'DESCRIPTOR' : _TELEMETRY, '__module__' : 'huawei_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.Telemetry) }) _sym_db.RegisterMessage(Telemetry) TelemetryGPBTable = _reflection.GeneratedProtocolMessageType('TelemetryGPBTable', (_message.Message,), { 'DESCRIPTOR' : _TELEMETRYGPBTABLE, '__module__' : 'huawei_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.TelemetryGPBTable) }) _sym_db.RegisterMessage(TelemetryGPBTable) TelemetryRowGPB = _reflection.GeneratedProtocolMessageType('TelemetryRowGPB', (_message.Message,), { 'DESCRIPTOR' : _TELEMETRYROWGPB, '__module__' : 'huawei_telemetry_pb2' # @@protoc_insertion_point(class_scope:telemetry.TelemetryRowGPB) }) _sym_db.RegisterMessage(TelemetryRowGPB) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/cisco_grpc_dialout_pb2_grpc.py0000755000175000017500000000310614354105275025461 0ustar paolopaolo# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! import grpc import cisco_grpc_dialout_pb2 as cisco__grpc__dialout__pb2 class gRPCMdtDialoutStub(object): """gRPCMdtDialout defines service used for client-side streaming pushing MdtDialoutArgs. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.MdtDialout = channel.stream_stream( '/mdt_dialout.gRPCMdtDialout/MdtDialout', request_serializer=cisco__grpc__dialout__pb2.MdtDialoutArgs.SerializeToString, response_deserializer=cisco__grpc__dialout__pb2.MdtDialoutArgs.FromString, ) class gRPCMdtDialoutServicer(object): """gRPCMdtDialout defines service used for client-side streaming pushing MdtDialoutArgs. """ def MdtDialout(self, request_iterator, context): # missing associated documentation comment in .proto file pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_gRPCMdtDialoutServicer_to_server(servicer, server): rpc_method_handlers = { 'MdtDialout': grpc.stream_stream_rpc_method_handler( servicer.MdtDialout, request_deserializer=cisco__grpc__dialout__pb2.MdtDialoutArgs.FromString, response_serializer=cisco__grpc__dialout__pb2.MdtDialoutArgs.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'mdt_dialout.gRPCMdtDialout', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) pmacct-1.7.8/telemetry/decoders/v3/protos/gnmi.proto0000644000175000017500000005245314354105275021522 0ustar paolopaolo// // Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // syntax = "proto3"; import "google/protobuf/any.proto"; import "google/protobuf/descriptor.proto"; import "gnmi_ext.proto"; // Package gNMI defines a service specification for the gRPC Network Management // Interface. This interface is defined to be a standard interface via which // a network management system ("client") can subscribe to state values, // retrieve snapshots of state information, and manipulate the state of a data // tree supported by a device ("target"). // // This document references the gNMI Specification which can be found at // http://github.com/openconfig/reference/blob/master/rpc/gnmi package gnmi; // Define a protobuf FileOption that defines the gNMI service version. extend google.protobuf.FileOptions { // The gNMI service semantic version. string gnmi_service = 1001; } // gNMI_service is the current version of the gNMI service, returned through // the Capabilities RPC. option (gnmi_service) = "0.7.0"; service gNMI { // Capabilities allows the client to retrieve the set of capabilities that // is supported by the target. This allows the target to validate the // service version that is implemented and retrieve the set of models that // the target supports. The models can then be specified in subsequent RPCs // to restrict the set of data that is utilized. // Reference: gNMI Specification Section 3.2 rpc Capabilities(CapabilityRequest) returns (CapabilityResponse); // Retrieve a snapshot of data from the target. A Get RPC requests that the // target snapshots a subset of the data tree as specified by the paths // included in the message and serializes this to be returned to the // client using the specified encoding. // Reference: gNMI Specification Section 3.3 rpc Get(GetRequest) returns (GetResponse); // Set allows the client to modify the state of data on the target. The // paths to modified along with the new values that the client wishes // to set the value to. // Reference: gNMI Specification Section 3.4 rpc Set(SetRequest) returns (SetResponse); // Subscribe allows a client to request the target to send it values // of particular paths within the data tree. These values may be streamed // at a particular cadence (STREAM), sent one off on a long-lived channel // (POLL), or sent as a one-off retrieval (ONCE). // Reference: gNMI Specification Section 3.5 rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeResponse); } // Notification is a re-usable message that is used to encode data from the // target to the client. A Notification carries two types of changes to the data // tree: // - Deleted values (delete) - a set of paths that have been removed from the // data tree. // - Updated values (update) - a set of path-value pairs indicating the path // whose value has changed in the data tree. // Reference: gNMI Specification Section 2.1 message Notification { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. Path prefix = 2; // Prefix used for paths in the message. // An alias for the path specified in the prefix field. // Reference: gNMI Specification Section 2.4.2 string alias = 3; repeated Update update = 4; // Data elements that have changed values. repeated Path delete = 5; // Data elements that have been deleted. // This notification contains a set of paths that are always updated together // referenced by a globally unique prefix. bool atomic = 6; } // Update is a re-usable message that is used to store a particular Path, // Value pair. // Reference: gNMI Specification Section 2.1 message Update { Path path = 1; // The path (key) for the update. Value value = 2 [deprecated=true]; // The value (value) for the update. TypedValue val = 3; // The explicitly typed update value. uint32 duplicates = 4; // Number of coalesced duplicates. } // TypedValue is used to encode a value being sent between the client and // target (originated by either entity). message TypedValue { // One of the fields within the val oneof is populated with the value // of the update. The type of the value being included in the Update // determines which field should be populated. In the case that the // encoding is a particular form of the base protobuf type, a specific // field is used to store the value (e.g., json_val). oneof value { string string_val = 1; // String value. int64 int_val = 2; // Integer value. uint64 uint_val = 3; // Unsigned integer value. bool bool_val = 4; // Bool value. bytes bytes_val = 5; // Arbitrary byte sequence value. float float_val = 6; // Floating point value. Decimal64 decimal_val = 7; // Decimal64 encoded value. ScalarArray leaflist_val = 8; // Mixed type scalar array value. google.protobuf.Any any_val = 9; // protobuf.Any encoded bytes. bytes json_val = 10; // JSON-encoded text. bytes json_ietf_val = 11; // JSON-encoded text per RFC7951. string ascii_val = 12; // Arbitrary ASCII text. // Protobuf binary encoded bytes. The message type is not included. // See the specification at // github.com/openconfig/reference/blob/master/rpc/gnmi/protobuf-vals.md // for a complete specification. bytes proto_bytes = 13; } } // Path encodes a data tree path as a series of repeated strings, with // each element of the path representing a data tree node name and the // associated attributes. // Reference: gNMI Specification Section 2.2.2. message Path { // Elements of the path are no longer encoded as a string, but rather within // the elem field as a PathElem message. repeated string element = 1 [deprecated=true]; string origin = 2; // Label to disambiguate path. repeated PathElem elem = 3; // Elements of the path. string target = 4; // The name of the target // (Sec. 2.2.2.1) } // PathElem encodes an element of a gNMI path, along with any attributes (keys) // that may be associated with it. // Reference: gNMI Specification Section 2.2.2. message PathElem { string name = 1; // The name of the element in the path. map key = 2; // Map of key (attribute) name to value. } // Value encodes a data tree node's value - along with the way in which // the value is encoded. This message is deprecated by gNMI 0.3.0. // Reference: gNMI Specification Section 2.2.3. message Value { option deprecated = true; bytes value = 1; // Value of the variable being transmitted. Encoding type = 2; // Encoding used for the value field. } // Encoding defines the value encoding formats that are supported by the gNMI // protocol. These encodings are used by both the client (when sending Set // messages to modify the state of the target) and the target when serializing // data to be returned to the client (in both Subscribe and Get RPCs). // Reference: gNMI Specification Section 2.3 enum Encoding { JSON = 0; // JSON encoded text. BYTES = 1; // Arbitrarily encoded bytes. PROTO = 2; // Encoded according to out-of-band agreed Protobuf. ASCII = 3; // ASCII text of an out-of-band agreed format. JSON_IETF = 4; // JSON encoded text as per RFC7951. } // Error message previously utilised to return errors to the client. Deprecated // in favour of using the google.golang.org/genproto/googleapis/rpc/status // message in the RPC response. // Reference: gNMI Specification Section 2.5 message Error { option deprecated = true; uint32 code = 1; // Canonical gRPC error code. string message = 2; // Human readable error. google.protobuf.Any data = 3; // Optional additional information. } // Decimal64 is used to encode a fixed precision decimal number. The value // is expressed as a set of digits with the precision specifying the // number of digits following the decimal point in the digit set. message Decimal64 { int64 digits = 1; // Set of digits. uint32 precision = 2; // Number of digits following the decimal point. } // ScalarArray is used to encode a mixed-type array of values. message ScalarArray { // The set of elements within the array. Each TypedValue message should // specify only elements that have a field identifier of 1-7 (i.e., the // values are scalar values). repeated TypedValue element = 1; } // SubscribeRequest is the message sent by the client to the target when // initiating a subscription to a set of paths within the data tree. The // request field must be populated and the initial message must specify a // SubscriptionList to initiate a subscription. The message is subsequently // used to define aliases or trigger polled data to be sent by the target. // Reference: gNMI Specification Section 3.5.1.1 message SubscribeRequest { oneof request { SubscriptionList subscribe = 1; // Specify the paths within a subscription. Poll poll = 3; // Trigger a polled update. AliasList aliases = 4; // Aliases to be created. } // Extension messages associated with the SubscribeRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; } // Poll is sent within a SubscribeRequest to trigger the device to // send telemetry updates for the paths that are associated with the // subscription. // Reference: gNMI Specification Section Section 3.5.1.4 message Poll { } // SubscribeResponse is the message used by the target within a Subscribe RPC. // The target includes a Notification message which is used to transmit values // of the path(s) that are associated with the subscription. The same message // is to indicate that the target has sent all data values once (is // synchronized). // Reference: gNMI Specification Section 3.5.1.4 message SubscribeResponse { oneof response { Notification update = 1; // Changed or sampled value for a path. // Indicate target has sent all values associated with the subscription // at least once. bool sync_response = 3; // Deprecated in favour of google.golang.org/genproto/googleapis/rpc/status Error error = 4 [deprecated=true]; } // Extension messages associated with the SubscribeResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; } // SubscriptionList is used within a Subscribe message to specify the list of // paths that the client wishes to subscribe to. The message consists of a // list of (possibly prefixed) paths, and options that relate to the // subscription. // Reference: gNMI Specification Section 3.5.1.2 message SubscriptionList { Path prefix = 1; // Prefix used for paths. repeated Subscription subscription = 2; // Set of subscriptions to create. // Whether target defined aliases are allowed within the subscription. bool use_aliases = 3; QOSMarking qos = 4; // DSCP marking to be used. // Mode of the subscription. enum Mode { STREAM = 0; // Values streamed by the target (Sec. 3.5.1.5.2). ONCE = 1; // Values sent once-off by the target (Sec. 3.5.1.5.1). POLL = 2; // Values sent in response to a poll request (Sec. 3.5.1.5.3). } Mode mode = 5; // Whether elements of the schema that are marked as eligible for aggregation // should be aggregated or not. bool allow_aggregation = 6; // The set of schemas that define the elements of the data tree that should // be sent by the target. repeated ModelData use_models = 7; // The encoding that the target should use within the Notifications generated // corresponding to the SubscriptionList. Encoding encoding = 8; // An optional field to specify that only updates to current state should be // sent to a client. If set, the initial state is not sent to the client but // rather only the sync message followed by any subsequent updates to the // current state. For ONCE and POLL modes, this causes the server to send only // the sync message (Sec. 3.5.2.3). bool updates_only = 9; } // Subscription is a single request within a SubscriptionList. The path // specified is interpreted (along with the prefix) as the elements of the data // tree that the client is subscribing to. The mode determines how the target // should trigger updates to be sent. // Reference: gNMI Specification Section 3.5.1.3 message Subscription { Path path = 1; // The data tree path. SubscriptionMode mode = 2; // Subscription mode to be used. uint64 sample_interval = 3; // ns between samples in SAMPLE mode. // Indicates whether values that have not changed should be sent in a SAMPLE // subscription. bool suppress_redundant = 4; // Specifies the maximum allowable silent period in nanoseconds when // suppress_redundant is in use. The target should send a value at least once // in the period specified. uint64 heartbeat_interval = 5; } // SubscriptionMode is the mode of the subscription, specifying how the // target must return values in a subscription. // Reference: gNMI Specification Section 3.5.1.3 enum SubscriptionMode { TARGET_DEFINED = 0; // The target selects the relevant mode for each element. ON_CHANGE = 1; // The target sends an update on element value change. SAMPLE = 2; // The target samples values according to the interval. } // QOSMarking specifies the DSCP value to be set on transmitted telemetry // updates from the target. // Reference: gNMI Specification Section 3.5.1.2 message QOSMarking { uint32 marking = 1; } // Alias specifies a data tree path, and an associated string which defines an // alias which is to be used for this path in the context of the RPC. The alias // is specified as a string which is prefixed with "#" to disambiguate it from // data tree element paths. // Reference: gNMI Specification Section 2.4.2 message Alias { Path path = 1; // The path to be aliased. string alias = 2; // The alias value, a string prefixed by "#". } // AliasList specifies a list of aliases. It is used in a SubscribeRequest for // a client to create a set of aliases that the target is to utilize. // Reference: gNMI Specification Section 3.5.1.6 message AliasList { repeated Alias alias = 1; // The set of aliases to be created. } // SetRequest is sent from a client to the target to update values in the data // tree. Paths are either deleted by the client, or modified by means of being // updated, or replaced. Where a replace is used, unspecified values are // considered to be replaced, whereas when update is used the changes are // considered to be incremental. The set of changes that are specified within // a single SetRequest are considered to be a transaction. // Reference: gNMI Specification Section 3.4.1 message SetRequest { Path prefix = 1; // Prefix used for paths in the message. repeated Path delete = 2; // Paths to be deleted from the data tree. repeated Update replace = 3; // Updates specifying elements to be replaced. repeated Update update = 4; // Updates specifying elements to updated. // Extension messages associated with the SetRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; } // SetResponse is the response to a SetRequest, sent from the target to the // client. It reports the result of the modifications to the data tree that were // specified by the client. Errors for this RPC should be reported using the // https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto // message in the RPC return. The gnmi.Error message can be used to add additional // details where required. // Reference: gNMI Specification Section 3.4.2 message SetResponse { Path prefix = 1; // Prefix used for paths. // A set of responses specifying the result of the operations specified in // the SetRequest. repeated UpdateResult response = 2; Error message = 3 [deprecated=true]; // The overall status of the transaction. int64 timestamp = 4; // Timestamp of transaction (ns since epoch). // Extension messages associated with the SetResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; } // UpdateResult is used within the SetResponse message to communicate the // result of an operation specified within a SetRequest message. // Reference: gNMI Specification Section 3.4.2 message UpdateResult { // The operation that was associated with the Path specified. enum Operation { INVALID = 0; DELETE = 1; // The result relates to a delete of Path. REPLACE = 2; // The result relates to a replace of Path. UPDATE = 3; // The result relates to an update of Path. } // Deprecated timestamp for the UpdateResult, this field has been // replaced by the timestamp within the SetResponse message, since // all mutations effected by a set should be applied as a single // transaction. int64 timestamp = 1 [deprecated=true]; Path path = 2; // Path associated with the update. Error message = 3 [deprecated=true]; // Status of the update operation. Operation op = 4; // Update operation type. } // GetRequest is sent when a client initiates a Get RPC. It is used to specify // the set of data elements for which the target should return a snapshot of // data. The use_models field specifies the set of schema modules that are to // be used by the target - where use_models is not specified then the target // must use all schema models that it has. // Reference: gNMI Specification Section 3.3.1 message GetRequest { Path prefix = 1; // Prefix used for paths. repeated Path path = 2; // Paths requested by the client. // Type of elements within the data tree. enum DataType { ALL = 0; // All data elements. CONFIG = 1; // Config (rw) only elements. STATE = 2; // State (ro) only elements. // Data elements marked in the schema as operational. This refers to data // elements whose value relates to the state of processes or interactions // running on the device. OPERATIONAL = 3; } DataType type = 3; // The type of data being requested. Encoding encoding = 5; // Encoding to be used. repeated ModelData use_models = 6; // The schema models to be used. // Extension messages associated with the GetRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 7; } // GetResponse is used by the target to respond to a GetRequest from a client. // The set of Notifications corresponds to the data values that are requested // by the client in the GetRequest. // Reference: gNMI Specification Section 3.3.2 message GetResponse { repeated Notification notification = 1; // Data values. Error error = 2 [deprecated=true]; // Errors that occurred in the Get. // Extension messages associated with the GetResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 3; } // CapabilityRequest is sent by the client in the Capabilities RPC to request // that the target reports its capabilities. // Reference: gNMI Specification Section 3.2.1 message CapabilityRequest { // Extension messages associated with the CapabilityRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 1; } // CapabilityResponse is used by the target to report its capabilities to the // client within the Capabilities RPC. // Reference: gNMI Specification Section 3.2.2 message CapabilityResponse { repeated ModelData supported_models = 1; // Supported schema models. repeated Encoding supported_encodings = 2; // Supported encodings. string gNMI_version = 3; // Supported gNMI version. // Extension messages associated with the CapabilityResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 4; } // ModelData is used to describe a set of schema modules. It can be used in a // CapabilityResponse where a target reports the set of modules that it // supports, and within the SubscribeRequest and GetRequest messages to specify // the set of models from which data tree elements should be reported. // Reference: gNMI Specification Section 3.2.3 message ModelData { string name = 1; // Name of the model. string organization = 2; // Organization publishing the model. string version = 3; // Semantic version of the model. } pmacct-1.7.8/telemetry/decoders/v3/protos/cisco_grpc_dialout.proto0000755000175000017500000000074414354105275024423 0ustar paolopaolosyntax = "proto3"; // Package implements gRPC Model Driven Telemetry service package mdt_dialout; // gRPCMdtDialout defines service used for client-side streaming pushing MdtDialoutArgs. service gRPCMdtDialout { rpc MdtDialout(stream MdtDialoutArgs) returns(stream MdtDialoutArgs) {}; } // MdtDialoutArgs is the content pushed to the server message MdtDialoutArgs { int64 ReqId = 1; // data carries the payload content. bytes data = 2; string errors = 3; } pmacct-1.7.8/telemetry/decoders/v3/protos/huawei_devm_pb2.py0000755000175000017500000006744414354105275023126 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: huawei-devm.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='huawei-devm.proto', package='huawei_devm', syntax='proto3', serialized_options=None, serialized_pb=_b('\n\x11huawei-devm.proto\x12\x0bhuawei_devm\"\xc6\n\n\x04\x44\x65vm\x12,\n\x08\x63puInfos\x18\x05 \x01(\x0b\x32\x1a.huawei_devm.Devm.CpuInfos\x12\x38\n\x0e\x65thPortStaStss\x18\x07 \x01(\x0b\x32 .huawei_devm.Devm.EthPortStaStss\x12\x32\n\x0bmemoryInfos\x18\x0f \x01(\x0b\x32\x1d.huawei_devm.Devm.MemoryInfos\x12&\n\x05ports\x18\x14 \x01(\x0b\x32\x17.huawei_devm.Devm.Ports\x1a\xcd\x01\n\x08\x43puInfos\x12\x33\n\x07\x63puInfo\x18\x01 \x03(\x0b\x32\".huawei_devm.Devm.CpuInfos.CpuInfo\x1a\x8b\x01\n\x07\x43puInfo\x12\x10\n\x08\x65ntIndex\x18\x01 \x01(\r\x12\x10\n\x08interval\x18\x02 \x01(\r\x12\x17\n\x0fovloadThreshold\x18\x03 \x01(\r\x12\x10\n\x08position\x18\x04 \x01(\t\x12\x16\n\x0esystemCpuUsage\x18\x05 \x01(\r\x12\x19\n\x11unovloadThreshold\x18\x06 \x01(\r\x1a\xca\x01\n\x0e\x45thPortStaStss\x12\x45\n\rethPortStaSts\x18\x01 \x03(\x0b\x32..huawei_devm.Devm.EthPortStaStss.EthPortStaSts\x1aq\n\rEthPortStaSts\x12\x0e\n\x06ifName\x18\x01 \x01(\r\x12\x13\n\x0breceiveByte\x18\x02 \x01(\x04\x12\x15\n\rreceivePacket\x18\x03 \x01(\x04\x12\x10\n\x08sendByte\x18\x04 \x01(\x04\x12\x12\n\nsendPacket\x18\x05 \x01(\x04\x1a\xcd\x03\n\x0bMemoryInfos\x12<\n\nmemoryInfo\x18\x01 \x03(\x0b\x32(.huawei_devm.Devm.MemoryInfos.MemoryInfo\x1a\xff\x02\n\nMemoryInfo\x12\x14\n\x0c\x64oMemoryFree\x18\x01 \x01(\r\x12\x15\n\rdoMemoryTotal\x18\x02 \x01(\r\x12\x15\n\rdoMemoryUsage\x18\x03 \x01(\r\x12\x13\n\x0b\x64oMemoryUse\x18\x04 \x01(\r\x12\x10\n\x08\x65ntIndex\x18\x05 \x01(\r\x12\x14\n\x0cosMemoryFree\x18\x06 \x01(\r\x12\x15\n\rosMemoryTotal\x18\x07 \x01(\r\x12\x15\n\rosMemoryUsage\x18\x08 \x01(\r\x12\x13\n\x0bosMemoryUse\x18\t \x01(\r\x12\x17\n\x0fovloadThreshold\x18\n \x01(\r\x12\x10\n\x08position\x18\x0b \x01(\t\x12\x18\n\x10simpleMemoryFree\x18\x0c \x01(\r\x12\x19\n\x11simpleMemoryTotal\x18\r \x01(\r\x12\x19\n\x11simpleMemoryUsage\x18\x0e \x01(\r\x12\x17\n\x0fsimpleMemoryUse\x18\x0f \x01(\r\x12\x19\n\x11unovloadThreshold\x18\x10 \x01(\r\x1a\x8c\x02\n\x05Ports\x12*\n\x04port\x18\x01 \x03(\x0b\x32\x1c.huawei_devm.Devm.Ports.Port\x1a\xd6\x01\n\x04Port\x12=\n\x0bopticalInfo\x18\x08 \x01(\x0b\x32(.huawei_devm.Devm.Ports.Port.OpticalInfo\x1a\x8e\x01\n\x0bOpticalInfo\x12\x13\n\x0b\x62iasCurrent\x18\x01 \x01(\t\x12\x10\n\x08manuDate\x18\x02 \x01(\t\x12\x10\n\x08position\x18\x0f \x01(\t\x12\x0f\n\x07rxPower\x18\x10 \x01(\t\x12\x13\n\x0btemperature\x18\x11 \x01(\t\x12\x0f\n\x07txPower\x18\x14 \x01(\t\x12\x0f\n\x07voltage\x18\x17 \x01(\tb\x06proto3') ) _DEVM_CPUINFOS_CPUINFO = _descriptor.Descriptor( name='CpuInfo', full_name='huawei_devm.Devm.CpuInfos.CpuInfo', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='entIndex', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.entIndex', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='interval', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.interval', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ovloadThreshold', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.ovloadThreshold', index=2, number=3, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='position', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.position', index=3, number=4, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='systemCpuUsage', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.systemCpuUsage', index=4, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='unovloadThreshold', full_name='huawei_devm.Devm.CpuInfos.CpuInfo.unovloadThreshold', index=5, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=306, serialized_end=445, ) _DEVM_CPUINFOS = _descriptor.Descriptor( name='CpuInfos', full_name='huawei_devm.Devm.CpuInfos', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='cpuInfo', full_name='huawei_devm.Devm.CpuInfos.cpuInfo', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_CPUINFOS_CPUINFO, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=240, serialized_end=445, ) _DEVM_ETHPORTSTASTSS_ETHPORTSTASTS = _descriptor.Descriptor( name='EthPortStaSts', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ifName', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts.ifName', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='receiveByte', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts.receiveByte', index=1, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='receivePacket', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts.receivePacket', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendByte', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts.sendByte', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sendPacket', full_name='huawei_devm.Devm.EthPortStaStss.EthPortStaSts.sendPacket', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=537, serialized_end=650, ) _DEVM_ETHPORTSTASTSS = _descriptor.Descriptor( name='EthPortStaStss', full_name='huawei_devm.Devm.EthPortStaStss', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ethPortStaSts', full_name='huawei_devm.Devm.EthPortStaStss.ethPortStaSts', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_ETHPORTSTASTSS_ETHPORTSTASTS, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=448, serialized_end=650, ) _DEVM_MEMORYINFOS_MEMORYINFO = _descriptor.Descriptor( name='MemoryInfo', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='doMemoryFree', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.doMemoryFree', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='doMemoryTotal', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.doMemoryTotal', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='doMemoryUsage', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.doMemoryUsage', index=2, number=3, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='doMemoryUse', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.doMemoryUse', index=3, number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='entIndex', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.entIndex', index=4, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='osMemoryFree', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.osMemoryFree', index=5, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='osMemoryTotal', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.osMemoryTotal', index=6, number=7, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='osMemoryUsage', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.osMemoryUsage', index=7, number=8, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='osMemoryUse', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.osMemoryUse', index=8, number=9, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ovloadThreshold', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.ovloadThreshold', index=9, number=10, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='position', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.position', index=10, number=11, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='simpleMemoryFree', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.simpleMemoryFree', index=11, number=12, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='simpleMemoryTotal', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.simpleMemoryTotal', index=12, number=13, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='simpleMemoryUsage', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.simpleMemoryUsage', index=13, number=14, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='simpleMemoryUse', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.simpleMemoryUse', index=14, number=15, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='unovloadThreshold', full_name='huawei_devm.Devm.MemoryInfos.MemoryInfo.unovloadThreshold', index=15, number=16, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=731, serialized_end=1114, ) _DEVM_MEMORYINFOS = _descriptor.Descriptor( name='MemoryInfos', full_name='huawei_devm.Devm.MemoryInfos', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='memoryInfo', full_name='huawei_devm.Devm.MemoryInfos.memoryInfo', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_MEMORYINFOS_MEMORYINFO, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=653, serialized_end=1114, ) _DEVM_PORTS_PORT_OPTICALINFO = _descriptor.Descriptor( name='OpticalInfo', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='biasCurrent', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.biasCurrent', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='manuDate', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.manuDate', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='position', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.position', index=2, number=15, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='rxPower', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.rxPower', index=3, number=16, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='temperature', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.temperature', index=4, number=17, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='txPower', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.txPower', index=5, number=20, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='voltage', full_name='huawei_devm.Devm.Ports.Port.OpticalInfo.voltage', index=6, number=23, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1243, serialized_end=1385, ) _DEVM_PORTS_PORT = _descriptor.Descriptor( name='Port', full_name='huawei_devm.Devm.Ports.Port', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='opticalInfo', full_name='huawei_devm.Devm.Ports.Port.opticalInfo', index=0, number=8, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_PORTS_PORT_OPTICALINFO, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1171, serialized_end=1385, ) _DEVM_PORTS = _descriptor.Descriptor( name='Ports', full_name='huawei_devm.Devm.Ports', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='port', full_name='huawei_devm.Devm.Ports.port', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_PORTS_PORT, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1117, serialized_end=1385, ) _DEVM = _descriptor.Descriptor( name='Devm', full_name='huawei_devm.Devm', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='cpuInfos', full_name='huawei_devm.Devm.cpuInfos', index=0, number=5, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ethPortStaStss', full_name='huawei_devm.Devm.ethPortStaStss', index=1, number=7, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='memoryInfos', full_name='huawei_devm.Devm.memoryInfos', index=2, number=15, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ports', full_name='huawei_devm.Devm.ports', index=3, number=20, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_DEVM_CPUINFOS, _DEVM_ETHPORTSTASTSS, _DEVM_MEMORYINFOS, _DEVM_PORTS, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=35, serialized_end=1385, ) _DEVM_CPUINFOS_CPUINFO.containing_type = _DEVM_CPUINFOS _DEVM_CPUINFOS.fields_by_name['cpuInfo'].message_type = _DEVM_CPUINFOS_CPUINFO _DEVM_CPUINFOS.containing_type = _DEVM _DEVM_ETHPORTSTASTSS_ETHPORTSTASTS.containing_type = _DEVM_ETHPORTSTASTSS _DEVM_ETHPORTSTASTSS.fields_by_name['ethPortStaSts'].message_type = _DEVM_ETHPORTSTASTSS_ETHPORTSTASTS _DEVM_ETHPORTSTASTSS.containing_type = _DEVM _DEVM_MEMORYINFOS_MEMORYINFO.containing_type = _DEVM_MEMORYINFOS _DEVM_MEMORYINFOS.fields_by_name['memoryInfo'].message_type = _DEVM_MEMORYINFOS_MEMORYINFO _DEVM_MEMORYINFOS.containing_type = _DEVM _DEVM_PORTS_PORT_OPTICALINFO.containing_type = _DEVM_PORTS_PORT _DEVM_PORTS_PORT.fields_by_name['opticalInfo'].message_type = _DEVM_PORTS_PORT_OPTICALINFO _DEVM_PORTS_PORT.containing_type = _DEVM_PORTS _DEVM_PORTS.fields_by_name['port'].message_type = _DEVM_PORTS_PORT _DEVM_PORTS.containing_type = _DEVM _DEVM.fields_by_name['cpuInfos'].message_type = _DEVM_CPUINFOS _DEVM.fields_by_name['ethPortStaStss'].message_type = _DEVM_ETHPORTSTASTSS _DEVM.fields_by_name['memoryInfos'].message_type = _DEVM_MEMORYINFOS _DEVM.fields_by_name['ports'].message_type = _DEVM_PORTS DESCRIPTOR.message_types_by_name['Devm'] = _DEVM _sym_db.RegisterFileDescriptor(DESCRIPTOR) Devm = _reflection.GeneratedProtocolMessageType('Devm', (_message.Message,), { 'CpuInfos' : _reflection.GeneratedProtocolMessageType('CpuInfos', (_message.Message,), { 'CpuInfo' : _reflection.GeneratedProtocolMessageType('CpuInfo', (_message.Message,), { 'DESCRIPTOR' : _DEVM_CPUINFOS_CPUINFO, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.CpuInfos.CpuInfo) }) , 'DESCRIPTOR' : _DEVM_CPUINFOS, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.CpuInfos) }) , 'EthPortStaStss' : _reflection.GeneratedProtocolMessageType('EthPortStaStss', (_message.Message,), { 'EthPortStaSts' : _reflection.GeneratedProtocolMessageType('EthPortStaSts', (_message.Message,), { 'DESCRIPTOR' : _DEVM_ETHPORTSTASTSS_ETHPORTSTASTS, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.EthPortStaStss.EthPortStaSts) }) , 'DESCRIPTOR' : _DEVM_ETHPORTSTASTSS, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.EthPortStaStss) }) , 'MemoryInfos' : _reflection.GeneratedProtocolMessageType('MemoryInfos', (_message.Message,), { 'MemoryInfo' : _reflection.GeneratedProtocolMessageType('MemoryInfo', (_message.Message,), { 'DESCRIPTOR' : _DEVM_MEMORYINFOS_MEMORYINFO, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.MemoryInfos.MemoryInfo) }) , 'DESCRIPTOR' : _DEVM_MEMORYINFOS, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.MemoryInfos) }) , 'Ports' : _reflection.GeneratedProtocolMessageType('Ports', (_message.Message,), { 'Port' : _reflection.GeneratedProtocolMessageType('Port', (_message.Message,), { 'OpticalInfo' : _reflection.GeneratedProtocolMessageType('OpticalInfo', (_message.Message,), { 'DESCRIPTOR' : _DEVM_PORTS_PORT_OPTICALINFO, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.Ports.Port.OpticalInfo) }) , 'DESCRIPTOR' : _DEVM_PORTS_PORT, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.Ports.Port) }) , 'DESCRIPTOR' : _DEVM_PORTS, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm.Ports) }) , 'DESCRIPTOR' : _DEVM, '__module__' : 'huawei_devm_pb2' # @@protoc_insertion_point(class_scope:huawei_devm.Devm) }) _sym_db.RegisterMessage(Devm) _sym_db.RegisterMessage(Devm.CpuInfos) _sym_db.RegisterMessage(Devm.CpuInfos.CpuInfo) _sym_db.RegisterMessage(Devm.EthPortStaStss) _sym_db.RegisterMessage(Devm.EthPortStaStss.EthPortStaSts) _sym_db.RegisterMessage(Devm.MemoryInfos) _sym_db.RegisterMessage(Devm.MemoryInfos.MemoryInfo) _sym_db.RegisterMessage(Devm.Ports) _sym_db.RegisterMessage(Devm.Ports.Port) _sym_db.RegisterMessage(Devm.Ports.Port.OpticalInfo) # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/huawei-grpc-dialout.proto0000755000175000017500000000035514354105275024437 0ustar paolopaolosyntax = "proto3"; package huawei_dialout; service gRPCDataservice { rpc dataPublish(stream serviceArgs) returns(stream serviceArgs) {}; } message serviceArgs { int64 ReqId = 1; bytes data = 2; string errors = 3; } pmacct-1.7.8/telemetry/decoders/v3/protos/gnmi_ext.proto0000644000175000017500000000510014354105275022365 0ustar paolopaolo// // Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // syntax = "proto3"; // Package gnmi_ext defines a set of extensions messages which can be optionally // included with the request and response messages of gNMI RPCs. A set of // well-known extensions are defined within this file, along with a registry for // extensions defined outside of this package. package gnmi_ext; // The Extension message contains a single gNMI extension. message Extension { oneof ext { RegisteredExtension registered_ext = 1; // A registered extension. // Well known extensions. MasterArbitration master_arbitration = 2; // Master arbitration extension. } } // The RegisteredExtension message defines an extension which is defined outside // of this file. message RegisteredExtension { ExtensionID id = 1; // The unique ID assigned to this extension. bytes msg = 2; // The binary-marshalled protobuf extension payload. } // RegisteredExtension is an enumeration acting as a registry for extensions // defined by external sources. enum ExtensionID { EID_UNSET = 0; // New extensions are to be defined within this enumeration - their definition // MUST link to a reference describing their implementation. // An experimental extension that may be used during prototyping of a new // extension. EID_EXPERIMENTAL = 999; } // MasterArbitration is used to select the master among multiple gNMI clients // with the same Roles. The client with the largest election_id is honored as // the master. // The document about gNMI master arbitration can be found at // https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-master-arbitration.md message MasterArbitration { Role role = 1; Uint128 election_id = 2; } // Representation of unsigned 128-bit integer. message Uint128 { uint64 high = 1; uint64 low = 2; } // There can be one master for each role. The role is identified by its id. message Role { string id = 1; // More fields can be added if needed, for example, to specify what paths the // role can read/write. } pmacct-1.7.8/telemetry/decoders/v3/protos/huawei-ifm.proto0000755000175000017500000001031714354105275022617 0ustar paolopaolosyntax = "proto3"; // Automatically generated by goyang https://github.com/openconfig/goyang // compiled 2017-08-10T11:15:34Z // do not delete the next line // goyang-version 1 // module "huawei-ifm" // revision "2017-03-23" // revision "2013-01-01" // namespace "http://www.huawei.com/netconf/vrp/huawei-ifm" package huawei_ifm; message Ifm { message Interfaces { message Interface { enum IfAdminStatus { IfAdminStatus_DOWN = 0; IfAdminStatus_UP = 1; }; IfAdminStatus ifAdminStatus = 5; message IfClearedStat { uint64 sendByte = 29; uint64 sendPacket = 36; } IfClearedStat ifClearedStat = 9; message IfDynamicInfo { enum IfOperStatus { IfOperStatus_DOWN = 0; IfOperStatus_UP = 1; }; IfOperStatus ifOperStatus = 5; } IfDynamicInfo ifDynamicInfo = 13; uint32 ifIndex = 16; string ifName = 25; message IfStatistics { uint64 rcvBroadPacket = 2; uint64 rcvDropPacket = 3; uint64 rcvErrorPacket = 4; uint64 rcvMutiPacket = 5; uint64 rcvUniPacket = 6; uint64 receiveByte = 7; uint64 receivePacket = 8; uint64 sendBroadPacket = 9; uint64 sendByte = 10; uint64 sendDropPacket = 11; uint64 sendErrorPacket = 12; uint64 sendMutiPacket = 13; uint64 sendPacket = 14; uint64 sendUniPacket = 15; } IfStatistics ifStatistics = 35; } repeated Interface interface = 1; } Interfaces interfaces = 5; } // Do not delete the lines below, they preserve tag information for goyang. // goyang-tag Ifm interfaces/Interfaces 5 // goyang-tag Ifm_Interface_IfClearedStat sendByte/uint64 29 // goyang-tag Ifm_Interface_IfClearedStat sendPacket/uint64 36 // goyang-tag Ifm_Interface_IfDynamicInfo ifOperStatus/IfOperStatus 5 // goyang-tag Ifm_Interface_IfStatistics ethPortErrSts/EthPortErrSts 1 // goyang-tag Ifm_Interface_IfStatistics rcvBroadPacket/uint64 2 // goyang-tag Ifm_Interface_IfStatistics rcvMutiPacket/uint64 5 // goyang-tag Ifm_Interface_IfStatistics rcvUniPacket/uint64 6 // goyang-tag Ifm_Interface_IfStatistics receiveByte/uint64 7 // goyang-tag Ifm_Interface_IfStatistics receivePacket/uint64 8 // goyang-tag Ifm_Interface_IfStatistics sendBroadPacket/uint64 9 // goyang-tag Ifm_Interface_IfStatistics sendByte/uint64 10 // goyang-tag Ifm_Interface_IfStatistics sendMutiPacket/uint64 13 // goyang-tag Ifm_Interface_IfStatistics sendPacket/uint64 14 // goyang-tag Ifm_Interface_IfStatistics sendUniPacket/uint64 15 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxAlignment/uint64 1 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxCRC/uint64 2 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxFragment/uint64 3 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxInrangeLen/uint64 4 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxJabber/uint64 5 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxJomboOctets/uint64 6 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxLong/uint64 7 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxOverrun/uint64 8 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxPause/uint64 9 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxSymbol/uint64 10 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts rxUndersize/uint64 11 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txJomboOctets/uint64 12 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txLost/uint64 13 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txOverrun/uint64 14 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txPause/uint64 15 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txSystem/uint64 16 // goyang-tag Ifm_Interface_IfStatistics_EthPortErrSts txUnderrun/uint64 17 // goyang-tag Ifm_Interfaces interface/Interface[] 1 // goyang-tag Ifm_Interfaces_Interface ifAdminStatus/IfAdminStatus 5 // goyang-tag Ifm_Interfaces_Interface ifClearedStat/IfClearedStat 9 // goyang-tag Ifm_Interfaces_Interface ifDynamicInfo/IfDynamicInfo 13 // goyang-tag Ifm_Interfaces_Interface ifIndex/uint32 16 // goyang-tag Ifm_Interfaces_Interface ifName/string 25 // goyang-tag Ifm_Interfaces_Interface ifStatistics/IfStatistics 35 pmacct-1.7.8/telemetry/decoders/v3/protos/gnmi_pb2.py0000644000175000017500000022440114354105275021544 0ustar paolopaolo# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: gnmi.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf.internal import enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 import gnmi_ext_pb2 as gnmi__ext__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='gnmi.proto', package='gnmi', syntax='proto3', serialized_options=_b('\312>\0050.7.0'), serialized_pb=_b('\n\ngnmi.proto\x12\x04gnmi\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x0egnmi_ext.proto\"\x96\x01\n\x0cNotification\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\x1a\n\x06prefix\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12\r\n\x05\x61lias\x18\x03 \x01(\t\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1a\n\x06\x64\x65lete\x18\x05 \x03(\x0b\x32\n.gnmi.Path\x12\x0e\n\x06\x61tomic\x18\x06 \x01(\x08\"u\n\x06Update\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1e\n\x05value\x18\x02 \x01(\x0b\x32\x0b.gnmi.ValueB\x02\x18\x01\x12\x1d\n\x03val\x18\x03 \x01(\x0b\x32\x10.gnmi.TypedValue\x12\x12\n\nduplicates\x18\x04 \x01(\r\"\xe5\x02\n\nTypedValue\x12\x14\n\nstring_val\x18\x01 \x01(\tH\x00\x12\x11\n\x07int_val\x18\x02 \x01(\x03H\x00\x12\x12\n\x08uint_val\x18\x03 \x01(\x04H\x00\x12\x12\n\x08\x62ool_val\x18\x04 \x01(\x08H\x00\x12\x13\n\tbytes_val\x18\x05 \x01(\x0cH\x00\x12\x13\n\tfloat_val\x18\x06 \x01(\x02H\x00\x12&\n\x0b\x64\x65\x63imal_val\x18\x07 \x01(\x0b\x32\x0f.gnmi.Decimal64H\x00\x12)\n\x0cleaflist_val\x18\x08 \x01(\x0b\x32\x11.gnmi.ScalarArrayH\x00\x12\'\n\x07\x61ny_val\x18\t \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x12\x12\n\x08json_val\x18\n \x01(\x0cH\x00\x12\x17\n\rjson_ietf_val\x18\x0b \x01(\x0cH\x00\x12\x13\n\tascii_val\x18\x0c \x01(\tH\x00\x12\x15\n\x0bproto_bytes\x18\r \x01(\x0cH\x00\x42\x07\n\x05value\"Y\n\x04Path\x12\x13\n\x07\x65lement\x18\x01 \x03(\tB\x02\x18\x01\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x1c\n\x04\x65lem\x18\x03 \x03(\x0b\x32\x0e.gnmi.PathElem\x12\x0e\n\x06target\x18\x04 \x01(\t\"j\n\x08PathElem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x03key\x18\x02 \x03(\x0b\x32\x17.gnmi.PathElem.KeyEntry\x1a*\n\x08KeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"8\n\x05Value\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\x1c\n\x04type\x18\x02 \x01(\x0e\x32\x0e.gnmi.Encoding:\x02\x18\x01\"N\n\x05\x45rror\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any:\x02\x18\x01\".\n\tDecimal64\x12\x0e\n\x06\x64igits\x18\x01 \x01(\x03\x12\x11\n\tprecision\x18\x02 \x01(\r\"0\n\x0bScalarArray\x12!\n\x07\x65lement\x18\x01 \x03(\x0b\x32\x10.gnmi.TypedValue\"\xb2\x01\n\x10SubscribeRequest\x12+\n\tsubscribe\x18\x01 \x01(\x0b\x32\x16.gnmi.SubscriptionListH\x00\x12\x1a\n\x04poll\x18\x03 \x01(\x0b\x32\n.gnmi.PollH\x00\x12\"\n\x07\x61liases\x18\x04 \x01(\x0b\x32\x0f.gnmi.AliasListH\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\t\n\x07request\"\x06\n\x04Poll\"\xa8\x01\n\x11SubscribeResponse\x12$\n\x06update\x18\x01 \x01(\x0b\x32\x12.gnmi.NotificationH\x00\x12\x17\n\rsync_response\x18\x03 \x01(\x08H\x00\x12 \n\x05\x65rror\x18\x04 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01H\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\n\n\x08response\"\xd7\x02\n\x10SubscriptionList\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12(\n\x0csubscription\x18\x02 \x03(\x0b\x32\x12.gnmi.Subscription\x12\x13\n\x0buse_aliases\x18\x03 \x01(\x08\x12\x1d\n\x03qos\x18\x04 \x01(\x0b\x32\x10.gnmi.QOSMarking\x12)\n\x04mode\x18\x05 \x01(\x0e\x32\x1b.gnmi.SubscriptionList.Mode\x12\x19\n\x11\x61llow_aggregation\x18\x06 \x01(\x08\x12#\n\nuse_models\x18\x07 \x03(\x0b\x32\x0f.gnmi.ModelData\x12 \n\x08\x65ncoding\x18\x08 \x01(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cupdates_only\x18\t \x01(\x08\"&\n\x04Mode\x12\n\n\x06STREAM\x10\x00\x12\x08\n\x04ONCE\x10\x01\x12\x08\n\x04POLL\x10\x02\"\x9f\x01\n\x0cSubscription\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x04mode\x18\x02 \x01(\x0e\x32\x16.gnmi.SubscriptionMode\x12\x17\n\x0fsample_interval\x18\x03 \x01(\x04\x12\x1a\n\x12suppress_redundant\x18\x04 \x01(\x08\x12\x1a\n\x12heartbeat_interval\x18\x05 \x01(\x04\"\x1d\n\nQOSMarking\x12\x0f\n\x07marking\x18\x01 \x01(\r\"0\n\x05\x41lias\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\r\n\x05\x61lias\x18\x02 \x01(\t\"\'\n\tAliasList\x12\x1a\n\x05\x61lias\x18\x01 \x03(\x0b\x32\x0b.gnmi.Alias\"\xa9\x01\n\nSetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1a\n\x06\x64\x65lete\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\x1d\n\x07replace\x18\x03 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xac\x01\n\x0bSetResponse\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x08response\x18\x02 \x03(\x0b\x32\x12.gnmi.UpdateResult\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xca\x01\n\x0cUpdateResult\x12\x15\n\ttimestamp\x18\x01 \x01(\x03\x42\x02\x18\x01\x12\x18\n\x04path\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12(\n\x02op\x18\x04 \x01(\x0e\x32\x1c.gnmi.UpdateResult.Operation\"=\n\tOperation\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06\x44\x45LETE\x10\x01\x12\x0b\n\x07REPLACE\x10\x02\x12\n\n\x06UPDATE\x10\x03\"\x97\x02\n\nGetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x18\n\x04path\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\'\n\x04type\x18\x03 \x01(\x0e\x32\x19.gnmi.GetRequest.DataType\x12 \n\x08\x65ncoding\x18\x05 \x01(\x0e\x32\x0e.gnmi.Encoding\x12#\n\nuse_models\x18\x06 \x03(\x0b\x32\x0f.gnmi.ModelData\x12&\n\textension\x18\x07 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x08\x44\x61taType\x12\x07\n\x03\x41LL\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\t\n\x05STATE\x10\x02\x12\x0f\n\x0bOPERATIONAL\x10\x03\"\x7f\n\x0bGetResponse\x12(\n\x0cnotification\x18\x01 \x03(\x0b\x32\x12.gnmi.Notification\x12\x1e\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12&\n\textension\x18\x03 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x11\x43\x61pabilityRequest\x12&\n\textension\x18\x01 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xaa\x01\n\x12\x43\x61pabilityResponse\x12)\n\x10supported_models\x18\x01 \x03(\x0b\x32\x0f.gnmi.ModelData\x12+\n\x13supported_encodings\x18\x02 \x03(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cgNMI_version\x18\x03 \x01(\t\x12&\n\textension\x18\x04 \x03(\x0b\x32\x13.gnmi_ext.Extension\"@\n\tModelData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t*D\n\x08\x45ncoding\x12\x08\n\x04JSON\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\t\n\x05PROTO\x10\x02\x12\t\n\x05\x41SCII\x10\x03\x12\r\n\tJSON_IETF\x10\x04*A\n\x10SubscriptionMode\x12\x12\n\x0eTARGET_DEFINED\x10\x00\x12\r\n\tON_CHANGE\x10\x01\x12\n\n\x06SAMPLE\x10\x02\x32\xe3\x01\n\x04gNMI\x12\x41\n\x0c\x43\x61pabilities\x12\x17.gnmi.CapabilityRequest\x1a\x18.gnmi.CapabilityResponse\x12*\n\x03Get\x12\x10.gnmi.GetRequest\x1a\x11.gnmi.GetResponse\x12*\n\x03Set\x12\x10.gnmi.SetRequest\x1a\x11.gnmi.SetResponse\x12@\n\tSubscribe\x12\x16.gnmi.SubscribeRequest\x1a\x17.gnmi.SubscribeResponse(\x01\x30\x01:3\n\x0cgnmi_service\x12\x1c.google.protobuf.FileOptions\x18\xe9\x07 \x01(\tB\x08\xca>\x05\x30.7.0b\x06proto3') , dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,gnmi__ext__pb2.DESCRIPTOR,]) _ENCODING = _descriptor.EnumDescriptor( name='Encoding', full_name='gnmi.Encoding', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='JSON', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='BYTES', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='PROTO', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='ASCII', index=3, number=3, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='JSON_IETF', index=4, number=4, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=3417, serialized_end=3485, ) _sym_db.RegisterEnumDescriptor(_ENCODING) Encoding = enum_type_wrapper.EnumTypeWrapper(_ENCODING) _SUBSCRIPTIONMODE = _descriptor.EnumDescriptor( name='SubscriptionMode', full_name='gnmi.SubscriptionMode', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='TARGET_DEFINED', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='ON_CHANGE', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='SAMPLE', index=2, number=2, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=3487, serialized_end=3552, ) _sym_db.RegisterEnumDescriptor(_SUBSCRIPTIONMODE) SubscriptionMode = enum_type_wrapper.EnumTypeWrapper(_SUBSCRIPTIONMODE) JSON = 0 BYTES = 1 PROTO = 2 ASCII = 3 JSON_IETF = 4 TARGET_DEFINED = 0 ON_CHANGE = 1 SAMPLE = 2 GNMI_SERVICE_FIELD_NUMBER = 1001 gnmi_service = _descriptor.FieldDescriptor( name='gnmi_service', full_name='gnmi.gnmi_service', index=0, number=1001, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=True, extension_scope=None, serialized_options=None, file=DESCRIPTOR) _SUBSCRIPTIONLIST_MODE = _descriptor.EnumDescriptor( name='Mode', full_name='gnmi.SubscriptionList.Mode', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='STREAM', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='ONCE', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='POLL', index=2, number=2, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=1830, serialized_end=1868, ) _sym_db.RegisterEnumDescriptor(_SUBSCRIPTIONLIST_MODE) _UPDATERESULT_OPERATION = _descriptor.EnumDescriptor( name='Operation', full_name='gnmi.UpdateResult.Operation', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='INVALID', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='DELETE', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='REPLACE', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='UPDATE', index=3, number=3, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=2643, serialized_end=2704, ) _sym_db.RegisterEnumDescriptor(_UPDATERESULT_OPERATION) _GETREQUEST_DATATYPE = _descriptor.EnumDescriptor( name='DataType', full_name='gnmi.GetRequest.DataType', filename=None, file=DESCRIPTOR, values=[ _descriptor.EnumValueDescriptor( name='ALL', index=0, number=0, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='CONFIG', index=1, number=1, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='STATE', index=2, number=2, serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OPERATIONAL', index=3, number=3, serialized_options=None, type=None), ], containing_type=None, serialized_options=None, serialized_start=2927, serialized_end=2986, ) _sym_db.RegisterEnumDescriptor(_GETREQUEST_DATATYPE) _NOTIFICATION = _descriptor.Descriptor( name='Notification', full_name='gnmi.Notification', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='timestamp', full_name='gnmi.Notification.timestamp', index=0, number=1, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='prefix', full_name='gnmi.Notification.prefix', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='alias', full_name='gnmi.Notification.alias', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='update', full_name='gnmi.Notification.update', index=3, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='delete', full_name='gnmi.Notification.delete', index=4, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='atomic', full_name='gnmi.Notification.atomic', index=5, number=6, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=98, serialized_end=248, ) _UPDATE = _descriptor.Descriptor( name='Update', full_name='gnmi.Update', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='path', full_name='gnmi.Update.path', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='value', full_name='gnmi.Update.value', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='val', full_name='gnmi.Update.val', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='duplicates', full_name='gnmi.Update.duplicates', index=3, number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=250, serialized_end=367, ) _TYPEDVALUE = _descriptor.Descriptor( name='TypedValue', full_name='gnmi.TypedValue', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='string_val', full_name='gnmi.TypedValue.string_val', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='int_val', full_name='gnmi.TypedValue.int_val', index=1, number=2, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='uint_val', full_name='gnmi.TypedValue.uint_val', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='bool_val', full_name='gnmi.TypedValue.bool_val', index=3, number=4, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='bytes_val', full_name='gnmi.TypedValue.bytes_val', index=4, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='float_val', full_name='gnmi.TypedValue.float_val', index=5, number=6, type=2, cpp_type=6, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='decimal_val', full_name='gnmi.TypedValue.decimal_val', index=6, number=7, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='leaflist_val', full_name='gnmi.TypedValue.leaflist_val', index=7, number=8, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='any_val', full_name='gnmi.TypedValue.any_val', index=8, number=9, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='json_val', full_name='gnmi.TypedValue.json_val', index=9, number=10, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='json_ietf_val', full_name='gnmi.TypedValue.json_ietf_val', index=10, number=11, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ascii_val', full_name='gnmi.TypedValue.ascii_val', index=11, number=12, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='proto_bytes', full_name='gnmi.TypedValue.proto_bytes', index=12, number=13, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='value', full_name='gnmi.TypedValue.value', index=0, containing_type=None, fields=[]), ], serialized_start=370, serialized_end=727, ) _PATH = _descriptor.Descriptor( name='Path', full_name='gnmi.Path', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='element', full_name='gnmi.Path.element', index=0, number=1, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='origin', full_name='gnmi.Path.origin', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='elem', full_name='gnmi.Path.elem', index=2, number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='target', full_name='gnmi.Path.target', index=3, number=4, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=729, serialized_end=818, ) _PATHELEM_KEYENTRY = _descriptor.Descriptor( name='KeyEntry', full_name='gnmi.PathElem.KeyEntry', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='key', full_name='gnmi.PathElem.KeyEntry.key', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='value', full_name='gnmi.PathElem.KeyEntry.value', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=_b('8\001'), is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=884, serialized_end=926, ) _PATHELEM = _descriptor.Descriptor( name='PathElem', full_name='gnmi.PathElem', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='gnmi.PathElem.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='key', full_name='gnmi.PathElem.key', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[_PATHELEM_KEYENTRY, ], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=820, serialized_end=926, ) _VALUE = _descriptor.Descriptor( name='Value', full_name='gnmi.Value', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='value', full_name='gnmi.Value.value', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='type', full_name='gnmi.Value.type', index=1, number=2, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=_b('\030\001'), is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=928, serialized_end=984, ) _ERROR = _descriptor.Descriptor( name='Error', full_name='gnmi.Error', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='code', full_name='gnmi.Error.code', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='message', full_name='gnmi.Error.message', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='data', full_name='gnmi.Error.data', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=_b('\030\001'), is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=986, serialized_end=1064, ) _DECIMAL64 = _descriptor.Descriptor( name='Decimal64', full_name='gnmi.Decimal64', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='digits', full_name='gnmi.Decimal64.digits', index=0, number=1, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='precision', full_name='gnmi.Decimal64.precision', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1066, serialized_end=1112, ) _SCALARARRAY = _descriptor.Descriptor( name='ScalarArray', full_name='gnmi.ScalarArray', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='element', full_name='gnmi.ScalarArray.element', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1114, serialized_end=1162, ) _SUBSCRIBEREQUEST = _descriptor.Descriptor( name='SubscribeRequest', full_name='gnmi.SubscribeRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='subscribe', full_name='gnmi.SubscribeRequest.subscribe', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='poll', full_name='gnmi.SubscribeRequest.poll', index=1, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='aliases', full_name='gnmi.SubscribeRequest.aliases', index=2, number=4, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.SubscribeRequest.extension', index=3, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='request', full_name='gnmi.SubscribeRequest.request', index=0, containing_type=None, fields=[]), ], serialized_start=1165, serialized_end=1343, ) _POLL = _descriptor.Descriptor( name='Poll', full_name='gnmi.Poll', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1345, serialized_end=1351, ) _SUBSCRIBERESPONSE = _descriptor.Descriptor( name='SubscribeResponse', full_name='gnmi.SubscribeResponse', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='update', full_name='gnmi.SubscribeResponse.update', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sync_response', full_name='gnmi.SubscribeResponse.sync_response', index=1, number=3, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='error', full_name='gnmi.SubscribeResponse.error', index=2, number=4, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.SubscribeResponse.extension', index=3, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( name='response', full_name='gnmi.SubscribeResponse.response', index=0, containing_type=None, fields=[]), ], serialized_start=1354, serialized_end=1522, ) _SUBSCRIPTIONLIST = _descriptor.Descriptor( name='SubscriptionList', full_name='gnmi.SubscriptionList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='prefix', full_name='gnmi.SubscriptionList.prefix', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='subscription', full_name='gnmi.SubscriptionList.subscription', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='use_aliases', full_name='gnmi.SubscriptionList.use_aliases', index=2, number=3, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='qos', full_name='gnmi.SubscriptionList.qos', index=3, number=4, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mode', full_name='gnmi.SubscriptionList.mode', index=4, number=5, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='allow_aggregation', full_name='gnmi.SubscriptionList.allow_aggregation', index=5, number=6, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='use_models', full_name='gnmi.SubscriptionList.use_models', index=6, number=7, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='encoding', full_name='gnmi.SubscriptionList.encoding', index=7, number=8, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='updates_only', full_name='gnmi.SubscriptionList.updates_only', index=8, number=9, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ _SUBSCRIPTIONLIST_MODE, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1525, serialized_end=1868, ) _SUBSCRIPTION = _descriptor.Descriptor( name='Subscription', full_name='gnmi.Subscription', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='path', full_name='gnmi.Subscription.path', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mode', full_name='gnmi.Subscription.mode', index=1, number=2, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sample_interval', full_name='gnmi.Subscription.sample_interval', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='suppress_redundant', full_name='gnmi.Subscription.suppress_redundant', index=3, number=4, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='heartbeat_interval', full_name='gnmi.Subscription.heartbeat_interval', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=1871, serialized_end=2030, ) _QOSMARKING = _descriptor.Descriptor( name='QOSMarking', full_name='gnmi.QOSMarking', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='marking', full_name='gnmi.QOSMarking.marking', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2032, serialized_end=2061, ) _ALIAS = _descriptor.Descriptor( name='Alias', full_name='gnmi.Alias', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='path', full_name='gnmi.Alias.path', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='alias', full_name='gnmi.Alias.alias', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2063, serialized_end=2111, ) _ALIASLIST = _descriptor.Descriptor( name='AliasList', full_name='gnmi.AliasList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='alias', full_name='gnmi.AliasList.alias', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2113, serialized_end=2152, ) _SETREQUEST = _descriptor.Descriptor( name='SetRequest', full_name='gnmi.SetRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='prefix', full_name='gnmi.SetRequest.prefix', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='delete', full_name='gnmi.SetRequest.delete', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='replace', full_name='gnmi.SetRequest.replace', index=2, number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='update', full_name='gnmi.SetRequest.update', index=3, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.SetRequest.extension', index=4, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2155, serialized_end=2324, ) _SETRESPONSE = _descriptor.Descriptor( name='SetResponse', full_name='gnmi.SetResponse', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='prefix', full_name='gnmi.SetResponse.prefix', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='response', full_name='gnmi.SetResponse.response', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='message', full_name='gnmi.SetResponse.message', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='timestamp', full_name='gnmi.SetResponse.timestamp', index=3, number=4, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.SetResponse.extension', index=4, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2327, serialized_end=2499, ) _UPDATERESULT = _descriptor.Descriptor( name='UpdateResult', full_name='gnmi.UpdateResult', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='timestamp', full_name='gnmi.UpdateResult.timestamp', index=0, number=1, type=3, cpp_type=2, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='path', full_name='gnmi.UpdateResult.path', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='message', full_name='gnmi.UpdateResult.message', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='op', full_name='gnmi.UpdateResult.op', index=3, number=4, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ _UPDATERESULT_OPERATION, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2502, serialized_end=2704, ) _GETREQUEST = _descriptor.Descriptor( name='GetRequest', full_name='gnmi.GetRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='prefix', full_name='gnmi.GetRequest.prefix', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='path', full_name='gnmi.GetRequest.path', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='type', full_name='gnmi.GetRequest.type', index=2, number=3, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='encoding', full_name='gnmi.GetRequest.encoding', index=3, number=5, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='use_models', full_name='gnmi.GetRequest.use_models', index=4, number=6, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.GetRequest.extension', index=5, number=7, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ _GETREQUEST_DATATYPE, ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2707, serialized_end=2986, ) _GETRESPONSE = _descriptor.Descriptor( name='GetResponse', full_name='gnmi.GetResponse', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='notification', full_name='gnmi.GetResponse.notification', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='error', full_name='gnmi.GetResponse.error', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=_b('\030\001'), file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.GetResponse.extension', index=2, number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=2988, serialized_end=3115, ) _CAPABILITYREQUEST = _descriptor.Descriptor( name='CapabilityRequest', full_name='gnmi.CapabilityRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='extension', full_name='gnmi.CapabilityRequest.extension', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=3117, serialized_end=3176, ) _CAPABILITYRESPONSE = _descriptor.Descriptor( name='CapabilityResponse', full_name='gnmi.CapabilityResponse', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='supported_models', full_name='gnmi.CapabilityResponse.supported_models', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='supported_encodings', full_name='gnmi.CapabilityResponse.supported_encodings', index=1, number=2, type=14, cpp_type=8, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='gNMI_version', full_name='gnmi.CapabilityResponse.gNMI_version', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='extension', full_name='gnmi.CapabilityResponse.extension', index=3, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=3179, serialized_end=3349, ) _MODELDATA = _descriptor.Descriptor( name='ModelData', full_name='gnmi.ModelData', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='gnmi.ModelData.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='organization', full_name='gnmi.ModelData.organization', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='version', full_name='gnmi.ModelData.version', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=3351, serialized_end=3415, ) _NOTIFICATION.fields_by_name['prefix'].message_type = _PATH _NOTIFICATION.fields_by_name['update'].message_type = _UPDATE _NOTIFICATION.fields_by_name['delete'].message_type = _PATH _UPDATE.fields_by_name['path'].message_type = _PATH _UPDATE.fields_by_name['value'].message_type = _VALUE _UPDATE.fields_by_name['val'].message_type = _TYPEDVALUE _TYPEDVALUE.fields_by_name['decimal_val'].message_type = _DECIMAL64 _TYPEDVALUE.fields_by_name['leaflist_val'].message_type = _SCALARARRAY _TYPEDVALUE.fields_by_name['any_val'].message_type = google_dot_protobuf_dot_any__pb2._ANY _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['string_val']) _TYPEDVALUE.fields_by_name['string_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['int_val']) _TYPEDVALUE.fields_by_name['int_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['uint_val']) _TYPEDVALUE.fields_by_name['uint_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['bool_val']) _TYPEDVALUE.fields_by_name['bool_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['bytes_val']) _TYPEDVALUE.fields_by_name['bytes_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['float_val']) _TYPEDVALUE.fields_by_name['float_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['decimal_val']) _TYPEDVALUE.fields_by_name['decimal_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['leaflist_val']) _TYPEDVALUE.fields_by_name['leaflist_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['any_val']) _TYPEDVALUE.fields_by_name['any_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['json_val']) _TYPEDVALUE.fields_by_name['json_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['json_ietf_val']) _TYPEDVALUE.fields_by_name['json_ietf_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['ascii_val']) _TYPEDVALUE.fields_by_name['ascii_val'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _TYPEDVALUE.oneofs_by_name['value'].fields.append( _TYPEDVALUE.fields_by_name['proto_bytes']) _TYPEDVALUE.fields_by_name['proto_bytes'].containing_oneof = _TYPEDVALUE.oneofs_by_name['value'] _PATH.fields_by_name['elem'].message_type = _PATHELEM _PATHELEM_KEYENTRY.containing_type = _PATHELEM _PATHELEM.fields_by_name['key'].message_type = _PATHELEM_KEYENTRY _VALUE.fields_by_name['type'].enum_type = _ENCODING _ERROR.fields_by_name['data'].message_type = google_dot_protobuf_dot_any__pb2._ANY _SCALARARRAY.fields_by_name['element'].message_type = _TYPEDVALUE _SUBSCRIBEREQUEST.fields_by_name['subscribe'].message_type = _SUBSCRIPTIONLIST _SUBSCRIBEREQUEST.fields_by_name['poll'].message_type = _POLL _SUBSCRIBEREQUEST.fields_by_name['aliases'].message_type = _ALIASLIST _SUBSCRIBEREQUEST.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _SUBSCRIBEREQUEST.oneofs_by_name['request'].fields.append( _SUBSCRIBEREQUEST.fields_by_name['subscribe']) _SUBSCRIBEREQUEST.fields_by_name['subscribe'].containing_oneof = _SUBSCRIBEREQUEST.oneofs_by_name['request'] _SUBSCRIBEREQUEST.oneofs_by_name['request'].fields.append( _SUBSCRIBEREQUEST.fields_by_name['poll']) _SUBSCRIBEREQUEST.fields_by_name['poll'].containing_oneof = _SUBSCRIBEREQUEST.oneofs_by_name['request'] _SUBSCRIBEREQUEST.oneofs_by_name['request'].fields.append( _SUBSCRIBEREQUEST.fields_by_name['aliases']) _SUBSCRIBEREQUEST.fields_by_name['aliases'].containing_oneof = _SUBSCRIBEREQUEST.oneofs_by_name['request'] _SUBSCRIBERESPONSE.fields_by_name['update'].message_type = _NOTIFICATION _SUBSCRIBERESPONSE.fields_by_name['error'].message_type = _ERROR _SUBSCRIBERESPONSE.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _SUBSCRIBERESPONSE.oneofs_by_name['response'].fields.append( _SUBSCRIBERESPONSE.fields_by_name['update']) _SUBSCRIBERESPONSE.fields_by_name['update'].containing_oneof = _SUBSCRIBERESPONSE.oneofs_by_name['response'] _SUBSCRIBERESPONSE.oneofs_by_name['response'].fields.append( _SUBSCRIBERESPONSE.fields_by_name['sync_response']) _SUBSCRIBERESPONSE.fields_by_name['sync_response'].containing_oneof = _SUBSCRIBERESPONSE.oneofs_by_name['response'] _SUBSCRIBERESPONSE.oneofs_by_name['response'].fields.append( _SUBSCRIBERESPONSE.fields_by_name['error']) _SUBSCRIBERESPONSE.fields_by_name['error'].containing_oneof = _SUBSCRIBERESPONSE.oneofs_by_name['response'] _SUBSCRIPTIONLIST.fields_by_name['prefix'].message_type = _PATH _SUBSCRIPTIONLIST.fields_by_name['subscription'].message_type = _SUBSCRIPTION _SUBSCRIPTIONLIST.fields_by_name['qos'].message_type = _QOSMARKING _SUBSCRIPTIONLIST.fields_by_name['mode'].enum_type = _SUBSCRIPTIONLIST_MODE _SUBSCRIPTIONLIST.fields_by_name['use_models'].message_type = _MODELDATA _SUBSCRIPTIONLIST.fields_by_name['encoding'].enum_type = _ENCODING _SUBSCRIPTIONLIST_MODE.containing_type = _SUBSCRIPTIONLIST _SUBSCRIPTION.fields_by_name['path'].message_type = _PATH _SUBSCRIPTION.fields_by_name['mode'].enum_type = _SUBSCRIPTIONMODE _ALIAS.fields_by_name['path'].message_type = _PATH _ALIASLIST.fields_by_name['alias'].message_type = _ALIAS _SETREQUEST.fields_by_name['prefix'].message_type = _PATH _SETREQUEST.fields_by_name['delete'].message_type = _PATH _SETREQUEST.fields_by_name['replace'].message_type = _UPDATE _SETREQUEST.fields_by_name['update'].message_type = _UPDATE _SETREQUEST.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _SETRESPONSE.fields_by_name['prefix'].message_type = _PATH _SETRESPONSE.fields_by_name['response'].message_type = _UPDATERESULT _SETRESPONSE.fields_by_name['message'].message_type = _ERROR _SETRESPONSE.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _UPDATERESULT.fields_by_name['path'].message_type = _PATH _UPDATERESULT.fields_by_name['message'].message_type = _ERROR _UPDATERESULT.fields_by_name['op'].enum_type = _UPDATERESULT_OPERATION _UPDATERESULT_OPERATION.containing_type = _UPDATERESULT _GETREQUEST.fields_by_name['prefix'].message_type = _PATH _GETREQUEST.fields_by_name['path'].message_type = _PATH _GETREQUEST.fields_by_name['type'].enum_type = _GETREQUEST_DATATYPE _GETREQUEST.fields_by_name['encoding'].enum_type = _ENCODING _GETREQUEST.fields_by_name['use_models'].message_type = _MODELDATA _GETREQUEST.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _GETREQUEST_DATATYPE.containing_type = _GETREQUEST _GETRESPONSE.fields_by_name['notification'].message_type = _NOTIFICATION _GETRESPONSE.fields_by_name['error'].message_type = _ERROR _GETRESPONSE.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _CAPABILITYREQUEST.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION _CAPABILITYRESPONSE.fields_by_name['supported_models'].message_type = _MODELDATA _CAPABILITYRESPONSE.fields_by_name['supported_encodings'].enum_type = _ENCODING _CAPABILITYRESPONSE.fields_by_name['extension'].message_type = gnmi__ext__pb2._EXTENSION DESCRIPTOR.message_types_by_name['Notification'] = _NOTIFICATION DESCRIPTOR.message_types_by_name['Update'] = _UPDATE DESCRIPTOR.message_types_by_name['TypedValue'] = _TYPEDVALUE DESCRIPTOR.message_types_by_name['Path'] = _PATH DESCRIPTOR.message_types_by_name['PathElem'] = _PATHELEM DESCRIPTOR.message_types_by_name['Value'] = _VALUE DESCRIPTOR.message_types_by_name['Error'] = _ERROR DESCRIPTOR.message_types_by_name['Decimal64'] = _DECIMAL64 DESCRIPTOR.message_types_by_name['ScalarArray'] = _SCALARARRAY DESCRIPTOR.message_types_by_name['SubscribeRequest'] = _SUBSCRIBEREQUEST DESCRIPTOR.message_types_by_name['Poll'] = _POLL DESCRIPTOR.message_types_by_name['SubscribeResponse'] = _SUBSCRIBERESPONSE DESCRIPTOR.message_types_by_name['SubscriptionList'] = _SUBSCRIPTIONLIST DESCRIPTOR.message_types_by_name['Subscription'] = _SUBSCRIPTION DESCRIPTOR.message_types_by_name['QOSMarking'] = _QOSMARKING DESCRIPTOR.message_types_by_name['Alias'] = _ALIAS DESCRIPTOR.message_types_by_name['AliasList'] = _ALIASLIST DESCRIPTOR.message_types_by_name['SetRequest'] = _SETREQUEST DESCRIPTOR.message_types_by_name['SetResponse'] = _SETRESPONSE DESCRIPTOR.message_types_by_name['UpdateResult'] = _UPDATERESULT DESCRIPTOR.message_types_by_name['GetRequest'] = _GETREQUEST DESCRIPTOR.message_types_by_name['GetResponse'] = _GETRESPONSE DESCRIPTOR.message_types_by_name['CapabilityRequest'] = _CAPABILITYREQUEST DESCRIPTOR.message_types_by_name['CapabilityResponse'] = _CAPABILITYRESPONSE DESCRIPTOR.message_types_by_name['ModelData'] = _MODELDATA DESCRIPTOR.enum_types_by_name['Encoding'] = _ENCODING DESCRIPTOR.enum_types_by_name['SubscriptionMode'] = _SUBSCRIPTIONMODE DESCRIPTOR.extensions_by_name['gnmi_service'] = gnmi_service _sym_db.RegisterFileDescriptor(DESCRIPTOR) Notification = _reflection.GeneratedProtocolMessageType('Notification', (_message.Message,), dict( DESCRIPTOR = _NOTIFICATION, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Notification) )) _sym_db.RegisterMessage(Notification) Update = _reflection.GeneratedProtocolMessageType('Update', (_message.Message,), dict( DESCRIPTOR = _UPDATE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Update) )) _sym_db.RegisterMessage(Update) TypedValue = _reflection.GeneratedProtocolMessageType('TypedValue', (_message.Message,), dict( DESCRIPTOR = _TYPEDVALUE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.TypedValue) )) _sym_db.RegisterMessage(TypedValue) Path = _reflection.GeneratedProtocolMessageType('Path', (_message.Message,), dict( DESCRIPTOR = _PATH, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Path) )) _sym_db.RegisterMessage(Path) PathElem = _reflection.GeneratedProtocolMessageType('PathElem', (_message.Message,), dict( KeyEntry = _reflection.GeneratedProtocolMessageType('KeyEntry', (_message.Message,), dict( DESCRIPTOR = _PATHELEM_KEYENTRY, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.PathElem.KeyEntry) )) , DESCRIPTOR = _PATHELEM, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.PathElem) )) _sym_db.RegisterMessage(PathElem) _sym_db.RegisterMessage(PathElem.KeyEntry) Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), dict( DESCRIPTOR = _VALUE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Value) )) _sym_db.RegisterMessage(Value) Error = _reflection.GeneratedProtocolMessageType('Error', (_message.Message,), dict( DESCRIPTOR = _ERROR, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Error) )) _sym_db.RegisterMessage(Error) Decimal64 = _reflection.GeneratedProtocolMessageType('Decimal64', (_message.Message,), dict( DESCRIPTOR = _DECIMAL64, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Decimal64) )) _sym_db.RegisterMessage(Decimal64) ScalarArray = _reflection.GeneratedProtocolMessageType('ScalarArray', (_message.Message,), dict( DESCRIPTOR = _SCALARARRAY, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.ScalarArray) )) _sym_db.RegisterMessage(ScalarArray) SubscribeRequest = _reflection.GeneratedProtocolMessageType('SubscribeRequest', (_message.Message,), dict( DESCRIPTOR = _SUBSCRIBEREQUEST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.SubscribeRequest) )) _sym_db.RegisterMessage(SubscribeRequest) Poll = _reflection.GeneratedProtocolMessageType('Poll', (_message.Message,), dict( DESCRIPTOR = _POLL, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Poll) )) _sym_db.RegisterMessage(Poll) SubscribeResponse = _reflection.GeneratedProtocolMessageType('SubscribeResponse', (_message.Message,), dict( DESCRIPTOR = _SUBSCRIBERESPONSE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.SubscribeResponse) )) _sym_db.RegisterMessage(SubscribeResponse) SubscriptionList = _reflection.GeneratedProtocolMessageType('SubscriptionList', (_message.Message,), dict( DESCRIPTOR = _SUBSCRIPTIONLIST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.SubscriptionList) )) _sym_db.RegisterMessage(SubscriptionList) Subscription = _reflection.GeneratedProtocolMessageType('Subscription', (_message.Message,), dict( DESCRIPTOR = _SUBSCRIPTION, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Subscription) )) _sym_db.RegisterMessage(Subscription) QOSMarking = _reflection.GeneratedProtocolMessageType('QOSMarking', (_message.Message,), dict( DESCRIPTOR = _QOSMARKING, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.QOSMarking) )) _sym_db.RegisterMessage(QOSMarking) Alias = _reflection.GeneratedProtocolMessageType('Alias', (_message.Message,), dict( DESCRIPTOR = _ALIAS, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.Alias) )) _sym_db.RegisterMessage(Alias) AliasList = _reflection.GeneratedProtocolMessageType('AliasList', (_message.Message,), dict( DESCRIPTOR = _ALIASLIST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.AliasList) )) _sym_db.RegisterMessage(AliasList) SetRequest = _reflection.GeneratedProtocolMessageType('SetRequest', (_message.Message,), dict( DESCRIPTOR = _SETREQUEST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.SetRequest) )) _sym_db.RegisterMessage(SetRequest) SetResponse = _reflection.GeneratedProtocolMessageType('SetResponse', (_message.Message,), dict( DESCRIPTOR = _SETRESPONSE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.SetResponse) )) _sym_db.RegisterMessage(SetResponse) UpdateResult = _reflection.GeneratedProtocolMessageType('UpdateResult', (_message.Message,), dict( DESCRIPTOR = _UPDATERESULT, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.UpdateResult) )) _sym_db.RegisterMessage(UpdateResult) GetRequest = _reflection.GeneratedProtocolMessageType('GetRequest', (_message.Message,), dict( DESCRIPTOR = _GETREQUEST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.GetRequest) )) _sym_db.RegisterMessage(GetRequest) GetResponse = _reflection.GeneratedProtocolMessageType('GetResponse', (_message.Message,), dict( DESCRIPTOR = _GETRESPONSE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.GetResponse) )) _sym_db.RegisterMessage(GetResponse) CapabilityRequest = _reflection.GeneratedProtocolMessageType('CapabilityRequest', (_message.Message,), dict( DESCRIPTOR = _CAPABILITYREQUEST, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.CapabilityRequest) )) _sym_db.RegisterMessage(CapabilityRequest) CapabilityResponse = _reflection.GeneratedProtocolMessageType('CapabilityResponse', (_message.Message,), dict( DESCRIPTOR = _CAPABILITYRESPONSE, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.CapabilityResponse) )) _sym_db.RegisterMessage(CapabilityResponse) ModelData = _reflection.GeneratedProtocolMessageType('ModelData', (_message.Message,), dict( DESCRIPTOR = _MODELDATA, __module__ = 'gnmi_pb2' # @@protoc_insertion_point(class_scope:gnmi.ModelData) )) _sym_db.RegisterMessage(ModelData) google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(gnmi_service) DESCRIPTOR._options = None _UPDATE.fields_by_name['value']._options = None _PATH.fields_by_name['element']._options = None _PATHELEM_KEYENTRY._options = None _VALUE._options = None _ERROR._options = None _SUBSCRIBERESPONSE.fields_by_name['error']._options = None _SETRESPONSE.fields_by_name['message']._options = None _UPDATERESULT.fields_by_name['timestamp']._options = None _UPDATERESULT.fields_by_name['message']._options = None _GETRESPONSE.fields_by_name['error']._options = None _GNMI = _descriptor.ServiceDescriptor( name='gNMI', full_name='gnmi.gNMI', file=DESCRIPTOR, index=0, serialized_options=None, serialized_start=3555, serialized_end=3782, methods=[ _descriptor.MethodDescriptor( name='Capabilities', full_name='gnmi.gNMI.Capabilities', index=0, containing_service=None, input_type=_CAPABILITYREQUEST, output_type=_CAPABILITYRESPONSE, serialized_options=None, ), _descriptor.MethodDescriptor( name='Get', full_name='gnmi.gNMI.Get', index=1, containing_service=None, input_type=_GETREQUEST, output_type=_GETRESPONSE, serialized_options=None, ), _descriptor.MethodDescriptor( name='Set', full_name='gnmi.gNMI.Set', index=2, containing_service=None, input_type=_SETREQUEST, output_type=_SETRESPONSE, serialized_options=None, ), _descriptor.MethodDescriptor( name='Subscribe', full_name='gnmi.gNMI.Subscribe', index=3, containing_service=None, input_type=_SUBSCRIBEREQUEST, output_type=_SUBSCRIBERESPONSE, serialized_options=None, ), ]) _sym_db.RegisterServiceDescriptor(_GNMI) DESCRIPTOR.services_by_name['gNMI'] = _GNMI # @@protoc_insertion_point(module_scope) pmacct-1.7.8/telemetry/decoders/v3/protos/openconfig-interfaces.proto0000644000175000017500000002154314354105275025034 0ustar paolopaolosyntax = "proto3"; // Automatically generated by goyang https://github.com/openconfig/goyang // compiled 2018-07-04T09:10:55Z // do not delete the next line // goyang-version 1 // module "openconfig-interfaces" // revision "2018-01-05" // revision "2017-12-22" // revision "2017-12-21" // revision "2017-07-14" // revision "2017-04-03" // revision "2016-12-22" // namespace "http://openconfig.net/yang/interfaces" package openconfig_interfaces; message Interfaces { message Interface { message Config { string description = 1; bool enabled = 2; bool loopback_mode = 3; uint32 mtu = 4; string name = 5; string type = 6; } Config config = 1; message HoldTime { message Config { uint32 down = 1; uint32 up = 2; } Config config = 1; message State { uint32 down = 1; uint32 up = 2; } State state = 2; } HoldTime hold_time = 2; string name = 3; message State { enum AdminStatus { AdminStatus_INVALID = 0; AdminStatus_UP = 1; AdminStatus_DOWN = 2; AdminStatus_TESTING = 3; }; AdminStatus admin_status = 1; message Counters { uint64 carrier_transitions = 1; uint64 in_broadcast_pkts = 2; uint64 in_discards = 3; uint64 in_errors = 4; uint64 in_fcs_errors = 5; uint64 in_multicast_pkts = 6; uint64 in_octets = 7; uint64 in_unicast_pkts = 8; uint64 in_unknown_protos = 9; uint64 last_clear = 10; uint64 out_broadcast_pkts = 11; uint64 out_discards = 12; uint64 out_errors = 13; uint64 out_multicast_pkts = 14; uint64 out_octets = 15; uint64 out_unicast_pkts = 16; } Counters counters = 2; string description = 3; bool enabled = 4; uint32 ifindex = 5; uint64 last_change = 6; bool loopback_mode = 7; uint32 mtu = 8; string name = 9; enum OperStatus { OperStatus_INVALID = 0; OperStatus_UP = 1; OperStatus_DOWN = 2; OperStatus_TESTING = 3; OperStatus_UNKNOWN = 4; OperStatus_DORMANT = 5; OperStatus_NOT_PRESENT = 6; OperStatus_LOWER_LAYER_DOWN = 7; }; OperStatus oper_status = 10; string type = 11; } State state = 4; message Subinterfaces { message Subinterface { message Config { string description = 1; bool enabled = 2; uint32 index = 3; } Config config = 1; uint32 index = 2; message State { enum AdminStatus { AdminStatus_INVALID = 0; AdminStatus_UP = 1; AdminStatus_DOWN = 2; AdminStatus_TESTING = 3; }; AdminStatus admin_status = 1; message Counters { uint64 carrier_transitions = 1; uint64 in_broadcast_pkts = 2; uint64 in_discards = 3; uint64 in_errors = 4; uint64 in_fcs_errors = 5; uint64 in_multicast_pkts = 6; uint64 in_octets = 7; uint64 in_unicast_pkts = 8; uint64 in_unknown_protos = 9; uint64 last_clear = 10; uint64 out_broadcast_pkts = 11; uint64 out_discards = 12; uint64 out_errors = 13; uint64 out_multicast_pkts = 14; uint64 out_octets = 15; uint64 out_unicast_pkts = 16; } Counters counters = 2; string description = 3; bool enabled = 4; uint32 ifindex = 5; uint32 index = 6; uint64 last_change = 7; string name = 8; enum OperStatus { OperStatus_INVALID = 0; OperStatus_UP = 1; OperStatus_DOWN = 2; OperStatus_TESTING = 3; OperStatus_UNKNOWN = 4; OperStatus_DORMANT = 5; OperStatus_NOT_PRESENT = 6; OperStatus_LOWER_LAYER_DOWN = 7; }; OperStatus oper_status = 9; } State state = 3; } repeated Subinterface subinterface = 1; } Subinterfaces subinterfaces = 5; } repeated Interface interface = 1; } // Do not delete the lines below, they preserve tag information for goyang. // goyang-tag Interface_Config description/string 1 // goyang-tag Interface_Config enabled/bool 2 // goyang-tag Interface_Config loopback_mode/bool 3 // goyang-tag Interface_Config mtu/uint32 4 // goyang-tag Interface_Config name/string 5 // goyang-tag Interface_Config type/string 6 // goyang-tag Interface_HoldTime config/Config 1 // goyang-tag Interface_HoldTime state/State 2 // goyang-tag Interface_HoldTime_Config down/uint32 1 // goyang-tag Interface_HoldTime_Config up/uint32 2 // goyang-tag Interface_HoldTime_State down/uint32 1 // goyang-tag Interface_HoldTime_State up/uint32 2 // goyang-tag Interface_State admin_status/AdminStatus 1 // goyang-tag Interface_State counters/Counters 2 // goyang-tag Interface_State description/string 3 // goyang-tag Interface_State enabled/bool 4 // goyang-tag Interface_State ifindex/uint32 5 // goyang-tag Interface_State last_change/uint64 6 // goyang-tag Interface_State loopback_mode/bool 7 // goyang-tag Interface_State mtu/uint32 8 // goyang-tag Interface_State name/string 9 // goyang-tag Interface_State oper_status/OperStatus 10 // goyang-tag Interface_State type/string 11 // goyang-tag Interface_State_Counters carrier_transitions/uint64 1 // goyang-tag Interface_State_Counters in_broadcast_pkts/uint64 2 // goyang-tag Interface_State_Counters in_discards/uint64 3 // goyang-tag Interface_State_Counters in_errors/uint64 4 // goyang-tag Interface_State_Counters in_fcs_errors/uint64 5 // goyang-tag Interface_State_Counters in_multicast_pkts/uint64 6 // goyang-tag Interface_State_Counters in_octets/uint64 7 // goyang-tag Interface_State_Counters in_unicast_pkts/uint64 8 // goyang-tag Interface_State_Counters in_unknown_protos/uint64 9 // goyang-tag Interface_State_Counters last_clear/uint64 10 // goyang-tag Interface_State_Counters out_broadcast_pkts/uint64 11 // goyang-tag Interface_State_Counters out_discards/uint64 12 // goyang-tag Interface_State_Counters out_errors/uint64 13 // goyang-tag Interface_State_Counters out_multicast_pkts/uint64 14 // goyang-tag Interface_State_Counters out_octets/uint64 15 // goyang-tag Interface_State_Counters out_unicast_pkts/uint64 16 // goyang-tag Interface_Subinterface_Config description/string 1 // goyang-tag Interface_Subinterface_Config enabled/bool 2 // goyang-tag Interface_Subinterface_Config index/uint32 3 // goyang-tag Interface_Subinterface_State admin_status/AdminStatus 1 // goyang-tag Interface_Subinterface_State counters/Counters 2 // goyang-tag Interface_Subinterface_State description/string 3 // goyang-tag Interface_Subinterface_State enabled/bool 4 // goyang-tag Interface_Subinterface_State ifindex/uint32 5 // goyang-tag Interface_Subinterface_State index/uint32 6 // goyang-tag Interface_Subinterface_State last_change/uint64 7 // goyang-tag Interface_Subinterface_State name/string 8 // goyang-tag Interface_Subinterface_State oper_status/OperStatus 9 // goyang-tag Interface_Subinterface_State_Counters carrier_transitions/uint64 1 // goyang-tag Interface_Subinterface_State_Counters in_broadcast_pkts/uint64 2 // goyang-tag Interface_Subinterface_State_Counters in_discards/uint64 3 // goyang-tag Interface_Subinterface_State_Counters in_errors/uint64 4 // goyang-tag Interface_Subinterface_State_Counters in_fcs_errors/uint64 5 // goyang-tag Interface_Subinterface_State_Counters in_multicast_pkts/uint64 6 // goyang-tag Interface_Subinterface_State_Counters in_octets/uint64 7 // goyang-tag Interface_Subinterface_State_Counters in_unicast_pkts/uint64 8 // goyang-tag Interface_Subinterface_State_Counters in_unknown_protos/uint64 9 // goyang-tag Interface_Subinterface_State_Counters last_clear/uint64 10 // goyang-tag Interface_Subinterface_State_Counters out_broadcast_pkts/uint64 11 // goyang-tag Interface_Subinterface_State_Counters out_discards/uint64 12 // goyang-tag Interface_Subinterface_State_Counters out_errors/uint64 13 // goyang-tag Interface_Subinterface_State_Counters out_multicast_pkts/uint64 14 // goyang-tag Interface_Subinterface_State_Counters out_octets/uint64 15 // goyang-tag Interface_Subinterface_State_Counters out_unicast_pkts/uint64 16 // goyang-tag Interface_Subinterfaces subinterface/Subinterface[] 1 // goyang-tag Interface_Subinterfaces_Subinterface config/Config 1 // goyang-tag Interface_Subinterfaces_Subinterface index/uint32 2 // goyang-tag Interface_Subinterfaces_Subinterface state/State 3 // goyang-tag Interfaces interface/Interface[] 1 // goyang-tag Interfaces_Interface config/Config 1 // goyang-tag Interfaces_Interface hold_time/HoldTime 2 // goyang-tag Interfaces_Interface name/string 3 // goyang-tag Interfaces_Interface state/State 4 // goyang-tag Interfaces_Interface subinterfaces/Subinterfaces 5 pmacct-1.7.8/telemetry/decoders/v3/protos/gnmi_pb2_grpc.py0000644000175000017500000001065514354105275022563 0ustar paolopaolo# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! import grpc import gnmi_pb2 as gnmi__pb2 class gNMIStub(object): # missing associated documentation comment in .proto file pass def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.Capabilities = channel.unary_unary( '/gnmi.gNMI/Capabilities', request_serializer=gnmi__pb2.CapabilityRequest.SerializeToString, response_deserializer=gnmi__pb2.CapabilityResponse.FromString, ) self.Get = channel.unary_unary( '/gnmi.gNMI/Get', request_serializer=gnmi__pb2.GetRequest.SerializeToString, response_deserializer=gnmi__pb2.GetResponse.FromString, ) self.Set = channel.unary_unary( '/gnmi.gNMI/Set', request_serializer=gnmi__pb2.SetRequest.SerializeToString, response_deserializer=gnmi__pb2.SetResponse.FromString, ) self.Subscribe = channel.stream_stream( '/gnmi.gNMI/Subscribe', request_serializer=gnmi__pb2.SubscribeRequest.SerializeToString, response_deserializer=gnmi__pb2.SubscribeResponse.FromString, ) class gNMIServicer(object): # missing associated documentation comment in .proto file pass def Capabilities(self, request, context): """Capabilities allows the client to retrieve the set of capabilities that is supported by the target. This allows the target to validate the service version that is implemented and retrieve the set of models that the target supports. The models can then be specified in subsequent RPCs to restrict the set of data that is utilized. Reference: gNMI Specification Section 3.2 """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Get(self, request, context): """Retrieve a snapshot of data from the target. A Get RPC requests that the target snapshots a subset of the data tree as specified by the paths included in the message and serializes this to be returned to the client using the specified encoding. Reference: gNMI Specification Section 3.3 """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Set(self, request, context): """Set allows the client to modify the state of data on the target. The paths to modified along with the new values that the client wishes to set the value to. Reference: gNMI Specification Section 3.4 """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Subscribe(self, request_iterator, context): """Subscribe allows a client to request the target to send it values of particular paths within the data tree. These values may be streamed at a particular cadence (STREAM), sent one off on a long-lived channel (POLL), or sent as a one-off retrieval (ONCE). Reference: gNMI Specification Section 3.5 """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_gNMIServicer_to_server(servicer, server): rpc_method_handlers = { 'Capabilities': grpc.unary_unary_rpc_method_handler( servicer.Capabilities, request_deserializer=gnmi__pb2.CapabilityRequest.FromString, response_serializer=gnmi__pb2.CapabilityResponse.SerializeToString, ), 'Get': grpc.unary_unary_rpc_method_handler( servicer.Get, request_deserializer=gnmi__pb2.GetRequest.FromString, response_serializer=gnmi__pb2.GetResponse.SerializeToString, ), 'Set': grpc.unary_unary_rpc_method_handler( servicer.Set, request_deserializer=gnmi__pb2.SetRequest.FromString, response_serializer=gnmi__pb2.SetResponse.SerializeToString, ), 'Subscribe': grpc.stream_stream_rpc_method_handler( servicer.Subscribe, request_deserializer=gnmi__pb2.SubscribeRequest.FromString, response_serializer=gnmi__pb2.SubscribeResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'gnmi.gNMI', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) pmacct-1.7.8/telemetry/decoders/v3/protos/README.md0000644000175000017500000000007114354105275020747 0ustar paolopaoloPlaceholder for the proto file and their generated code. pmacct-1.7.8/telemetry/decoders/v3/protos/huawei-devm.proto0000755000175000017500000001041014354105275022771 0ustar paolopaolosyntax = "proto3"; // Automatically generated by goyang https://github.com/openconfig/goyang // compiled 2017-08-09T07:03:53Z // do not delete the next line // goyang-version 1 // module "huawei-devm" // revision "2017-03-23" // revision "2013-01-01" // namespace "http://www.huawei.com/netconf/vrp/huawei-devm" package huawei_devm; message Devm { message CpuInfos { message CpuInfo { uint32 entIndex = 1; //0x08 uint32 interval = 2; //0x10 uint32 ovloadThreshold = 3; //0x18 string position = 4; //0x22 uint32 systemCpuUsage = 5; //0x28 uint32 unovloadThreshold = 6; //0x30 } repeated CpuInfo cpuInfo = 1; //0x1a } CpuInfos cpuInfos = 5; //0x2a message EthPortStaStss { message EthPortStaSts { uint32 ifName = 1; //0x08 uint64 receiveByte = 2; //0x10 uint64 receivePacket = 3; //0x18 uint64 sendByte = 4; //0x20 uint64 sendPacket = 5; //0x28 } repeated EthPortStaSts ethPortStaSts = 1; //0x0a } EthPortStaStss ethPortStaStss = 7; //0x3a message MemoryInfos { message MemoryInfo { uint32 doMemoryFree = 1; //0x08 uint32 doMemoryTotal = 2; //0x10 uint32 doMemoryUsage = 3; //0x18 uint32 doMemoryUse = 4; //0x20 uint32 entIndex = 5; //0x28 uint32 osMemoryFree = 6; //0x30 uint32 osMemoryTotal = 7; //0x38 uint32 osMemoryUsage = 8; //0x40 uint32 osMemoryUse = 9; //0x48 uint32 ovloadThreshold = 10; //0x50 string position = 11; //0x5a uint32 simpleMemoryFree = 12; //0x60 uint32 simpleMemoryTotal = 13; //0x68 uint32 simpleMemoryUsage = 14; //0x70 uint32 simpleMemoryUse = 15; //0x78 uint32 unovloadThreshold = 16; //0x80 01 } repeated MemoryInfo memoryInfo = 1; //0x0e } MemoryInfos memoryInfos = 15; //0x7e message Ports { message Port { message OpticalInfo { string biasCurrent = 1; string manuDate = 2; string position = 15; string rxPower = 16; string temperature = 17; string txPower = 20; string voltage = 23; } OpticalInfo opticalInfo = 8; } repeated Port port = 1; } Ports ports = 20; } // Do not delete the lines below, they preserve tag information for goyang. // goyang-tag Devm cpuInfos/CpuInfos 5 // goyang-tag Devm ethPortStaStss/EthPortStaStss 7 // goyang-tag Devm memoryInfos/MemoryInfos 15 // goyang-tag Devm_CpuInfos cpuInfo/CpuInfo[] 1 // goyang-tag Devm_CpuInfos_CpuInfo entIndex/uint32 1 // goyang-tag Devm_CpuInfos_CpuInfo interval/uint32 2 // goyang-tag Devm_CpuInfos_CpuInfo ovloadThreshold/uint32 3 // goyang-tag Devm_CpuInfos_CpuInfo position/string 4 // goyang-tag Devm_CpuInfos_CpuInfo systemCpuUsage/uint32 5 // goyang-tag Devm_CpuInfos_CpuInfo unovloadThreshold/uint32 6 // goyang-tag Devm_MemoryInfos memoryInfo/MemoryInfo[] 1 // goyang-tag Devm_MemoryInfos_MemoryInfo doMemoryFree/uint32 1 // goyang-tag Devm_MemoryInfos_MemoryInfo doMemoryTotal/uint32 2 // goyang-tag Devm_MemoryInfos_MemoryInfo doMemoryUsage/uint32 3 // goyang-tag Devm_MemoryInfos_MemoryInfo doMemoryUse/uint32 4 // goyang-tag Devm_MemoryInfos_MemoryInfo entIndex/uint32 5 // goyang-tag Devm_MemoryInfos_MemoryInfo osMemoryFree/uint32 6 // goyang-tag Devm_MemoryInfos_MemoryInfo osMemoryTotal/uint32 7 // goyang-tag Devm_MemoryInfos_MemoryInfo osMemoryUsage/uint32 8 // goyang-tag Devm_MemoryInfos_MemoryInfo osMemoryUse/uint32 9 // goyang-tag Devm_MemoryInfos_MemoryInfo ovloadThreshold/uint32 10 // goyang-tag Devm_MemoryInfos_MemoryInfo position/string 11 // goyang-tag Devm_MemoryInfos_MemoryInfo simpleMemoryFree/uint32 12 // goyang-tag Devm_MemoryInfos_MemoryInfo simpleMemoryTotal/uint32 13 // goyang-tag Devm_MemoryInfos_MemoryInfo simpleMemoryUsage/uint32 14 // goyang-tag Devm_MemoryInfos_MemoryInfo simpleMemoryUse/uint32 15 // goyang-tag Devm_MemoryInfos_MemoryInfo unovloadThreshold/uint32 16 // goyang-tag Devm_EthPortStaStss ethPortStaSts/EthPortStaSts[] 1 // goyang-tag Devm_EthPortStaStss_EthPortStaSts ifName/uint32 1 // goyang-tag Devm_EthPortStaStss_EthPortStaSts receiveByte/uint64 2 // goyang-tag Devm_EthPortStaStss_EthPortStaSts receivePacket/uint64 3 // goyang-tag Devm_EthPortStaStss_EthPortStaSts sendByte/uint64 4 // goyang-tag Devm_EthPortStaStss_EthPortStaSts sendPacket/uint64 5 pmacct-1.7.8/telemetry/decoders/v3/config.py0000644000175000017500000000411114354105275017760 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import export_pmgrpcd import lib_pmgrpcd from zmq_modules.zmq_exporter import ZmqExporter from kafka_modules.kafka_avro_exporter import KafkaAvroExporter from kafka_modules.kafka_simple_exporter import KafkaExporter from file_modules.file_producer import FileExporter from lib_pmgrpcd import PMGRPCDLOG def configure(config=None): if config is None: config = lib_pmgrpcd.OPTIONS # Add the exporters if config.zmq: zmq_exporter = ZmqExporter() export_pmgrpcd.EXPORTERS["zmq"] = zmq_exporter if config.kafkaavro: kafka_avro_exporter = KafkaAvroExporter() export_pmgrpcd.EXPORTERS["kafkaavro"] = kafka_avro_exporter if config.kafkasimple: kafka_exporter = KafkaExporter(config.bsservers, config.topic) export_pmgrpcd.EXPORTERS["kafka"] = kafka_exporter if config.file_exporter_file is not None: exporter = FileExporter(config.file_exporter_file) export_pmgrpcd.EXPORTERS["file"] = exporter pmacct-1.7.8/telemetry/decoders/v3/kafka_modules/0000755000175000017500000000000014354105275020751 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/kafka_modules/__init__.py0000644000175000017500000000000014354105275023050 0ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/kafka_modules/kafka_avro_exporter.py0000644000175000017500000004620014354105275025361 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import multiprocessing import threading from confluent_kafka.avro.cached_schema_registry_client import ( CachedSchemaRegistryClient, ) from confluent_kafka import avro from confluent_kafka.avro import AvroProducer import lib_pmgrpcd import ujson as json from export_pmgrpcd import Exporter from lib_pmgrpcd import PMGRPCDLOG import logging import logging.handlers import signal import os class WorkerProcess(multiprocessing.Process): def __init__(self, queue, state_builder, transform_function): super().__init__() self.__queue = queue self.__state_builder = state_builder self.__transformFunction = transform_function def run(self): state = self.__state_builder() while True: submission = self.__queue.get(block=True) if submission is not None: ret = self.__transformFunction(state, submission.job) if submission.callback is not None: submission.callback(ret) else: return class WorkerSwarm: def enqueue(self, job, callback=None): self.__queue.put(WorkerTask(job, callback)) def __init__(self, number_of_workers, state_builder, transform_function): self.__queue = multiprocessing.Queue() self.__processes = [] for i in range(0, number_of_workers): t = WorkerProcess(self.__queue, state_builder, transform_function) self.__processes.append(t) def start(self): for process in self.__processes: process.start() def wait(self): for process in self.__processes: process.join() def stop(self): self.__queue.empty() for process in self.__processes: self.__queue.put(None, block=True) class WorkerTask: def __init__(self, job, callback): super().__init__() self.job = job self.callback = callback class KafkaAvroExporterContext: def __init__(self): global logQueue self.avscmap = {} self.jsonmap = {} # https://docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes h = logging.handlers.QueueHandler(logQueue) # Just the one handler needed root = logging.getLogger() root.addHandler(h) # send all messages, for demo; no other level or filter logic applied. root.setLevel(logging.DEBUG) self.__logger = logging.getLogger("KAFKA-AVRO-WORKER") def process_metric(self, datajsonstring): jsondata = json.loads(datajsonstring) self.__logger.debug("In process_metric") if "grpcPeer" in jsondata["collector"]["grpc"]: grpcPeer = jsondata["collector"]["grpc"]["grpcPeer"] if "collection_timestamp" in jsondata["collector"]["data"]: collection_timestamp = jsondata["collector"]["data"][ "collection_timestamp" ] else: collection_timestamp = -1 if "encoding_path" in jsondata["collector"]["data"]: encoding_path = jsondata["collector"]["data"]["encoding_path"] # print("IDENIFIER: %s - %s" % (grpcPeer, encoding_path)) self.__logger.debug("Found encoding_path: %s" % encoding_path) avscid = self.getavroschemaid(grpcPeer, encoding_path) # print("AVSCID: %s" % (avscid)) if avscid is not None: self.__logger.debug( "GETAVROSCHEMAID: grpcPeer=%s | encoding_path=%s | avroschemaid=%s" % (grpcPeer, encoding_path, avscid) ) avsc = self.getavroschema(avscid) avroinstance = self.getavro_schid_instance(avscid) self.__logger.debug("avroinstance is: %s" % (avroinstance)) if "name" in avsc: self.__logger.info( "SERIALIZE: epoch=%-10s | gP=%-13s | ep=%s | avscid=%s(%s)" % ( collection_timestamp, grpcPeer, encoding_path, avscid, avsc["name"], ) ) topic = lib_pmgrpcd.OPTIONS.topic try: # serialize(json.dumps(avsc), jsondata, topic, avscid, avroinstance) self.serialize( jsondata, lib_pmgrpcd.OPTIONS.topic, avscid, avroinstance, ) except Exception as e: if "msg_timestamp" in jsondata["collector"]["data"]: msg_timestamp = jsondata["collector"]["data"][ "msg_timestamp" ] self.__logger.info( "ERROR: serialize exeption on collection_timestamp=%s topic=%s avscid=%s grpcPeer=%s encoding_path=%s msg_timestamp=%s avroschemaname:%s" % ( collection_timestamp, topic, avscid, grpcPeer, encoding_path, msg_timestamp, avsc["name"], ) ) self.__logger.info("ERROR: %s" % (e)) pass else: self.__logger.info("%s -> encoding_path is missing" % grpcPeer) else: self.__logger.info("grpcPeer is missing" % jsondata) def getavroschemaid(self, grpcPeer, encoding_path): # global self.jsonmap self.__logger.debug( "In getavroschemaid with encoding_path: %s and grpcpeer: %s" % (encoding_path, grpcPeer) ) avroid = None if type(self.jsonmap) != dict: self.__logger.debug("jsonmap is not a dict") self.loadavscidmapfile() if not self.jsonmap: self.__logger.debug("jsonmap is empty") self.loadavscidmapfile() if grpcPeer in self.jsonmap: if encoding_path in self.jsonmap[grpcPeer]: avroid = self.jsonmap[grpcPeer][encoding_path] self.__logger.debug("avroid is found: %s" % avroid) else: self.__logger.debug( "avroid not found because of not maching/existing encoding_path (%s) within the mapping and grpcpeer (%s)" % (encoding_path, grpcPeer) ) pass else: self.__logger.debug( "avroid not found because of not maching/existing grpcPeer (%s) within the mapping" % grpcPeer ) return avroid def loadavscidmapfile(self): # global self.jsonmap self.__logger.info( "loading of the schemaidmappingfile (%s) to the cache self.jsonmap" % (lib_pmgrpcd.OPTIONS.avscmapfile) ) with open(lib_pmgrpcd.OPTIONS.avscmapfile, "r") as avscmapfile: self.jsonmap = json.load(avscmapfile) # mapfile and self.jsonmap # ------------------- # { # "138.187.58.1": { # "openconfig-interfaces:interfaces": 288 # }, # "10.0.0.2": { # "openconfig-interfaces:interfaces": 288 # } # } def getavro_schid_instance(self, avscid): # global self.avscmap self.__logger.debug("In getavro_schid_instance with avscid: %s" % avscid) avroinstance = None if avscid in self.avscmap: if "avroinstance" in self.avscmap[avscid]: self.__logger.debug("avroinstance found in dict self.avscmap") avroinstance = self.avscmap[avscid]["avroinstance"] else: self.__logger.debug("avroinstance not found in dict self.avscmap") self.create_avro_schid_instance(avscid) if "avroinstance" in self.avscmap[avscid]: self.__logger.debug( "avroinstance found in dict self.avscmap after creating with create_avro_schid_instance" ) avroinstance = self.avscmap[avscid]["avroinstance"] else: self.__logger.debug("avroid not found in dict self.avscmap") self.create_avro_schid_instance(avscid) if "avroinstance" in self.avscmap[avscid]: self.__logger.debug( "avroid and avroinstance found in dict self.avscmap after creating with create_avro_schid_instance" ) avroinstance = self.avscmap[avscid]["avroinstance"] self.__logger.debug("I will return the avroinstance: %s" % avroinstance) return avroinstance def create_avro_schid_instance(self, avscid): # global self.avscmap avroinstance = None self.__logger.info("Creating avroinstance for avro-schemaid: %s" % (avscid)) avsc = self.getavroschema(avscid) value_schema = avro.loads(json.dumps(avsc)) # print("TEST:%s" % (value_schema)) key_schema = avro.loads( '{"name": "schemaregistry", "type": "record", "fields": [{"name" : "schemaid", "type" : "long"}]}' ) avroProducer = AvroProducer( { "bootstrap.servers": lib_pmgrpcd.OPTIONS.bsservers, "schema.registry.url": lib_pmgrpcd.OPTIONS.urlscreg, "schema.registry.ssl.ca.location": lib_pmgrpcd.OPTIONS.calocation, "security.protocol": lib_pmgrpcd.OPTIONS.secproto, "ssl.certificate.location": lib_pmgrpcd.OPTIONS.sslcertloc, "ssl.key.location": lib_pmgrpcd.OPTIONS.sslkeyloc, "ssl.ca.location": lib_pmgrpcd.OPTIONS.calocation, }, default_key_schema=key_schema, default_value_schema=value_schema, ) if avscid in self.avscmap: self.avscmap[avscid].update({"avroinstance": avroProducer}) else: self.avscmap.update({avscid: {"avroinstance": avroProducer}}) return avsc def getavroschema(self, avscid): # global self.avscmap self.__logger.debug("In getavroschema with avscid: %s" % avscid) avsc = None if avscid in self.avscmap: if "avsc" in self.avscmap[avscid]: avsc = self.avscmap[avscid]["avsc"] else: self.loadavsc(avscid) if avscid in self.avscmap: if "avsc" in self.avscmap[avscid]: avsc = self.avscmap[avscid]["avsc"] else: # self.__logger.info("avsc not found in dict self.avscmap") self.loadavsc(avscid) if avscid in self.avscmap: if "avsc" in self.avscmap[avscid]: avsc = self.avscmap[avscid]["avsc"] return avsc # PMGRPCDLOG.info("PROTOPATH[" + telemetry_node + "]: " + protopath) def loadavsc(self, avscid): # global self.avscmap self.__logger.debug("In loadavsc with avscid: %s" % avscid) avsc = None self.__logger.debug( "lib_pmgrpcd.OPTIONS.urlscreg: %s lib_pmgrpcd.OPTIONS.calocation: %s" % (lib_pmgrpcd.OPTIONS.urlscreg, lib_pmgrpcd.OPTIONS.calocation) ) try: self.__logger.debug( "Instancing client (CachedSchemaRegistryClient) with avscid:%s url:%s ssl.ca.location:%s", avscid, lib_pmgrpcd.OPTIONS.urlscreg, lib_pmgrpcd.OPTIONS.calocation, ) client = CachedSchemaRegistryClient( url=lib_pmgrpcd.OPTIONS.urlscreg, ca_location=lib_pmgrpcd.OPTIONS.calocation, ) except Exception as e: self.__logger.info( "ERROR: load avro schema from schema-registry-server is failed on CachedSchemaRegistryClient on using method get_by_id()" ) self.__logger.info("ERROR: %s" % (e)) return avsc try: avsc = client.get_by_id(avscid) except Exception as e: self.__logger.info( "ERROR: load avro schema from schema-registry-server is failed on CachedSchemaRegistryClient on using method get_by_id()" ) self.__logger.info("ERROR: %s" % (e)) return avsc try: avsc_dict = json.loads(str(avsc)) except Exception as e: self.__logger.info( "ERROR: json.loads of the avsc_str is faild to produce a dict" ) self.__logger.info("ERROR: %s" % (e)) return avsc self.__logger.info("SCHEMA_OF_ID(%s): %s" % (avscid, avsc_dict["name"])) # Query Schema-Registry # self.jsonmap = json.load(mapfile) if avscid in self.avscmap: self.__logger.debug( "Update self.avscmap the existing record avscid (%s) with avroschema" % avscid ) self.avscmap[avscid].update({"avsc": avsc_dict}) else: self.__logger.debug( "Update self.avscmap with new record avscid (%s) with avroschema" % avscid ) self.avscmap.update({avscid: {"avsc": avsc_dict}}) return avsc def delivery_report(self, err, msg): """ Called once for each message produced to indicate delivery result. Triggered by poll() or flush(). """ if err: sys.stderr.write("%% Message failed delivery: %s\n" % err) elif lib_pmgrpcd.OPTIONS.debug: print("Message delivered to {} [{}]".format(msg.topic(), msg.partition())) def serialize(self, jsondata, topic, avscid, avroinstance): self.__logger.debug( "JSONDATA:%s\nTOPIC:%s\nAVSCID:%s\nAVROINSTANCE:%s\nSERIALIZELOG:%s" % (jsondata, topic, avscid, avroinstance, self.__logger) ) if lib_pmgrpcd.OPTIONS.jsondatafile or lib_pmgrpcd.OPTIONS.rawdatafile: self.__logger.info( "JSONDATA:%s\nTOPIC:%s\nAVSCID:%s\nAVROINSTANCE:%s\nSERIALIZELOG:%s" % (jsondata, topic, avscid, avroinstance, self.__logger) ) try: # https://github.com/confluentinc/confluent-kafka-python/issues/137 result = avroinstance.produce( topic=topic, value=jsondata, callback=self.delivery_report ) avroinstance.poll(0) if lib_pmgrpcd.OPTIONS.jsondatafile or lib_pmgrpcd.OPTIONS.rawdatafile: result = avroinstance.flush() except BufferError as e: print("[Exception avroinstance.produce BufferError]: %s" % (str(e))) self.__logger.debug( "[Exception avroinstance.produce BufferError]: see serializelog for details\n%s\n%s" % (json.dumps(jsondata, indent=2, sort_keys=True), str(e)) ) avroinstance.poll(10) result = avroinstance.produce( topic=topic, value=jsondata, key={"schemaid": avscid}, callback=self.delivery_report, ) except NotImplementedError as e: print("[Exception avroinstance.produce NotImplementedError]: %s" % (str(e))) self.__logger.debug( "[Exception avroinstance.produce NotImplementedError]: see serializelog for details\n%s\n%s" % (json.dumps(jsondata, indent=2, sort_keys=True), str(e)) ) except Exception as e: print("[Exception avroinstance.produce Exception]: %s" % (str(e))) self.__logger.debug( "[Exception avroinstance.produce Exception]: see serializelog for details\n%s\n%s" % (json.dumps(jsondata, indent=2, sort_keys=True), str(e)) ) def manually_serialize(self): PMGRPCDLOG.info( "manually serialize with avscid (%s) and jsondatafile (%s)" % (lib_pmgrpcd.OPTIONS.avscid, lib_pmgrpcd.OPTIONS.jsondatafile) ) avscid = int(lib_pmgrpcd.OPTIONS.avscid) avroinstance = self.getavro_schid_instance(avscid) with open(lib_pmgrpcd.OPTIONS.jsondatafile, "r") as jsondatahandler: jsondata = json.load(jsondatahandler) self.serialize(jsondata, lib_pmgrpcd.OPTIONS.topic, avscid, avroinstance) def buildCtx(): return KafkaAvroExporterContext() def processor(state, data): return state.process_metric(data) def manually_serialize(): ctx = buildCtx() ctx.manually_serialize() logQueue = multiprocessing.Queue() class LoggingThread(threading.Thread): def __init__(self): super().__init__() def run(self): global logQueue while True: record = logQueue.get(block=True) if record is not None: lib_pmgrpcd.SERIALIZELOG.handle(record) else: return logging_thread = LoggingThread() logging_thread.start() class KafkaAvroExporter(Exporter): def __init__(self): self.ws = WorkerSwarm(lib_pmgrpcd.OPTIONS.ProcessPool, buildCtx, processor) def term(sig, frame): self.ws.stop() self.ws.wait() global logQueue logQueue.put(None) global logging_thread logging_thread.join() if self.__prev_handler != 0: self.__prev_handler(sig, frame) os._exit(0) self.ws.start() self.__prev_handler = signal.getsignal(signal.SIGTERM) signal.signal(signal.SIGTERM, term) def process_metric(self, datajsonstring): self.ws.enqueue(datajsonstring) pmacct-1.7.8/telemetry/decoders/v3/kafka_modules/kafka_simple_exporter.py0000644000175000017500000002700314354105275025703 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import lib_pmgrpcd from export_pmgrpcd import Exporter import ujson as json import os from confluent_kafka import Producer import pickle import itertools FOLDER_PICKLE = "/tmp" class KafkaExporter(Exporter): def __init__(self, servers, topic): self.producer = Producer({"bootstrap.servers": servers}) self.topic = topic self.encoding_paths_lists = {} self.names_data = {} for fn in os.listdir(FOLDER_PICKLE): if ".pickle" in fn: fn = FOLDER_PICKLE + "/" + fn with open(fn, 'rb') as fh: data = pickle.load(fh) path = data["path"] self.names_data[path] = data def process_metric(self, datajsonstring): jsondata = json.loads(datajsonstring) if lib_pmgrpcd.OPTIONS.flatten: self.flatten_pmgrpcd(jsondata) else: json_data = json.encode(jsondata) self.send(json_data, self.topic) def flatten_pmgrpcd(self, jsondata): """ Extracts the required information from a pmgrpcd json file, and returns a simple one layer dictionary structure. """ source_grpc = jsondata["collector"]["grpc"]["grpcPeer"] collection_start = jsondata["collector"]["data"]["collection_timestamp"] encoding_path = jsondata["collector"]["data"]["encoding_path"] # TODO: Fix this, encoding path includes the proto (proto, path) = encoding_path.split(":") node_id = jsondata["collector"]["data"]["node_id_str"] data = None if path in jsondata: data = jsondata[path] elif "dataGpbkv" in jsondata["collector"]["data"]: data = jsondata["collector"]["data"]["dataGpbkv"] if data is None: raise Exception("We could not extract data") if "qos" in encoding_path: try: flat_data = self.flatten_cisco_fields(data, encoding_path) topic = create_topic(encoding_path) for metric in flat_data: metric["collection_start"] = collection_start metric["node_id"] = node_id json_data = json.encode(metric) self.send(json_data, topic) except Exception as e: breakpoint() if ( encoding_path != "Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters" ): return try: flat_data = self.flatten_cisco_fields(data, encoding_path) except: breakpoint() for metric in flat_data: metric["collection_start"] = collection_start metric["node_id"] = node_id json_data = json.encode(metric) self.send(json_data) def send(self, text, topic=None): if topic is None: topic = self.topic self.producer.poll(0) self.producer.produce(topic, text.encode("utf-8")) def flatten_cisco_fields(self, fields, encoding_path, flatten_array=None): """ Takes data and returns one or more flatten jsons. """ if flatten_array is None: flatten_array = [] # let's take care of the key-content type of cisco if self.is_key_value(fields): self.flatten_key_content(fields, encoding_path, flatten_array) else: # we might have multiple keys, let's just take them one by one for field in fields: self.flatten_cisco_fields(field, encoding_path, flatten_array=flatten_array) breakpoint() return flatten_array def flatten_key_content(self, fields, encoding_path, metrics): # get keys and content keys = None content = None for field in fields: if field.get("name", "") == "keys": keys = field elif field.get("name", "") == "content": content = field if keys is None: raise Exception("No keys in field {}".format(fields)) if content is None: raise Exception("No content in field {}".format(fields)) metric_keys = {} # flatten keys for n, key in enumerate(keys["fields"]): key, value = self.simplify_cisco_field(key, encoding_path=encoding_path, key_n=n) metric_keys[key] = value flatten_metrics = [] self.flatten_content_fields(content, encoding_path, metric_keys, flatten_metrics, metrics) # now we can create the multiple metrics from a single one, if needed #for content_f in content["fields"]: #if "fields" in content_f and content_f["fields"]: # breakpoint() # raise Exception("Not ready") #key, value = simplify_cisco_field(content_f) #flatten_metric[key] = value metrics.extend(combine_keys_content(metric_keys, flatten_metrics)) return metrics def flatten_content_fields(self, content_f, encoding_path, keys, flatten_metrics, other_metrics, level=None): ''' Here we have pure content. ''' if level is None: level = [] # first we go over elements colleting all "normal" in this hierarchy fields_with_children = [] this_encoding_path = form_encoding_path(encoding_path, level) look_for_keys = this_encoding_path in self.encoding_paths_lists flatten_metric = {} for field in content_f["fields"]: if "fields" in field and field["fields"]: fields_with_children.append(field) continue name, value = self.simplify_cisco_field(field, encoding_path=encoding_path, levels=level) if look_for_keys: if name in self.encoding_paths_lists[this_encoding_path]: keys[name] = value else: flatten_metric[name] = value else: flatten_metric[name] = value children_flatten_metrics = [] if fields_with_children: for field in fields_with_children: name = field.get("name", None) if name is None: name = "Unknown" new_levels = level + [name] if add_leaf(this_encoding_path, name) in self.encoding_paths_lists: raise Exception("Not ready") new_keys = dict(keys) child_flatten_content = [] self.flatten_content_fields(field, this_encoding_path, new_keys, child_flatten_content, other_metrics) # now gett the flatten value and add it new_metric = combine_keys_content(new_keys, child_flatten_content) other_metrics.append(new_metric) else: self.flatten_content_fields(field, encoding_path, keys, children_flatten_metrics, other_metrics, new_levels) # our metrics are the ones in chilren_flatten_metrics together with the ones in this hierarchy if children_flatten_metrics: for children_metric in children_flatten_metrics: this_metric = dict(flatten_metric) this_metric.update(children_metric) flatten_metrics.append(this_metric) else: flatten_metrics.append(flatten_metric) @staticmethod def is_key_value(fields): return len(fields) == 2 and set( [field.get("name", "") for field in fields] ) == set(["keys", "content"]) def simplify_cisco_field(self, field, encoding_path=None, levels=None, key_n=None): # find the name, this becomes more of a problem when the mapping is complicated name = None if encoding_path in self.names_data: if key_n is not None: name = self.names_data[encoding_path]["names"][0][key_n] else: # we are in ocntent #relative_path = "/".join(["", *levels, field["name"]]) #if relative_path in self.names_data[encoding_path]["names"][1]: # name = self.names_data[encoding_path]["names"][1][relative_path] name = "_".join([*levels, field["name"]]) if name is None: # problem, log name = field["name"] value = None found = False found_attr = None for attr in field: if attr in ONE_OF: found_attr = attr found = True value = field[attr] break # try to cast value castin = None if found_attr in INTEGERS: casting = int elif found_attr in FLOAT: casting = float elif found_attr == "boolValue": casting = bool try: value = casting(value) except: pass if not found: raise Exception("We could not find a way of simplifying {}".format(field)) return name, value def create_topic(path): replacesments = set([':', '/']) rpath = path for ch in replacesments: rpath = rpath.replace(ch, ".") return rpath def form_encoding_path(encoding_path, levels): if not levels: return encoding_path if encoding_path[-1] == "/": encoding_path = encoding_path[:-1] return '/'.join([encoding_path, '/'.join(levels)]) def add_leaf(encoding_path, name): if encoding_path[-1] == "/": encoding_path = encoding_path[:-1] return '/'.join([encoding_path, name]) def combine_keys_content(keys, content): # keys are a dict, content is a dict -> list of dicts combined = [] for content_metric in content: metric = dict(keys) metric.update(content_metric) combined.append(metric) return combined #for comb in itertools.product(*content.values()): # metric = dict(keys) # for subhierarchy in comb: # metric.update(subhierarchy) # yield metric #combined = {} #combined.update(keys) #combined.update(content) #return combined ONE_OF = set( [ "bytesValue", "stringValue", "boolValue", "uint32Value", "uint64Value", "sint32Value", "sint64Value", "doubleValue", "floatValue", ] ) INTEGERS = set(["uint32Value", "uint64Value", "sint32Value", "sint64Value"]) FLOAT = set(["doubleValue", "floatValue"]) pmacct-1.7.8/telemetry/decoders/v3/README.pmgrpcd0000644000175000017500000001072614354105275020465 0ustar paolopaoloThese are quickstart notes on how to install pmgrpcd.py and all of its dependencies. CONFIG-KEYS.pmgrpcd provides the documentation for all of pmgrpcd.py configuration parameters. Install pmgrpcd.py =================== shell> mkdir -p /opt/pkg/ shell> git clone https://github.com/pmacct/pmacct.git /opt/pkg/pmacct shell> ln -s /opt/pkg/pmacct/telemetry/decoders/v3 /opt/pkg/pmgrpcd shell> chmod 700 /opt/pkg/pmgrpcd/pmgrpcd.py Install protoc -------------- Install system dependencies: shell> sudo yum install tar wget autoconf libtool automake gcc-c++ make git bzip2 curl unzip zlib zlib-devel -y [CentOS/RHEL] shell> sudo apt-get install tar wget autoconf libtool automake g++ make git bzip2 curl unzip zlib1g-dev [Debian/Ubuntu] Obtain and compile GPB code: shell> git clone https://github.com/protocolbuffers/protobuf.git /opt/pkg/protobuf shell> cd /opt/pkg/protobuf shell> ./autogen.sh shell> ./configure shell> make shell> make install shell> ldconfig shell> protoc --version Python interpreter ------------------ It is recommended to use Python >= 3.7 although the code would work with less recent Python 3 interpreters (ie. 3.5 and 3.6). The Command Line examples in the remainder of this document will assume the use of python3.7. Install Python dependencies --------------------------- shell> python3.7 -m pip install -r requirements.txt Setup PYTHONPATH ---------------- This is an environment variable which you can set to add additional directories where python will look for modules and packages. Setting PYTHONPATH is required (for the time being) to look for .py files in sub-directories. The following example is based on bash shell: shell> PYTHONPATH=/opt/pkg/pmgrpcd/protos:/opt/pkg/pmgrpcd/zmq_modules:/opt/pkg/pmgrpcd/kafka_modukes:/opt/pkg/pmgrpcd/file_modules:/etc/pmacct/telemetry/pblib shell> export PYTHONPATH Compile grpc libs (L1) ---------------------- shell> mkdir -p /etc/pmacct/telemetry/pblib Copy gRPC .proto file(s) (ie. huawei-grpc-dialout.proto) to /etc/pmacct/telemetry/pblib (some sample .proto files for testing purposes are available in the protos/ directory and can be copied over). shell> cd /etc/pmacct/telemetry/pblib/ shell> python3.7 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. huawei-grpc-dialout.proto shell> python3.7 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. cisco_grpc_dialout.proto Compile PB libs (L2/3) ---------------------- shell> cd /etc/pmacct/telemetry/pblib/ shell> /usr/local/bin/protoc -I=. --python_out=. ./huawei-grpc-dialout.proto shell> /usr/local/bin/protoc -I=. --python_out=. ./cisco_grpc_dialout.proto shell> /usr/local/bin/protoc -I=. --python_out=. ./huawei-telemetry.proto shell> /usr/local/bin/protoc -I=. --python_out=. ./huawei-ifm.proto shell> /usr/local/bin/protoc -I=. --python_out=. ./huawei-devm.proto shell> /usr/local/bin/protoc -I=. --python_out=. ./openconfig-interfaces.proto First Run pmgrpcd.py -------------------- shell> cd /opt/pkg/pmgrpcd && python3.7 ./pmgrpcd.py -h Scenario 1: ZMQ output to pmtelemetryd -------------------------------------- Export of JSON-encoded Streaming Telemetry data to pmtelemetryd allows to quickly access all daemon features, ie. save to files, produce to Kafka, stream/log data out or dump at regular intervals, etc. The default configuration in config_files/telemetry.conf is suitable for this scenario. If collecting from Cisco 'cisco = True' should be set; if collecting from Huawei 'huawei = True' should be set. The configuration instructs pmgrpcd to listen for Streaming Telemetry data on port 10000 and export it via ZMQ on port 50000: shell> python3.7 ./pmgrpcd.py -N pmtelemetryd can be configured as follows to read data from a ZeroMQ on port 50000 and stream/log it to local files: telemetry_daemon_zmq_address: 127.0.0.1:50000 telemetry_daemon_decoder: json ! telemetry_daemon_msglog_file: /path/to/spool/telemetry-msglog-$peer_src_ip.json telemetry_daemon_msglog_output: json Or pmtelemetryd can be configured as follows to read data from a ZeroMQ on port 50000 and produce it to a Kafka broker: telemetry_daemon_zmq_address: 127.0.0.1:50000 telemetry_daemon_decoder: json ! telemetry_dump_kafka_broker_host: telemetry_dump_kafka_broker_port: 9092 telemetry_dump_kafka_topic: pmacct.streaming-telemetry.test telemetry_dump_refresh_time: 60 Concluding notes ---------------- The default config being read is config_files/telemetry.conf . To learn more about all configuration directives see the document CONFIG-KEYS.pmgrpcd . pmacct-1.7.8/telemetry/decoders/v3/kafka_receiver.py0000644000175000017500000000353514354105275021465 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from confluent_kafka import Consumer, KafkaError import logging logging.basicConfig(level=logging.DEBUG) mylogger = logging.getLogger() c = Consumer({ 'bootstrap.servers': 'gtat-stage-msg01', 'group.id': 'mygroup', 'auto.offset.reset': 'latest', "logger": mylogger }) c.subscribe(['gnmi']) #c.subscribe(['Cisco-IOS-XR-qos-ma-oper.qos.nodes.node.policy-map.interface-table.interface.member-interfaces.member-interface.output.service-policy-names.service-policy-instance.statistics']) while True: msg = c.poll(1.0) if msg is None: continue if msg.error(): print("Consumer error: {}".format(msg.error())) continue print('Received message: {}'.format(msg.value().decode('utf-8'))) c.close() pmacct-1.7.8/telemetry/decoders/v3/utils/0000755000175000017500000000000014354105275017304 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/utils/huawei_generate_data.py0000644000175000017500000000413214354105275024003 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from huawei_generator import HuaweiDialOutClient from huawei_grpc_dialout_pb2 import serviceArgs from utils import generate_content_from_raw from optparse import OptionParser DEFAULT_FILE = "huawei_dump" DEFAULT_CONNECTION = "127.0.0.1:6000" parser = OptionParser() parser.add_option( "-f", "--file", default=str(DEFAULT_FILE), dest="file", help="File with raw data", ) parser.add_option( "-c", "--connection", default=str(DEFAULT_CONNECTION), help="IP (socket address) of the collector", ) (options, _) = parser.parse_args() huawei_client = HuaweiDialOutClient(options.connection) def generate_data(data_generator): for data in data_generator: yield serviceArgs(ReqId=1, data=data) huawei_client.send_data(generate_data(generate_content_from_raw(options.file))) # check status while not huawei_client.rcv.done(): continue try: result = huawei_client.rcv.result() except Exception as e: print("Generation failed with error ", e) pmacct-1.7.8/telemetry/decoders/v3/utils/kafka_consumer.py0000644000175000017500000000426514354105275022655 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from confluent_kafka import Consumer, KafkaError import sys from optparse import OptionParser DEFAULT_TOPIC = "daisy.test.device-avro-raw" DEFAULT_SERVER = "kafka.sbd.corproot.net:9093" parser = OptionParser() parser.add_option( "-t", "--topic",, default=str(DEFAULT_TOPIC), dest="topic", help="Topic to listen", ) parser.add_option( "-s", "--servers",, default=str(DEFAULT_SERVER), dest="servers", help="Kafka servers", ) (options, _) = parser.parse_args() c = Consumer({ 'bootstrap.servers': options.servers, 'group.id': 'mygroup', 'auto.offset.reset': 'earliest' }) c.subscribe([options.topic]) #c.subscribe(['Cisco-IOS-XR-qos-ma-oper.qos.nodes.node.policy-map.interface-table.interface.member-interfaces.member-interface.output.service-policy-names.service-policy-instance.statistics']) while True: msg = c.poll(1.0) if msg is None: continue if msg.error(): print("Consumer error: {}".format(msg.error())) continue print('Received message: {}'.format(msg.value().decode('utf-8'))) c.close() pmacct-1.7.8/telemetry/decoders/v3/utils/kafka_producer.py0000644000175000017500000000405214354105275022637 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from confluent_kafka import Producer p = Producer({"bootstrap.servers": "kafka.sbd.corproot.net:9093"}) def delivery_report(err, msg): """ Called once for each message produced to indicate delivery result. Triggered by poll() or flush(). """ if err is not None: print("Message delivery failed: {}".format(err)) else: print("Message delivered to {} [{}]".format(msg.topic(), msg.partition())) for data in ["test"]: # Trigger any available delivery report callbacks from previous produce() calls p.poll(0) # Asynchronously produce a message, the delivery report callback # will be triggered from poll() above, or flush() below, when the message has # been successfully delivered or failed permanently. p.produce("telemetry1.test", data.encode("utf-8"), callback=delivery_report) # Wait for any outstanding messages to be delivered and delivery report # callbacks to be triggered. p.flush() pmacct-1.7.8/telemetry/decoders/v3/utils/huawei_generator.py0000644000175000017500000000325614354105275023214 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # # Imitates the generation of huawei telemetry. # Use for testing. import huawei_grpc_dialout_pb2_grpc import grpc # Dialout code # Simple for now, it could get complicated if we need a more time based example. class HuaweiDialOutClient(): def __init__(self, server): self.server = server self.channel = grpc.insecure_channel(self.server) self.stub = huawei_grpc_dialout_pb2_grpc.gRPCDataserviceStub(self.channel) def send_data(self, data): self.rcv = self.stub.dataPublish(data) def close(self): self.channel.close() pmacct-1.7.8/telemetry/decoders/v3/utils/zmq_puller.py0000644000175000017500000000334014354105275022050 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from __future__ import print_function from zmq import ZMQError import zmq from optparse import OptionParser import sys def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) DEFAULT_PORT = "tcp://127.0.0.1:50000" parser = OptionParser() parser.add_option( "-p", "--port", default=str(DEFAULT_PORT), dest="port", help="Port to setup the server", ) (options, _) = parser.parse_args() zmqContext = zmq.Context() zmqSock = zmqContext.socket(zmq.PULL) zmqSock.connect(options.port) eprint("zmq ready") while True: work = zmqSock.recv_json().strip() if work: print(work) pmacct-1.7.8/telemetry/decoders/v3/export_pmgrpcd.py0000644000175000017500000001274414354105275021563 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import os import time from lib_pmgrpcd import PMGRPCDLOG import lib_pmgrpcd import sys import ujson as json from abc import ABC, abstractmethod jsonmap = {} avscmap = {} example_dict = {} class Exporter(ABC): @abstractmethod def process_metric(self, metric): pass EXPORTERS = {} def export_metrics(datajsonstring): for exporter in EXPORTERS: try: EXPORTERS[exporter].process_metric(datajsonstring) except Exception as e: PMGRPCDLOG.debug("Error processing packet on exporter %s. Error was %s", exporter, e) raise def examples(dictTelemetryData_mod, jsonTelemetryData): global example_dict if dictTelemetryData_mod["collector"]["grpc"]["grpcPeer"]: grpcPeer = dictTelemetryData_mod["collector"]["grpc"]["grpcPeer"] if dictTelemetryData_mod["collector"]["grpc"]["ne_vendor"]: ne_vendor = dictTelemetryData_mod["collector"]["grpc"]["ne_vendor"] if dictTelemetryData_mod["collector"]["data"]["encoding_path"]: encoding_path = dictTelemetryData_mod["collector"]["data"][ "encoding_path" ] PMGRPCDLOG.debug( "IN EXAMPLES: grpcPeer=%s ne_vendor=%s encoding_path=%s" % (grpcPeer, ne_vendor, encoding_path) ) try: if not os.path.exists(lib_pmgrpcd.OPTIONS.examplepath): os.makedirs(lib_pmgrpcd.OPTIONS.examplepath) except OSError: pass if grpcPeer not in example_dict: example_dict.update({grpcPeer: []}) if encoding_path not in example_dict[grpcPeer]: example_dict[grpcPeer].append(encoding_path) encoding_path_mod = encoding_path.replace(":", "_").replace("/", "-") exafilename = grpcPeer + "_" + ne_vendor + "_" + encoding_path_mod + ".json" exapathfile = os.path.join(lib_pmgrpcd.OPTIONS.examplepath, exafilename) with open(exapathfile, "w") as exapathfile: # exapathfile.write("PROTOPATH[" + telemetry_node + "]: " + protopath + "\n") exapathfile.write(jsonTelemetryData) exapathfile.write("\n") def FinalizeTelemetryData(dictTelemetryData): # Adding epoch in millisecond to identify this singel metric on the way to the storage epochmillis = int(round(time.time() * 1000)) dictTelemetryData["collector"]["data"].update({"collection_timestamp": epochmillis}) dictTelemetryData_mod = dictTelemetryData.copy() # Going over the mitigation library, if needed. # TODO: Simplify the next part if lib_pmgrpcd.OPTIONS.mitigation: from mitigation import mod_all_json_data try: dictTelemetryData_mod = mod_all_json_data(dictTelemetryData_mod) jsonTelemetryData = json.dumps( dictTelemetryData_mod, indent=2, sort_keys=True ) except Exception as e: PMGRPCDLOG.info("ERROR: mod_all_json_data raised a error:\n%s") PMGRPCDLOG.info("ERROR: %s" % (e)) dictTelemetryData_mod = dictTelemetryData jsonTelemetryData = json.dumps(dictTelemetryData, indent=2, sort_keys=True) else: dictTelemetryData_mod = dictTelemetryData jsonTelemetryData = json.dumps(dictTelemetryData, indent=2, sort_keys=True) PMGRPCDLOG.debug("After mitigation: %s" % (jsonTelemetryData)) if lib_pmgrpcd.OPTIONS.examplepath and lib_pmgrpcd.OPTIONS.example: examples(dictTelemetryData_mod, jsonTelemetryData) if lib_pmgrpcd.OPTIONS.jsondatadumpfile: PMGRPCDLOG.debug("Write jsondatadumpfile: %s" % (lib_pmgrpcd.OPTIONS.jsondatadumpfile)) with open(lib_pmgrpcd.OPTIONS.jsondatadumpfile, "a") as jsondatadumpfile: jsondatadumpfile.write(jsonTelemetryData) jsondatadumpfile.write("\n") # Filter only config. export = True if lib_pmgrpcd.OPTIONS.onlyopenconfig: PMGRPCDLOG.debug( "only openconfig filter matched because of options.onlyopenconfig: %s" % lib_pmgrpcd.OPTIONS.onlyopenconfig ) export = False if "encoding_path" in dictTelemetryData_mod["collector"]["data"]: if ( "openconfig" in dictTelemetryData_mod["collector"]["data"]["encoding_path"] ): export = True if export: export_metrics(jsonTelemetryData) return jsonTelemetryData pmacct-1.7.8/telemetry/decoders/v3/utils.py0000644000175000017500000000244214354105275017660 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import base64 def generate_content_from_raw(raw_file): with open(raw_file, "r") as fh: for line in fh: yield base64.b64decode(line.encode()) pmacct-1.7.8/telemetry/decoders/v3/config_files/0000755000175000017500000000000014354105275020573 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/config_files/avscmapfile0000644000175000017500000000000014354105275022776 0ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/config_files/mitigation.py0000644000175000017500000013254014354105275023316 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # # from datetime import datetime import pprint import json global mitigation mitigation = {} def mod_all_json_data(resdict): global mitigation mitigation = resdict.copy() if "collector" in mitigation: if ("grpc" in mitigation["collector"]) and ("data" in mitigation["collector"]): if "ne_vendor" in mitigation["collector"]["grpc"]: mod_all_pre() if mitigation["collector"]["grpc"]["ne_vendor"] == "Huawei": mod_huawei() elif mitigation["collector"]["grpc"]["ne_vendor"] == "Cisco": mod_cisco() mod_all_post() return mitigation def mod_all_pre(): global mitigation # especially Cisco oc_int has to have a Array after the "subinterface" but anyway it is good for all vendors in case it will be without array addanywayarray_subint() # Cisco oc_int has to have a Array after the "interface" but anyway it is good for all vendors in case it will be without array addanywayarray_int() # CHANGE ON EACH KEY THE DASH TO UNDERSCORE because avro only support underscore obj = mitigation.copy() mitigation = d2u(obj) def mod_huawei(): global mitigation # rename Huawei sensor_path to encoding_path because it has to match with the avroschema sens2enco() # "interface":[ # The parent container "interfaces" is missing for "interface" in case of Huawei # https://github.com/openconfig/public/blob/master/release/models/interfaces/openconfig-interfaces.yang#L1012 insert_rec_interfaces() # "admin_status":0, # "oper_status":0, # Huawei oc_interface "admin_status" and "oper_status" contains 0 or 1 but has to have "UP" or "DOWN" # https://github.com/openconfig/public/blob/master/release/models/interfaces/openconfig-interfaces.yang#L464 # https://github.com/openconfig/public/blob/master/release/models/interfaces/openconfig-interfaces.yang#L496 # because Huawei told us that the the hole section state is not in "acquisition path" of openconfig-interfaces i will remove all the leaves of "state". # only the section "counters" within the section "state" will be there remove_hua_state_with_ifindex0() #leaf admin-status and oper-status are type enumeration. #see https://github.com/openconfig/public.git -> public/release/models/interfaces/openconfig-interfaces.yang #"admin_status":1, -> "admin_status":"UP", #"oper_status":2, -> "oper_status":"DOWN", mod_hua_int_admin_and_oper_status_to_enum() mod_hua_subint_admin_and_oper_status_to_enum() # encoding_path of Hua has to be mach the jsondata: # "encoding_path":"openconfig-interfaces:interfaces\/interface\/state\/counters" -> "encoding_path":"openconfig-interfaces:interfaces", correct_huaw_enc_path() def mod_cisco(): global mitigation pass def mod_all_post(): global mitigation # https://github.com/openconfig/public/blob/master/release/models/interfaces/openconfig-interfaces.yang#L615 # "last_clear":"", # last_clear has to be epoch (integer) not string # https://github.com/openconfig/public/blob/master/release/models/interfaces/openconfig-interfaces.yang#L854 # https://tools.ietf.org/html/rfc6991 # typedef timeticks { # type uint32; # description # "The timeticks type represents a non-negative integer that # represents the time, modulo 2^32 (4294967296 decimal), in # # "in_unicast_pkts":"595769", # #oc_interface all counters of oc_int should be long mod_int_lastclear() mod_subint_lastclear() #In general all counter exept the last_clear has to be integer for interfaces and subinterfaces int_state_counters_2_integer() subint_state_counters_2_integer() # All collector meta-data part of collector -> data have to be all the time the correct data-type. # independent of the vendor or routertyp. # Only defined keys are allowed because of mandatory avroschema # In general remove all kv-pairs of record["collector"]["data"] except this ones: # "collection_end_time":1548319798771, # "collection_id":"3007", # "collection_start_time":1548319798741, # "encoding_path":"openconfig-interfaces:interfaces\/interface\/state\/counters", # "msg_timestamp":1548319798831, # "node_id_str":"ipi-zbb900-r-al-01", # "subscription_id_str":"DAISY63" harmonize_collector_data() #for hua #leaf last-change is type oc-types:timeticks64; #see https://github.com/openconfig/public.git -> public/release/models/interfaces/openconfig-interfaces.yang #"last_change":"1234567890", -> "last_change":1234567890, # #for cisco #"last_change":"2019-01-08T12:53:02Z", -> "last_change":1546951982, # #and also doing this (nothing) for already good cases: #"last_change":1234567890, -> "last_change":1234567890, mod_int_lastchange() mod_subint_lastchange() # Helper-Methods for ALL # --------------------------- def addanywayarray_subint(): if "encoding_path" in mitigation["collector"]["data"]: if ( mitigation["collector"]["data"]["encoding_path"] == "openconfig-interfaces:interfaces" ): if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: if "subinterfaces" in mitigation["interfaces"]["interface"]: if ( "subinterface" in mitigation["interfaces"]["interface"]["subinterfaces"] ): if ( type( mitigation["interfaces"]["interface"][ "subinterfaces" ]["subinterface"] ) == dict ): mitigation["interfaces"]["interface"]["subinterfaces"][ "subinterface" ] = [ mitigation["interfaces"]["interface"][ "subinterfaces" ]["subinterface"] ] def addanywayarray_int(): if "encoding_path" in mitigation["collector"]["data"]: if ( mitigation["collector"]["data"]["encoding_path"] == "openconfig-interfaces:interfaces" ): if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: if type(mitigation["interfaces"]["interface"]) == dict: mitigation["interfaces"]["interface"] = [ mitigation["interfaces"]["interface"] ] def d2u(obj): if isinstance(obj, (str, int, float)): return obj if isinstance(obj, dict): new = obj.__class__() for k, v in obj.items(): new[k.replace("-", "_")] = d2u(v) elif isinstance(obj, (list, set, tuple)): new = obj.__class__(d2u(v) for v in obj) else: return obj return new def harmonize_collector_data(): coldata = mitigation["collector"]["data"].copy() newcoldata = {} inttype = [ "collection_timestamp", "collection_end_time", "collection_start_time", "msg_timestamp", ] stringtype = [ "collection_id", "encoding_path", "node_id_str", "subscription_id_str", "encoding_type", ] for elem in mitigation["collector"]["data"]: if elem in inttype: newcoldata.update({elem: int(mitigation["collector"]["data"][elem])}) inttype.remove(elem) elif elem in stringtype: newcoldata.update({elem: str(mitigation["collector"]["data"][elem])}) stringtype.remove(elem) else: pass for elem in inttype: newcoldata.update({elem: -1}) for elem in stringtype: newcoldata.update({elem: "None"}) # newcoldata.update({"collection_timestamp": int(mitigation["collector"]["data"]["collection_timestamp"])}) # newcoldata.update({"collection_end_time": int(mitigation["collector"]["data"]["collection_end_time"])}) # newcoldata.update({"collection_id": str(mitigation["collector"]["data"]["collection_id"])}) # newcoldata.update({"collection_start_time": int(mitigation["collector"]["data"]["collection_start_time"])}) # newcoldata.update({"encoding_path": str(mitigation["collector"]["data"]["encoding_path"])}) # newcoldata.update({"msg_timestamp": int(mitigation["collector"]["data"]["msg_timestamp"])}) # newcoldata.update({"node_id_str": str(mitigation["collector"]["data"]["node_id_str"])}) # newcoldata.update({"subscription_id_str": str(mitigation["collector"]["data"]["subscription_id_str"])}) mitigation["collector"]["data"] = newcoldata # Helper-Methods for CISCO # --------------------------- def timestuff2epoch(lc): if isinstance(lc, int): lc_mod = lc else: try: # "last_clear":"2019-01-08T12:53:02Z", utc_dt = datetime.strptime(lc, "%Y-%m-%dT%H:%M:%SZ") timestamp = (utc_dt - datetime(1970, 1, 1)).total_seconds() except ValueError: try: int(lc) except ValueError: lc_mod = 0 else: lc_mod = int(lc) else: lc_mod = int(timestamp) return lc_mod def mod_int_lastclear(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for intelem in mitigation["interfaces"]["interface"]: intidx = mitigation["interfaces"]["interface"].index(intelem) if "state" in mitigation["interfaces"]["interface"][intidx]: if ("counters" in mitigation["interfaces"]["interface"][intidx]["state"]): for leave in mitigation["interfaces"]["interface"][intidx]["state"]["counters"]: if leave == "last_clear": lc = mitigation["interfaces"]["interface"][intidx]["state"]["counters"]["last_clear"] mitigation["interfaces"]["interface"][intidx]["state"]["counters"]["last_clear"] = timestuff2epoch(lc) if leave == "last-clear": lc = mitigation["interfaces"]["interface"][intidx]["state"]["counters"]["last-clear"] mitigation["interfaces"]["interface"][intidx]["state"]["counters"]["last-clear"] = timestuff2epoch(lc) def mod_subint_lastclear(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for intelem in mitigation["interfaces"]["interface"]: intidx = mitigation["interfaces"]["interface"].index(intelem) if ("subinterfaces" in mitigation["interfaces"]["interface"][intidx]): if ("subinterface" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]): for subintelem in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"]: subintidx = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"].index(subintelem) if ("state" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]): if ("counters" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]): for leave in mitigation["interfaces"][ "interface" ][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["counters"]: if leave == "last_clear": lc = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["counters"]["last_clear"] mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["counters"]["last_clear"] = timestuff2epoch(lc) if leave == "last-clear": lc = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["counters"]["last-clear"] mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["counters"]["last-clear"] = timestuff2epoch(lc) def mod_int_lastchange(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for intelem in mitigation["interfaces"]["interface"]: intidx = mitigation["interfaces"]["interface"].index(intelem) if "state" in mitigation["interfaces"]["interface"][intidx]: if ("last_change" in mitigation["interfaces"]["interface"][intidx]["state"]): lc = mitigation["interfaces"]["interface"][intidx]["state"]["last_change"] mitigation["interfaces"]["interface"][intidx]["state"]["last_change"] = timestuff2epoch(lc) if ("last-change" in mitigation["interfaces"]["interface"][intidx]["state"]): lc = mitigation["interfaces"]["interface"][intidx]["state"]["last-change"] mitigation["interfaces"]["interface"][intidx]["state"]["last-change"] = timestuff2epoch(lc) def mod_subint_lastchange(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for intelem in mitigation["interfaces"]["interface"]: intidx = mitigation["interfaces"]["interface"].index(intelem) if ("subinterfaces" in mitigation["interfaces"]["interface"][intidx]): if ("subinterface" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]): for subintelem in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"]: subintidx = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"].index(subintelem) if ("state" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]): if ("last_change" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]): lc = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["last_change"] mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["last_change"] = timestuff2epoch(lc) if ("last-change" in mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]): lc = mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["last-change"] mitigation["interfaces"]["interface"][intidx]["subinterfaces"]["subinterface"][subintidx]["state"]["last-change"] = timestuff2epoch(lc) # Helper-Methods for HUAWEI # --------------------------- def sens2enco(): if "collector" in mitigation: if "data" in mitigation["collector"]: if "sensor_path" in mitigation["collector"]["data"]: mitigation["collector"]["data"].update( {"encoding_path": mitigation["collector"]["data"]["sensor_path"]} ) del mitigation["collector"]["data"]["sensor_path"] def insert_rec_interfaces(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interface" in mitigation: if type(mitigation["interface"]) == list: mitigation.update( {"interfaces": {"interface": mitigation["interface"]}} ) del mitigation["interface"] def remove_hua_state_with_ifindex0(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: interface_list = list(mitigation["interfaces"]["interface"]) for elem in interface_list: idx = interface_list.index(elem) if "state" in interface_list[idx]: if "ifindex" in interface_list[idx]["state"]: if interface_list[idx]["state"]["ifindex"] == 0: if "counters" in interface_list[idx]["state"]: mitigation["interfaces"]["interface"][idx]["state"] = { "counters": mitigation["interfaces"]["interface"][idx]["state"]["counters"] } def mod_hua_int_admin_and_oper_status_to_enum(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: interface_list = list(mitigation["interfaces"]["interface"]) for elem in interface_list: idx = interface_list.index(elem) if "state" in interface_list[idx]: if "ifindex" in interface_list[idx]["state"]: if not interface_list[idx]["state"]["ifindex"] == 0: if "admin_status" in interface_list[idx]["state"]: if interface_list[idx]["state"]["admin_status"] == 0: mitigation["interfaces"]["interface"][idx]["state"]["admin_status"] = "INVALID" if interface_list[idx]["state"]["admin_status"] == 1: mitigation["interfaces"]["interface"][idx]["state"]["admin_status"] = "UP" if interface_list[idx]["state"]["admin_status"] == 2: mitigation["interfaces"]["interface"][idx]["state"]["admin_status"] = "DOWN" if interface_list[idx]["state"]["admin_status"] == 3: mitigation["interfaces"]["interface"][idx]["state"]["admin_status"] = "TESTING" if "oper_status" in interface_list[idx]["state"]: if interface_list[idx]["state"]["oper_status"] == 0: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "INVALID" if interface_list[idx]["state"]["oper_status"] == 1: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "UP" if interface_list[idx]["state"]["oper_status"] == 2: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "DOWN" if interface_list[idx]["state"]["oper_status"] == 3: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "TESTING" if interface_list[idx]["state"]["oper_status"] == 4: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "UNKNOWN" if interface_list[idx]["state"]["oper_status"] == 5: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "DORMANT" if interface_list[idx]["state"]["oper_status"] == 6: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "NOT_PRESENT" if interface_list[idx]["state"]["oper_status"] == 7: mitigation["interfaces"]["interface"][idx]["state"]["oper_status"] = "LOWER_LAYER_DOWN" def mod_hua_subint_admin_and_oper_status_to_enum(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: interface_list = list(mitigation["interfaces"]["interface"]) for elem in interface_list: idx = interface_list.index(elem) if "subinterfaces" in interface_list[idx]: if "subinterface" in interface_list[idx]["subinterfaces"]: subinterface_list = list(interface_list[idx]["subinterfaces"]["subinterface"]) for sub_elem in subinterface_list: subidx = subinterface_list.index(sub_elem) if "state" in subinterface_list[subidx]: if "ifindex" in subinterface_list[subidx]["state"]: if not subinterface_list[subidx]["state"]["ifindex"] == 0: if "admin_status" in subinterface_list[subidx]["state"]: if subinterface_list[subidx]["state"]["admin_status"] == 0: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["admin_status"] = "INVALID" if subinterface_list[subidx]["state"]["admin_status"] == 1: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["admin_status"] = "UP" if subinterface_list[subidx]["state"]["admin_status"] == 2: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["admin_status"] = "DOWN" if subinterface_list[subidx]["state"]["admin_status"] == 3: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["admin_status"] = "TESTING" if "oper_status" in subinterface_list[subidx]["state"]: if subinterface_list[subidx]["state"]["oper_status"] == 0: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "INVALID" if subinterface_list[subidx]["state"]["oper_status"] == 1: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "UP" if subinterface_list[subidx]["state"]["oper_status"] == 2: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "DOWN" if subinterface_list[subidx]["state"]["oper_status"] == 3: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "TESTING" if subinterface_list[subidx]["state"]["oper_status"] == 4: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "UNKNOWN" if subinterface_list[subidx]["state"]["oper_status"] == 5: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "DORMANT" if subinterface_list[subidx]["state"]["oper_status"] == 6: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "NOT_PRESENT" if subinterface_list[subidx]["state"]["oper_status"] == 7: mitigation["interfaces"]["interface"][idx]["subinterfaces"]["subinterface"][subidx]["state"]["oper_status"] = "LOWER_LAYER_DOWN" def int_state_counters_2_integer(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for elem in mitigation["interfaces"]["interface"]: idx = mitigation["interfaces"]["interface"].index(elem) if "state" in mitigation["interfaces"]["interface"][idx]: if ( "counters" in mitigation["interfaces"]["interface"][idx]["state"] ): for leave in mitigation["interfaces"]["interface"][idx][ "state" ]["counters"]: if not (leave == "last_clear"): try: int( mitigation["interfaces"]["interface"][ idx ]["state"]["counters"][leave] ) except ValueError: mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] = -1 else: mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] = int( mitigation["interfaces"]["interface"][ idx ]["state"]["counters"][leave] ) if ( mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] > 9223372036854775807 ): mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] = ( mitigation["interfaces"]["interface"][ idx ]["state"]["counters"][leave] - 9223372036854775808 ) else: try: int( mitigation["interfaces"]["interface"][ idx ]["state"]["counters"][leave] ) except ValueError: mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] = 0 else: mitigation["interfaces"]["interface"][idx][ "state" ]["counters"][leave] = int( mitigation["interfaces"]["interface"][ idx ]["state"]["counters"][leave] ) def subint_state_counters_2_integer(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: if "interfaces" in mitigation: if "interface" in mitigation["interfaces"]: for elem in mitigation["interfaces"]["interface"]: idx = mitigation["interfaces"]["interface"].index(elem) if ( "subinterfaces" in mitigation["interfaces"]["interface"][idx] ): if ( "subinterface" in mitigation["interfaces"]["interface"][idx][ "subinterfaces" ] ): for subelem in mitigation["interfaces"]["interface"][ idx ]["subinterfaces"]["subinterface"]: subidx = mitigation["interfaces"]["interface"][idx][ "subinterfaces" ]["subinterface"].index(subelem) if ( "state" in mitigation["interfaces"]["interface"][idx][ "subinterfaces" ]["subinterface"][subidx] ): if ( "counters" in mitigation["interfaces"]["interface"][ idx ]["subinterfaces"]["subinterface"][subidx][ "state" ] ): for leave in mitigation["interfaces"][ "interface" ][idx]["subinterfaces"]["subinterface"][ subidx ][ "state" ][ "counters" ]: if not (leave == "last_clear"): try: int( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] ) except ValueError: mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] = -1 else: mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] = int( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] ) if ( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] > 9223372036854775807 ): mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] = ( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] - 9223372036854775808 ) else: try: int( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] ) except ValueError: mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] = 0 else: mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] = int( mitigation["interfaces"][ "interface" ][idx]["subinterfaces"][ "subinterface" ][ subidx ][ "state" ][ "counters" ][ leave ] ) def correct_huaw_enc_path(): if "encoding_path" in mitigation["collector"]["data"]: if "openconfig-interfaces:" in mitigation["collector"]["data"]["encoding_path"]: mitigation["collector"]["data"][ "encoding_path" ] = "openconfig-interfaces:interfaces" if __name__ == "__mod_all_json_data__": mod_all_json_data pmacct-1.7.8/telemetry/decoders/v3/config_files/telemetry.conf0000644000175000017500000000120414354105275023451 0ustar paolopaolo[PMGRPCD] topic = randomtopic bsservers = kafkaservers urlscreg = url secproto = False sslcertloc = /path/ sslkeyloc = /path/ calocation = /path/ gpbmapfile = config_files/gpbmapfile.map avscmapfile = config_files/avscmapfile mitigation = True debug = True pmgrpcdlogfile = /tmp/logpmgrpcd.log serializelogfile = /tmp/logpmgrpcd_avro.log ipport = [::]:10000 workers = 20 processpool = 8 cisco = False cenctype = False example = False examplepath = /tmp/stexamples huawei = False zmq = True zmqipport = tcp://127.0.0.1:50000 kafkaavro = False onlyopenconfig = False flatten = True kafkasimple = false file_exporter_file = /tmp/file_test_output pmacct-1.7.8/telemetry/decoders/v3/config_files/gpbmapfile.map0000644000175000017500000000023614354105275023401 0ustar paolopaolohuawei-ifm = huawei_ifm_pb2.Ifm() huawei-devm = huawei_devm_pb2.Devm() openconfig-interfaces = openconfig_interfaces_pb2.Interfaces() pmacct-1.7.8/telemetry/decoders/v3/file_modules/0000755000175000017500000000000014354105275020613 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/file_modules/__init__.py0000644000175000017500000000000014354105275022712 0ustar paolopaolopmacct-1.7.8/telemetry/decoders/v3/file_modules/file_input.py0000644000175000017500000000323414354105275023325 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import time from export_pmgrpcd import export_metrics class FileInput(): def __init__(self, filename, max_metrics_per_packet = None, time_between_packets=None): self.filename = filename self.max_metrics_per_packet = max_metrics_per_packet self.time_between_packets = time_between_packets def generate(self): with open(self.filename, "r") as fh: for line in fh: export_metrics(line) if self.time_between_packets: time.sleep(self.time_between_packets) pmacct-1.7.8/telemetry/decoders/v3/file_modules/file_producer.py0000644000175000017500000000312314354105275024006 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from export_pmgrpcd import Exporter import os import ujson as json class FileExporter(Exporter): def __init__(self, output_file): self.output_file = output_file def process_metric(self, datajsonstring): jsondata = json.loads(datajsonstring) again_json = json.dumps(jsondata).replace("\n", "") # we'll probably remove the loading here with open(self.output_file, 'a') as fh: fh.write(again_json) fh.write("\n") pmacct-1.7.8/telemetry/decoders/v3/CONFIG-KEYS.pmgrpcd0000644000175000017500000002536314354105275021251 0ustar paolopaoloCONFIG-KEYS for pmgrpcd.py ================================================================= KEY: topic DESC: The Kafka topic name to produce to. It is a good idea to have a concept as topic, for example the following: [project].[env].[role]-[type]-[traffic] project: myproject env: dev, test, prod role: infra, flow, control, device, event type: metric, schema traffic: raw, proc infra producer is, e.g., pmacctd flow producer is, e.g., nfacctd control producer is, e.g., pmbmpd device producer is, e.g., pmgrpcd.py event producer is, e.g., nfacctd (ipfix-NEL) DEFAULT: none EXAMPLE: myproject.prod.device-metric-raw ----------------------------------------------------------------- KEY: bsservers DESC: One or multiple Kafka bootstrap servers DEFAULT: none EXAMPLE: kafka.single.boot.strap.server.net:9093 or "kafka.boot.strap.server.one.net:9093, kafka.boot.strap.server.two.net:9093, kafka.boot.strap.server.three.net:9093" ----------------------------------------------------------------- KEY: urlscreg DESC: The URL to the Schema Registry server where Avro schemas are registered. The server stores a 1:1 mapping among Avro schemas and Avro schema IDs. A client would supply a schema and be returned its ID; such ID is then used to serialize JSON metrics into Avro format. DEFAULT: none EXAMPLE: https://schema-registry.some.thing.net:443 ----------------------------------------------------------------- KEY: calocation DESC: The ca_location used to connect to Schema Registry DEFAULT: none EXAMPLE: /path/to/schema/registry/ssl/something_root_ca.crt ----------------------------------------------------------------- KEY: secproto DESC: security protocol DEFAULT: none EXAMPLE: ssl ----------------------------------------------------------------- KEY: sslcertloc DESC: Path/file to a SSL certification location DEFAULT: none EXAMPLE: /path/to/ssl/certificate/location/something.crt ----------------------------------------------------------------- KEY: sslkeyloc DESC: Path/file to a SSL key location DEFAULT: none EXAMPLE: /path/to/ssl/key/location/something.key ----------------------------------------------------------------- KEY: gpbmapfile DESC: This file is a way to keep the Python script as generic as possible. In this file further Python classes can be added in order to support more YANG models. pmgrpcd.py will read this file so to be able to unmarshall JSON metrics based on these Python libraries. DEFAULT: /etc/pmacct/telemetry/gpbmapfile.map EXAMPLE: huawei-ifm = huawei_ifm_pb2.Ifm() huawei-devm = huawei_devm_pb2.Devm() openconfig-interfaces = openconfig_interfaces_pb2.Interfaces() ----------------------------------------------------------------- KEY: avscmapfile DESC: This file is a JSON object. Based on this file, pmgrpcd.py is able to get the Avro schema to serialize the JSON metrics to Avro. pmgrpcd.py is getting JSON-encoded metrics from routers. The gRPC source IP address and YANG Encoding Path can also be found in the data. IP address being e.g. "10.215.133.15" and Encoding Path being e.g. "openconfig-interfaces:interfaces". Based on this mapping file it is possible to get the Avro Schema ID (ie. 249). With such ID it is possible to get the Avro schema from the Schema Registry server to serialize the JSON metrics to Avro. DEFAULT: /etc/pmacct/telemetry/schema_id_map_file.json EXAMPLE: { "10.215.133.15": { "openconfig-interfaces:interfaces": 249 "openconfig-platform:components": 365 }, "10.215.133.17": { "openconfig-interfaces:interfaces": 299 } } ----------------------------------------------------------------- KEY: mitigation DESC: The idea of this Python script is to have something like a plugin to mitigate JSON data problems. Streaming Telemetry today (1Q 2019) is not very well standardized. There are several pieces that vendors do in different ways. Also there are bugs (e.g.. missing values) and not correct implementations of the already existing standards. There are many optional parameters (e.g. some leafs) but also optional structures (i.e. records). For example: if there are multiple interfaces within the JSON message there has to be a record "interfaces" as parent of "interface"; whereas with only one interface within the message the record "interfaces" is optional. For Big Data (IT and data analytics) this is very hard to handle. The pmgrpcd.py (not the mitigation.py!) flattens data by splitting objects within the same message to multiple flat messages. It is possible with the mitigation script to mitigate JSON data before they are serialized. ie. all metrics must have a fixed data structure, like a parent "interfaces" array containing a single "interface" object. DEFAULT: /etc/pmacct/telemetry/mitigation.py EXAMPLE: see default file: /etc/pmacct/telemetry/mitigation.py ----------------------------------------------------------------- KEY: debug DESC: Enable debug DEFAULT: False EXAMPLE: False ----------------------------------------------------------------- KEY: pmgrpcdlogfile DESC: This logfile is for collection events of pmgrpcd.py DEFAULT: /var/log/pmgrpcd.log EXAMPLE: /var/log/pmgrpcd.log ----------------------------------------------------------------- KEY: serializelogfile DESC: This logfile if for data serialization events of pmgrpcd.py DEFAULT: /var/log/pmgrpcd_avro.log EXAMPLE: /var/log/pmgrpcd_avro.log ----------------------------------------------------------------- KEY: ipport DESC: IP address and port the daemon pmgrpcd.py listens on. By default the daemon listens on all interfaces on port 10000. DEFAULT: [::]:10000 EXAMPLE: [::]:10000 ----------------------------------------------------------------- KEY: workers DESC: Number of worker threads to process input data. DEFAULT: 20 EXAMPLE: 20 ----------------------------------------------------------------- KEY: processpool DESC: Number of processes within the ProcessPool of Kafka Avro exporter. DEFAULT: 8 EXAMPLE: 8 ----------------------------------------------------------------- KEY: cisco DESC: Enable/disable processing of metrics produced by Cisco devices DEFAULT: True EXAMPLE: True ----------------------------------------------------------------- KEY: huawei DESC: Enable/disable processing of metrics produced by Huawei devices DEFAULT: True EXAMPLE: True ----------------------------------------------------------------- KEY: cenctype DESC: cenctype is the type of encoding for cisco. This is because some protofiles are incompatible. With cenctype=gpbkv only cisco is enabled. The encoding type can be json, gpbcomp, gpbkv DEFAULT: json EXAMPLE: json, gpbcomp, gpbkv ----------------------------------------------------------------- KEY: example DESC: Enable/disable flag to produce example files for different network elements. If this flag is enabled example path files for each network element (NE) for each YANG model are going to be generated. In this file there will be an example (the first message of each NE/YANG model) where to look for what is being serialized to Avro for production to Kafka. DEFAULT: True EXAMPLE: True ----------------------------------------------------------------- KEY: examplepath DESC: The directory where example files will be produced to. DEFAULT: /tmp/stexamples EXAMPLE: /tmp/stexamples ----------------------------------------------------------------- KEY: jsondatafile DESC: This ioption is to serialize manually with avscid and jsondatafile (for development) DEFAULT: /tmp/stexamples/jsondatafile.json EXAMPLE: /tmp/stexamples/jsondatafile.json ----------------------------------------------------------------- KEY: rawdatafile DESC: This option is to process manually (via mitigation) process a rawdatafile with a single rawrecord (for development) DEFAULT: /tmp/stexamples/rawdatafile.json EXAMPLE: /tmp/stexamples/rawdatafile.json ----------------------------------------------------------------- KEY: jsondatadumpfile DESC: If enabled, mitigated metrics will be dumped to this file. With this file it is possible to find Avro schema mismatching problems. DEFAULT: /tmp/stexamples/jsondatadumpfile.json EXAMPLE: /tmp/stexamples/jsondatadumpfile.json ----------------------------------------------------------------- KEY: rawdatadumpfile DESC: If enabled, raw data collected by pmgrpcd.py will be dumped to this file. With this file it is possible to troubleshoot issues related to data structures. DEFAULT: /tmp/stexamples/rawdatadumpfile.json EXAMPLE: /tmp/stexamples/rawdatadumpfile.json ----------------------------------------------------------------- KEY: zmq DESC: Enable ZMQ forwarding. Output encoding is JSON. DEFAULT: False EXAMPLE: False ----------------------------------------------------------------- KEY: zmqipport DESC: Specify IP address and port for ZMQ forwarding. DEFAULT: tcp://127.0.0.1:50000 EXAMPLE: tcp://127.0.0.1:50000 ----------------------------------------------------------------- KEY: kafkaavro DESC: Enable/disable forwarding to Kafka and serializing to Avro. DEFAULT: True EXAMPLE: True ----------------------------------------------------------------- KEY: kafkasimple DESC: Enable/disable forwarding to Kafka and serializing to JSON. Also, optionally flatten output objects, see 'flatten'. DEFAULT: False EXAMPLE: False ----------------------------------------------------------------- KEY: flatten DESC: Enable/disable flattening of complex (ie. nested) input objects into multiple simpler ones suitable to be ingested in a Big Data system. DEFAULT: True EXAMPLE: True ----------------------------------------------------------------- KEY: onlyopenconfig DESC: Enable/disable vendor-specific YANG models leaving only the vendor independent ones, ie. openconfig or IETF ones. DEFAULT: False EXAMPLE: False ----------------------------------------------------------------- pmacct-1.7.8/telemetry/decoders/v3/huawei_pmgrpcd.py0000644000175000017500000002160514354105275021520 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import huawei_grpc_dialout_pb2_grpc from lib_pmgrpcd import PMGRPCDLOG import ujson as json import lib_pmgrpcd from google.protobuf.json_format import MessageToDict import time from datetime import datetime from export_pmgrpcd import FinalizeTelemetryData import base64 # TODO: Maybe move this to its own part, who knows import huawei_ifm_pb2 import huawei_devm_pb2 import openconfig_interfaces_pb2 if lib_pmgrpcd.OPTIONS.huawei and (not lib_pmgrpcd.OPTIONS.cenctype == 'gpbkv'): import huawei_telemetry_pb2 class gRPCDataserviceServicer(huawei_grpc_dialout_pb2_grpc.gRPCDataserviceServicer): def __init__(self): PMGRPCDLOG.info("Huawei: Initializing gRPCDataserviceServicer()") def dataPublish(self, message, context): grpcPeer = {} grpcPeerStr = context.peer() ( grpcPeer["telemetry_proto"], grpcPeer["telemetry_node"], grpcPeer["telemetry_node_port"], ) = grpcPeerStr.split(":") grpcPeer["ne_vendor"] = "Huawei" PMGRPCDLOG.debug("Huawei MdtDialout Message: %s" % grpcPeer["telemetry_node"]) metadata = dict(context.invocation_metadata()) grpcPeer["user-agent"] = metadata["user-agent"] # Example of grpcPeerStr -> 'ipv4:10.215.133.23:57775' grpcPeer["grpc_processing"] = "huawei_grpc_dialout_pb2_grpc" grpcPeer["grpc_ulayer"] = "GPB Telemetry" jsonTelemetryNode = json.dumps(grpcPeer, indent=2, sort_keys=True) PMGRPCDLOG.debug("Huawei RAW Message: %s" % jsonTelemetryNode) for new_msg in message: PMGRPCDLOG.debug("Huawei new_msg iteration message") if lib_pmgrpcd.OPTIONS.ip: if grpcPeer["telemetry_node"] != lib_pmgrpcd.OPTIONS.ip: continue PMGRPCDLOG.debug( "Huawei: ip filter matched with ip %s" % (lib_pmgrpcd.OPTIONS.ip) ) try: huawei_processing(grpcPeer, new_msg) except Exception as e: PMGRPCDLOG.debug("Error processing Huawei packet, error is %s", e) continue return yield def huawei_processing(grpcPeer, new_msg): PMGRPCDLOG.debug("Huawei: Received GRPC-Data") try: telemetry_msg = huawei_telemetry_pb2.Telemetry() telemetry_msg.ParseFromString(new_msg.data) except Exception as e: PMGRPCDLOG.error( "instancing or parsing data failed with huawei_telemetry_pb2.Telemetry" ) PMGRPCDLOG.error("ERROR: %s" % (e)) raise try: telemetry_msg_dict = MessageToDict( telemetry_msg, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) except Exception as e: PMGRPCDLOG.error( "instancing or parsing data failed with huawei_telemetry_pb2.Telemetry" ) raise PMGRPCDLOG.debug("Huawei: Received GPB-Data as JSON") # TODO: Do we really need this? it can be expensive PMGRPCDLOG.debug(json.dumps(telemetry_msg_dict, indent=2, sort_keys=True)) message_header_dict = telemetry_msg_dict.copy() if "data_gpb" in message_header_dict: del message_header_dict["data_gpb"] (proto, path) = message_header_dict["sensor_path"].split(":") (node_id_str) = message_header_dict["node_id_str"] (node_ip) = grpcPeer["telemetry_node"] (ne_vendor) = grpcPeer["ne_vendor"] # Get the maching L3-Methode msg = select_gbp_methode(proto) if msg: elem = len(telemetry_msg.data_gpb.row) epochmillis = int(round(time.time() * 1000)) PMGRPCDLOG.info( "EPOCH=%-10s NIP=%-15s NID=%-20s VEN=%-7s PT=%-22s ET=%-12s ELEM:%s" % (epochmillis, node_ip, node_id_str, ne_vendor, proto, "GPB", elem) ) # L2: for new_row in telemetry_msg.data_gpb.row: # PMGRPCDLOG.info("NEW_ROW: %s" % (new_row)) new_row_header_dict = MessageToDict( new_row, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) if "content" in new_row_header_dict: del new_row_header_dict["content"] # L3: msg.ParseFromString(new_row.content) content = MessageToDict( msg, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) message_dict = {} message_dict.update( { "collector": { "grpc": { "grpcPeer": grpcPeer["telemetry_node"], "ne_vendor": grpcPeer["ne_vendor"], } } } ) message_dict["collector"].update({"data": message_header_dict.copy()}) message_dict["collector"]["data"].update(new_row_header_dict) message_dict.update(content) # dump the raw data if lib_pmgrpcd.OPTIONS.rawdatadumpfile: PMGRPCDLOG.debug("Write rawdatadumpfile: %s" % (lib_pmgrpcd.OPTIONS.rawdatadumpfile)) with open(lib_pmgrpcd.OPTIONS.rawdatadumpfile, "a") as rawdatadumpfile: rawdatadumpfile.write(json.dumps(message_dict, indent=2, sort_keys=True)) rawdatadumpfile.write("\n") allkeys = parse_dict(content, ret="", level=0) PMGRPCDLOG.debug("Huawei: %s: %s" % (proto, allkeys)) try: returned = FinalizeTelemetryData(message_dict) except Exception as e: PMGRPCDLOG.error("Error finalizing message: %s", e) # TODO, probably better to have this in the object MAP_DICT = None def get_gpbmapfile(): global MAP_DICT if MAP_DICT is None: with open(lib_pmgrpcd.OPTIONS.gpbmapfile, "r") as file: MAP_DICT = {} for line in file: (k, v) = line.split("=") # a.e. "huawei-ifm" = 'huawei_ifm_pb2.Ifm()' MAP_DICT.update({k.lstrip().rstrip(): v.lstrip().rstrip()}) PMGRPCDLOG.debug("MAP_DICT: %s", MAP_DICT) return MAP_DICT def select_gbp_methode(proto): try: map_dict = get_gpbmapfile() except: PMGRPCDLOG.error( "Error getting the map dict" ) raise if proto in map_dict: PMGRPCDLOG.debug( "I FOUND THE GPB (%s) FOR PROTO (%s)" % (proto, map_dict[proto]) ) # TODO: I am pretty sure we can do something better than this. msg = eval(map_dict[proto]) return msg else: PMGRPCDLOG.debug("MISSING GPB Methode for PROTO: %s", proto) lib_pmgrpcd.MISSGPBLIB.update({proto: str(datetime.now())}) return False def parse_dict(init, ret, level): level += 1 if isinstance(init, dict): for key, val in init.items(): if isinstance(val, dict): if level == 1: if key != "grpc": ret = ret + "|" + key else: ret = ret + "->" + key ret = parse_dict(val, ret, level) if isinstance(val, list): for liit in val: ind = val.index(liit) if isinstance(liit, dict): if level == 1: if liit != "grpc": ret = ret + "|" + key + "->[" + str(ind) + "]" else: ret = ret + "->" + key + "->[" + str(ind) + "]" ret = parse_dict(liit, ret, level) return ret pmacct-1.7.8/telemetry/decoders/v3/requirements.txt0000644000175000017500000000011414354105275021424 0ustar paolopaoloujson pyzmq grpcio-tools avro-python3 requests confluent-kafka[avro] pytest pmacct-1.7.8/telemetry/decoders/v3/cisco_pmgrpcd.py0000644000175000017500000002203214354105275021331 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # from lib_pmgrpcd import PMGRPCDLOG import cisco_grpc_dialout_pb2_grpc from google.protobuf.json_format import MessageToDict import ujson as json import lib_pmgrpcd import time from export_pmgrpcd import FinalizeTelemetryData import base64 if lib_pmgrpcd.OPTIONS.cenctype == 'gpbkv': import cisco_telemetry_pb2 class gRPCMdtDialoutServicer(cisco_grpc_dialout_pb2_grpc.gRPCMdtDialoutServicer): def __init__(self): PMGRPCDLOG.info("Cisco: Initializing gRPCMdtDialoutServicer()") def MdtDialout(self, msg_iterator, context): try: grpcPeer = {} grpcPeerStr = context.peer() ( grpcPeer["telemetry_proto"], grpcPeer["telemetry_node"], grpcPeer["telemetry_node_port"], ) = grpcPeerStr.split(":") grpcPeer["ne_vendor"] = "Cisco" PMGRPCDLOG.debug("Cisco MdtDialout Message: %s" % grpcPeer["telemetry_node"]) # cisco_processing(grpcPeer, message, context) metadata = dict(context.invocation_metadata()) grpcPeer["user-agent"] = metadata["user-agent"] # Example of grpcPeerStr -> 'ipv4:10.215.133.23:57775' grpcPeer["grpc_processing"] = "cisco_grpc_dialout_pb2_grpc" grpcPeer["grpc_ulayer"] = "GPB Telemetry" jsonTelemetryNode = json.dumps(grpcPeer, indent=2, sort_keys=True) PMGRPCDLOG.debug("Cisco connection info: %s" % jsonTelemetryNode) for new_msg in msg_iterator: PMGRPCDLOG.debug("Cisco new_msg iteration message") # filter msgs that do not match the IP option if enabled. if lib_pmgrpcd.OPTIONS.ip: if grpcPeer["telemetry_node"] != lib_pmgrpcd.OPTIONS.ip: continue PMGRPCDLOG.debug( "Cisco: ip filter matched with ip %s" % (lib_pmgrpcd.OPTIONS.ip) ) try: cisco_processing(grpcPeer, new_msg) except Exception as e: PMGRPCDLOG.debug("Error processing Cisco packet, error is %s", e) continue except Exception as e: print(type(e)) print(e.args) return yield def process_cisco_kv(new_msg): """ Processes a msg using gpb-kv """ telemetry_msg = cisco_telemetry_pb2.Telemetry() telemetry_msg.ParseFromString(new_msg.data) #jsonStrTelemetry = MessageToJson(telemetry_msg) #grpc_message = json.loads(jsonStrTelemetry) grpc_message = MessageToDict(telemetry_msg) return grpc_message def cisco_processing(grpcPeer, new_msg): messages = {} grpc_message = {} encoding_type = None PMGRPCDLOG.debug("Cisco: Received GRPC-Data") PMGRPCDLOG.debug(new_msg.data) # Find the encoding of the packet try: encoding_type, grpc_message = find_encoding_and_decode(new_msg) except Exception as e: PMGRPCDLOG.error("Error decoding packet. Error is {}".format(e)) PMGRPCDLOG.debug("encoding_type is: %s\n" % (encoding_type)) if (encoding_type == "unknown") or encoding_type is None: print("encoding_type is unknown.") if (encoding_type == "unknown") or encoding_type is None: raise Exception("Encoding type unknown") message_header_dict = grpc_message.copy() if "data_json" in message_header_dict: del message_header_dict["data_json"] PMGRPCDLOG.debug("Header:%s", message_header_dict) (node_ip) = grpcPeer["telemetry_node"] (ne_vendor) = grpcPeer["ne_vendor"] epochmillis = int(round(time.time() * 1000)) if encoding_type == "ciscojson": message_header_dict.update({"encoding_type": encoding_type}) (proto, path) = message_header_dict["encoding_path"].split(":") (node_id_str) = message_header_dict["node_id_str"] elem = len(grpc_message["data_json"]) messages = grpc_message["data_json"] elif encoding_type == "ciscogrpckv": message_header_dict.update({"encoding_type": encoding_type}) message_header_dict["encoding_path"] = message_header_dict.pop("encodingPath") message_header_dict["node_id_str"] = message_header_dict.pop("nodeIdStr") message_header_dict["msg_timestamp"] = message_header_dict.pop("msgTimestamp") message_header_dict["subscription_id_str"] = message_header_dict.pop( "subscriptionIdStr" ) (proto, path) = message_header_dict["encoding_path"].split(":") (node_id_str) = message_header_dict["node_id_str"] if "dataGpbkv" in grpc_message: elem = len(grpc_message["dataGpbkv"]) messages = grpc_message["dataGpbkv"] else: elem = 0 messages = {} PMGRPCDLOG.info( "EPOCH=%-10s NIP=%-15s NID=%-20s VEN=%-7s PT=%-22s ET=%-12s ELEM=%s", epochmillis, node_ip, node_id_str, ne_vendor, proto, encoding_type, elem, ) # A single telemetry packet can contain multiple msgs (each having their own key/values). # here we are processing them one by one. for listelem in messages: # Copy the necessary metadata to the packet. PMGRPCDLOG.debug("LISTELEM: %s", listelem) message_dict = {} message_dict.update({"collector": {"grpc": {}}}) message_dict["collector"]["grpc"].update( {"grpcPeer": grpcPeer["telemetry_node"]} ) message_dict["collector"]["grpc"].update({"ne_vendor": grpcPeer["ne_vendor"]}) message_dict["collector"].update({"data": message_header_dict}) if encoding_type == "ciscojson": PMGRPCDLOG.debug("TEST: %s | %s", path, listelem["content"]) message_dict.update({path: listelem["content"]}) elif encoding_type == "ciscogrpckv": PMGRPCDLOG.debug("TEST: %s | %s", path, listelem["fields"]) message_dict.update({path: listelem["fields"]}) # allkeys = parse_dict(listelem, ret='', level=0) # PMGRPCDLOG.info("Cisco: %s: %s" % (proto, allkeys)) # dump the raw data if lib_pmgrpcd.OPTIONS.rawdatadumpfile: PMGRPCDLOG.debug("Write rawdatadumpfile: %s" % (lib_pmgrpcd.OPTIONS.rawdatadumpfile)) with open(lib_pmgrpcd.OPTIONS.rawdatadumpfile, "a") as rawdatadumpfile: rawdatadumpfile.write(json.dumps(message_dict, indent=2, sort_keys=True)) rawdatadumpfile.write("\n") try: returned = FinalizeTelemetryData(message_dict) except Exception as e: PMGRPCDLOG.error("Error finalizing message: %s", e) def find_encoding_and_decode(new_msg): encoding_type = None grpc_message = {} # TODO. If options force one type, only try that one. # Maybe it is json if lib_pmgrpcd.OPTIONS.cenctype == 'json': PMGRPCDLOG.debug("Try to parse json") try: grpc_message = json.loads(new_msg.data) encoding_type = "ciscojson" except Exception as e: PMGRPCDLOG.debug( "ERROR: Direct json parsing of grpc_message failed with message:\n%s\n", e ) else: return encoding_type, grpc_message elif lib_pmgrpcd.OPTIONS.cenctype == 'gpbkv': PMGRPCDLOG.debug("Try to unmarshall KV") if encoding_type is None: try: grpc_message = process_cisco_kv(new_msg) encoding_type = "ciscogrpckv" except Exception as e: PMGRPCDLOG.debug( "ERROR: Parsing of json after unmarshall KV failed with message:\n%s\n", e, ) else: return encoding_type, grpc_message elif lib_pmgrpcd.OPTIONS.cenctype == 'gpbcomp': PMGRPCDLOG.debug("Try to unmarshall compact mode") PMGRPCDLOG.debug("TODO") encoding_type = "unknown" return encoding_type, grpc_message pmacct-1.7.8/telemetry/decoders/v3/lib_pmgrpcd.py0000644000175000017500000000654514354105275021012 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2020 by: # # Matthias Arnold # Raphaël P. Barazzutti # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import logging from pathlib import Path SCRIPTVERSION = "3.2" class FileNotFound(Exception): pass PMGRPCDLOG = logging.getLogger("PMGRPCDLOG") OPTIONS = None MISSGPBLIB = {} SERIALIZELOG = None def init_pmgrpcdlog(): global PMGRPCDLOG, OPTIONS PMGRPCDLOG.setLevel(logging.DEBUG) grformatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) # create file handler which logs even debug messages grfh = logging.FileHandler(OPTIONS.PMGRPCDLOGfile) if OPTIONS.debug: grfh.setLevel(logging.DEBUG) else: grfh.setLevel(logging.INFO) grfh.setFormatter(grformatter) PMGRPCDLOG.addHandler(grfh) if OPTIONS.console: # create console handler with a higher log level grch = logging.StreamHandler() if OPTIONS.debug: grch.setLevel(logging.DEBUG) else: grch.setLevel(logging.INFO) grch.setFormatter(grformatter) PMGRPCDLOG.addHandler(grch) def init_serializelog(): global SERIALIZELOG SERIALIZELOG = logging.getLogger("SERIALIZELOG") SERIALIZELOG.setLevel(logging.DEBUG) seformatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) # create file handler which logs even debug messages sefh = logging.FileHandler(OPTIONS.serializelogfile) if OPTIONS.debug: sefh.setLevel(logging.DEBUG) else: sefh.setLevel(logging.INFO) sefh.setFormatter(seformatter) SERIALIZELOG.addHandler(sefh) if OPTIONS.console: # create console handler with a higher log level sech = logging.StreamHandler() if OPTIONS.debug: sech.setLevel(logging.DEBUG) else: sech.setLevel(logging.INFO) sech.setFormatter(seformatter) SERIALIZELOG.addHandler(sech) def signalhandler(signum, frame): global MISSGPBLIB # pkill -USR1 -e -f "python.*pmgrpc" if signum == 10: PMGRPCDLOG.info("Signal handler called with USR1 signal: %s" % (signum)) PMGRPCDLOG.info("These are the missing gpb libs: %s" % (MISSGPBLIB)) if signum == 12: PMGRPCDLOG.info("Signal handler called with USR2 signal: %s" % (signum)) PMGRPCDLOG.info("TODO: %s" % ("todo")) pmacct-1.7.8/telemetry/decoders/v1/0000755000175000017500000000000014354105275016142 5ustar paolopaolopmacct-1.7.8/telemetry/decoders/v1/cisco_grpc_dialout_server.py0000755000175000017500000001161514354105275023745 0ustar paolopaolo#!/usr/bin/env python # # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2018 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # from concurrent import futures import sys, getopt import ujson as json import zmq import time # gRPC and Protobuf imports import grpc from google.protobuf.json_format import MessageToJson from google.protobuf.json_format import MessageToDict import cisco_grpc_dialout_pb2 import cisco_grpc_dialout_pb2_grpc import cisco_telemetry_pb2 import cisco_ifstatsbag_generic_pb2 _ONE_DAY_IN_SECONDS = 60 * 60 * 24 debug = False zmqContext = None zmqSock = None class gRPCMdtDialoutServicer(cisco_grpc_dialout_pb2_grpc.gRPCMdtDialoutServicer): def __init__(self): print "Initializing gRPCMdtDialoutServicer()" def MdtDialout(self, message, context): grpcPeerStr = context.peer() grpcPeer = {} (grpcPeerProto, grpcPeer['telemetry_node'], grpcPeer['telemetry_node_port']) = grpcPeerStr.split(":") grpcPeer['telemetry_node_vendor'] = "Cisco" jsonTelemetryNode = json.dumps(grpcPeer) for new_msg in message: telemetry_msg = cisco_telemetry_pb2.Telemetry() telemetry_msg.ParseFromString(new_msg.data) jsonStrTelemetry = MessageToJson(telemetry_msg) dictTelemetry = json.loads(jsonStrTelemetry) (proto, path) = telemetry_msg.encoding_path.split(":") if (proto == "Cisco-IOS-XR-infra-statsd-oper"): for new_row in telemetry_msg.data_gpb.row: dictIfStats = {} ifStats_msg = cisco_ifstatsbag_generic_pb2.ifstatsbag_generic() ifStats_msg.ParseFromString(new_row.content) dictIfStatsContent = MessageToDict(ifStats_msg, including_default_value_fields = True, preserving_proto_field_name = True, use_integers_for_enums = True) dictIfStats['row'] = {} dictIfStats['row']['content'] = dictIfStatsContent dictIfStats['row']['timestamp'] = new_row.timestamp dictTelemetry['dataGpb'] = dictIfStats sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) else: sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) def sendJsonTelemetryData(jsonTelemetryNode, dictTelemetryData): global debug global zmqSock jsonTelemetryData = json.dumps(dictTelemetryData) if debug: print "dataPublish(): +++" print "dataPublish(): " + jsonTelemetryNode print "dataPublish(): " + jsonTelemetryData print "dataPublish(): ---" if not zmqSock.closed: try: zmqSock.send("%s" % jsonTelemetryNode, flags=zmq.SNDMORE) zmqSock.send("%s" % jsonTelemetryData) except ZMQError: pass def usage(tool): print "" print "Usage: %s [Args]" % tool print "" print "Optional Args:" print " -h, --help".ljust(25) + "Print this help" print " -d, --debug".ljust(25) + "Enable debug [default: no]" print " -g, --grpc-port".ljust(25) + "Set the port for input gRPC sessions [default: '10001']" print " -Z, --zmq-host".ljust(25) + "Set the ZeroMQ host for output [default: '127.0.0.1']" print " -z, --zmq-port".ljust(25) + "Set the ZeroMQ port for output [default: '50001']" def serve(): global debug global zmqContext global zmqSock try: opts, args = getopt.getopt(sys.argv[1:], "hdg:Z:z:", ["help", "debug", "grpc-port=", "zmq-host=", "zmq-port="]) except getopt.GetoptError as err: print str(err) usage(sys.argv[0]) sys.exit(1) # Defaults debug = False grpc_port = 10001 zmq_host = "127.0.0.1" zmq_port = 50001 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit(0) elif o in ("-d", "--debug"): debug = True elif o in ("-g", "--grpc-port"): grpc_port = a elif o in ("-Z", "--zmq-host"): zmq_host = a elif o in ("-z", "--zmq-port"): zmq_port = a else: assert False, "unhandled option" zmqBindStr = "tcp://" + zmq_host + ":" + str(zmq_port) gRPCBindStr = "[::]:" + str(grpc_port) zmqContext = zmq.Context() zmqSock = zmqContext.socket(zmq.PUSH) zmqSock.bind(zmqBindStr) gRPCserver = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) cisco_grpc_dialout_pb2_grpc.add_gRPCMdtDialoutServicer_to_server(gRPCMdtDialoutServicer(), gRPCserver) gRPCserver.add_insecure_port(gRPCBindStr) gRPCserver.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: gRPCserver.stop(0) if __name__ == '__main__': serve() pmacct-1.7.8/telemetry/decoders/v1/huawei_grpc_dialout_server.py0000755000175000017500000001440714354105275024131 0ustar paolopaolo#!/usr/bin/env python # # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2018 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # from concurrent import futures import sys, getopt import ujson as json import zmq import time # gRPC and Protobuf imports import grpc from google.protobuf.json_format import MessageToJson from google.protobuf.json_format import MessageToDict import huawei_grpc_dialout_pb2 import huawei_grpc_dialout_pb2_grpc import huawei_telemetry_pb2 import huawei_ifm_pb2 import huawei_devm_pb2 import openconfig_interfaces_pb2 _ONE_DAY_IN_SECONDS = 60 * 60 * 24 debug = False zmqContext = None zmqSock = None class gRPCDataserviceServicer(huawei_grpc_dialout_pb2_grpc.gRPCDataserviceServicer): def __init__(self): print "Initializing gRPCDataserviceServicer()" def dataPublish(self, message, context): grpcPeerStr = context.peer() grpcPeer = {} (grpcPeerProto, grpcPeer['telemetry_node'], grpcPeer['telemetry_node_port']) = grpcPeerStr.split(":") grpcPeer['telemetry_node_vendor'] = "Huawei" jsonTelemetryNode = json.dumps(grpcPeer) for new_msg in message: telemetry_msg = huawei_telemetry_pb2.Telemetry() telemetry_msg.ParseFromString(new_msg.data) jsonStrTelemetry = MessageToJson(telemetry_msg) dictTelemetry = json.loads(jsonStrTelemetry) (proto, path) = telemetry_msg.sensor_path.split(":") if (proto == "huawei-ifm"): for new_row in telemetry_msg.data_gpb.row: dictHuaweiIfm = {} huaweiIfm_msg = huawei_ifm_pb2.Ifm() huaweiIfm_msg.ParseFromString(new_row.content) dictHuaweiIfmContent = MessageToDict(huaweiIfm_msg, including_default_value_fields = True, preserving_proto_field_name = True, use_integers_for_enums = True) dictHuaweiIfm['row'] = {} dictHuaweiIfm['row']['content'] = dictHuaweiIfmContent dictHuaweiIfm['row']['timestamp'] = new_row.timestamp dictTelemetry['dataGpb'] = dictHuaweiIfm sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) elif (proto == "huawei-devm"): for new_row in telemetry_msg.data_gpb.row: dictHuaweiDevm = {} huaweiDevm_msg = huawei_devm_pb2.Devm() huaweiDevm_msg.ParseFromString(new_row.content) dictHuaweiDevmContent = MessageToDict(huaweiDevm_msg, including_default_value_fields = True, preserving_proto_field_name = True, use_integers_for_enums = True) dictHuaweiDevm['row'] = {} dictHuaweiDevm['row']['content'] = dictHuaweiDevmContent dictHuaweiDevm['row']['timestamp'] = new_row.timestamp dictTelemetry['dataGpb'] = dictHuaweiDevm sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) elif (proto == "openconfig-interfaces"): for new_row in telemetry_msg.data_gpb.row: dictOcInterfaces = {} ocInterfaces_msg = openconfig_interfaces_pb2.Interfaces() ocInterfaces_msg.ParseFromString(new_row.content) dictOcInterfacesContent = MessageToDict(ocInterfaces_msg, including_default_value_fields = True, preserving_proto_field_name = True, use_integers_for_enums = True) dictOcInterfaces['row'] = {} dictOcInterfaces['row']['content'] = dictOcInterfacesContent dictOcInterfaces['row']['timestamp'] = new_row.timestamp dictTelemetry['dataGpb'] = dictOcInterfaces sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) else: sendJsonTelemetryData(jsonTelemetryNode, dictTelemetry) def sendJsonTelemetryData(jsonTelemetryNode, dictTelemetryData): global debug global zmqSock jsonTelemetryData = json.dumps(dictTelemetryData) if debug: print "dataPublish(): +++" print "dataPublish(): " + jsonTelemetryNode print "dataPublish(): " + jsonTelemetryData print "dataPublish(): ---" if not zmqSock.closed: try: zmqSock.send("%s" % jsonTelemetryNode, flags=zmq.SNDMORE) zmqSock.send("%s" % jsonTelemetryData) except ZMQError: pass def usage(tool): print "" print "Usage: %s [Args]" % tool print "" print "Optional Args:" print " -h, --help".ljust(25) + "Print this help" print " -d, --debug".ljust(25) + "Enable debug [default: no]" print " -g, --grpc-port".ljust(25) + "Set the port for input gRPC sessions [default: '10000']" print " -Z, --zmq-host".ljust(25) + "Set the ZeroMQ host for output [default: '127.0.0.1']" print " -z, --zmq-port".ljust(25) + "Set the ZeroMQ port for output [default: '50000']" def serve(): global debug global zmqContext global zmqSock try: opts, args = getopt.getopt(sys.argv[1:], "hdg:Z:z:", ["help", "debug", "grpc-port=", "zmq-host=", "zmq-port="]) except getopt.GetoptError as err: print str(err) usage(sys.argv[0]) sys.exit(1) # Defaults debug = False grpc_port = 10001 zmq_host = "127.0.0.1" zmq_port = 50001 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit(0) elif o in ("-d", "--debug"): debug = True elif o in ("-g", "--grpc-port"): grpc_port = a elif o in ("-Z", "--zmq-host"): zmq_host = a elif o in ("-z", "--zmq-port"): zmq_port = a else: assert False, "unhandled option" zmqBindStr = "tcp://" + zmq_host + ":" + str(zmq_port) gRPCBindStr = "[::]:" + str(grpc_port) zmqContext = zmq.Context() zmqSock = zmqContext.socket(zmq.PUSH) zmqSock.bind(zmqBindStr) gRPCserver = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) huawei_grpc_dialout_pb2_grpc.add_gRPCDataserviceServicer_to_server(gRPCDataserviceServicer(), gRPCserver) gRPCserver.add_insecure_port(gRPCBindStr) gRPCserver.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: gRPCserver.stop(0) if __name__ == '__main__': serve() pmacct-1.7.8/telemetry/decoders/v1/README.grpc_dialout0000644000175000017500000000566514354105275021511 0ustar paolopaoloQUICKSTART. * Install the Protobuf compiler, see their downloads page: https://developers.google.com/protocol-buffers/docs/downloads * Install Python binding for Protobuf: shell> pip install protobuf * Install Python binding for gRPC, see their quickstart guide: https://grpc.io/docs/quickstart/python.html * Get relevant proto files from your vendor. For example, for Huawei get huawei-grpc-dialout.proto, huawei-telemetry.proto and relevant data models, ie. huawei-ifm.proto and huawei-devm.proto; for Cisco get cisco_grpc_dialout.proto, cisco_telemetry.proto and relevant data models, ie. cisco_ifstatsbag_generic.proto. Place them in the same directory of the decoders, ie. telemetry/decoders. See Huawei: http://support.huawei.com/enterprise/en/doc/EDOC1100039549?section=j00d&topicName=common-.proto-files http://support.huawei.com/enterprise/en/doc/EDOC1100039549?section=j00f&topicName=how-to-obtain-.proto-files See Cisco: https://github.com/cisco/bigmuddy-network-telemetry-proto/blob/master/proto_archive/telemetry.proto https://github.com/cisco/bigmuddy-network-telemetry-proto/blob/master/proto_archive/mdt_grpc_dialout/mdt_grpc_dialout.proto * OPTIONAL: if of interest, go and goyang can be installed and public openconfig YANG models can be downloaded and compiled to obtain a proto file: https://golang.org/doc/install https://github.com/openconfig/goyang https://github.com/openconfig/public shell> goyang --format proto openconfig-interfaces.yang > openconfig-interfaces.proto * Protobuf proto files must be compiled in order to be usable: shell> python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. cisco_grpc_dialout.proto shell> protoc -I=. --python_out=. cisco_telemetry.proto shell> protoc -I=. --python_out=. cisco_ifstatsbag_generic.proto shell> python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. huawei-grpc-dialout.proto shell> protoc -I=. --python_out=. huawei-telemetry.proto shell> protoc -I=. --python_out=. huawei-ifm.proto shell> protoc -I=. --python_out=. openconfig-interfaces.proto This produces pb2.py and pb2_grpc.py files that are suitable for inclusion in the Python decoders. * If interested in data models that are not supported in the sample Python decoders, edit the code accordingly (*and don't forget to share the code back with the rest of the community!*). * Start exporting Streaming Telemetry data from routers. * Compose a configuration file for pmtelemetryd (you can check for more configuration knobs in QUICKSTART and CONFIG-KEYS docs): ! telemetry_daemon_zmq_address: 127.0.0.1:50000 telemetry_daemon_zmq_address: 127.0.0.1:50001 telemetry_daemon_decoder: json ! telemetry_daemon_msglog_file: /path/to/telemetry-msglog-$peer_src_ip.json * Start pmtelemetryd: shell> pmtelemetryd -f /path/to/pmtelemetryd.conf * Start the relevant Streaming Telemetry pre-processing decoder: shell> cisco_grpc_dialout_server.py pmacct-1.7.8/telemetry/README.telemetry0000644000175000017500000001176214354105275016724 0ustar paolopaoloINTRODUCTION. pmacct strategy towards Streaming Telemetry is currently twofold and does encompass two daemons: 1) pmtelemetryd, written in C, and documented in "Quickstart guide to setup Streaming Telemetry collection" chapter of the QUICKSTART document; 2) pmgrpcd.py, written in Python, and documented in telemetry/decoders/v3/README.pmgrpcd. Following is the support matrix for Streaming Telemetry collection: Input transports: * TCP proprietary / non-standard (pmtelemetryd) * UDP proprietary / non-standard (pmtelemetryd) * UDP draft-ietf-netconf-udp-notif (pmtelemetryd) * gRPC (pmgrpcd.py) * gNMI (pmgrcpd.py [WiP]) Input encodings: * JSON (pmtelemetryd) * Protobuf (pmgrpcd.py) Output methods: * Kafka (pmtelemetryd, pmgrpcd.py) * files (pmtelemetryd) Output encodings: * JSON (pmtelemetryd, pmgrpcd.py [WiP]) * Avro (pmgrpcd.py) Examples of supported collection scenarios: * TCP/JSON -> pmtelemetryd -> Kafka/JSON * UDP draft-ietf-netconf-udp-notif/JSON -> pmtelemetryd -> Kafka/JSON * gRPC/Protobuf -> pmgrpcd.py -> Kafka/Avro * gRPC/Protobuf -> pmgrpcd.py -> Kafka/JSON * gRPC/Protobuf -> pmgrpcd.py -> pmtelemetryd -> files/JSON (-> decodeGPB.py) HISTORICAL NOTES. pmtelemetryd, the pmacct Streaming Telemetry daemon, does natively support TCP and UDP transports and JSON encoding; pmtelemetryd is also evolving to support upcoming IETF standards (ie. https-notif, udp-notif, cbor). In terms of encoding, in pmtelemetryd, GPB (or Google Protocol Buffers) is is only base64'd on output for de-marshalling upon post-processing (where utils/decodeGPB.py can help); also GPB encoding is mainly coupled with gRPC as a transport resulting in limited (or buggy) support for C language. As a result of that, in the problematic area of gRPC, two efforts are currently pursued: 1) write decoders to hold gRPC sessions and pre-process GPB encoding and pass de-serialized data to pmtelemetryd; decoders can be written in any language and pass data onto pmtelemetryd via a ZeroMQ queue; sample decoders can be found in telemetry/decoders/v1 and are written in Python; 2) write a slightly more autonomous tool in Python 3, pmgrpcd.py, to hold gRPC sessions, process GPB encoding and write JSON or Avro to Kafka (that is, bypassing pmtelemetryd); a sample of such tool can be found in telemetry/decoders/v3 along with its own documentation. In the ROUTER CONFIGS section below there are snippets of some routers configuration in order to export Streaming Telemetry data. Quickstart guides for collection are in telemetry/decoders/v1/README.grpc_dialout and telemetry/decoders/v3/README.pmgrpcd ROUTER CONFIGS. IOS XR configuration example, gRPC JSON encoding suitable (at time of this writing) for Openconfig YANG models, ie. openconfig-interface and openconfig-platform: telemetry model-driven destination-group COLLECTOR address-family ipv4 X.X.X.X port 10000 encoding json protocol grpc no-tls ! ! sensor-group SENSOR sensor-path openconfig-platform:components sensor-path openconfig-interfaces:interfaces ! subscription SUBSCRIPTION sensor-group-id SENSOR sample-interval 30000 destination-id COLLECTOR source-interface Loopback0 ! ! IOS XR configuration example, gRPC GPB key-value encoding suitable for for Cisco YANG models, ie. Cisco-IOS-XR-infra-statsd-oper: telemetry model-driven destination-group COLLECTOR address-family ipv4 X.X.X.X port 10000 encoding compact-gpb protocol grpc no-tls ! ! sensor-group SENSOR sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters ! subscription SUBSCRIPTION sensor-group-id SENSOR sample-interval 30000 destination-id COLLECTOR source-interface Loopback0 ! ! Huawei VRP configuration example, gRPC compact GPB encoding: telemetry # sensor-group SENSOR sensor-path huawei-ifm:ifm/interfaces/interface/ifStatistics # destination-group COLLECTOR ipv4-address X.X.X.X port 10000 vpn-instance MANAGEMENT_VRF protocol grpc no-tls # subscription SUBSCRIPTION sensor-group SENSOR destination-group COLLECTOR # return Huawei VRP configuration example, JSON over UDP-notif (draft-ietf-netconf-udp-notif) transport: telemetry udp-model udp-notif # sensor-group SENSOR sensor-path huawei-ifm:ifm/interfaces/interface/ifStatistics # destination-group COLLECTOR ipv4-address X.X.X.X port 10000 vpn-instance MANAGEMENT_VRF # subscription SUBSCRIPTION protocol udp encoding json sensor-group SENSOR destination-group COLLECTOR # return Juniper Native format telemetry configuration example, GPB encoding over UDP transport: services { analytics { streaming-server pmacct-server { remote-address X.X.X.X; remote-port 50000; } export-profile pmacct-server-export-params { local-address X.X.X.X; local-port 21111; reporting-rate 30; format gpb; transport udp; } sensor interface-xe { server-name pmacct-server; export-name pmacct-server-export-params; resource /junos/system/linecard/interface/logical/usage/; } } } pmacct-1.7.8/telemetry/utils/0000755000175000017500000000000014354105275015164 5ustar paolopaolopmacct-1.7.8/telemetry/utils/decodeGPB.py0000755000175000017500000000444014354105275017317 0ustar paolopaolo# # pmacct (Promiscuous mode IP Accounting package) # pmacct is Copyright (C) 2003-2020 by Paolo Lucente # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # pmgrpcd and its components are Copyright (C) 2018-2019 by: # # Matthias Arnold # Juan Camilo Cardona # Thomas Graf # Paolo Lucente # import sys import os sys.path.append(os.path.abspath('./')) from google.protobuf.json_format import MessageToJson import base64 import json import sys import telemetry_pb2 # import telemetry_top_pb2 <--. # import logical_port_pb2 <---`- JunOS Native Telemetry def main(): for line in sys.stdin: deviceJson = json.loads(line.strip()) #print(deviceJson) if "telemetry_data" not in deviceJson: print("No telemetry_data") print(deviceJson) continue telemetry_data = deviceJson["telemetry_data"] try: s = base64.b64decode(telemetry_data) #print(s) except Exception as e: print("Failed b64 decoding:", e) continue try: d = telemetry_pb2.Telemetry() # d = telemetry_top_pb2.TelemetryStream() <----- JunOS Native Telemetry d.ParseFromString(s) except Exception as e: print("Failed GPB parsing:", len(telemetry_data), e) try: jsonStrTelemetry = MessageToJson(d) print(jsonStrTelemetry) except Exception as e: print("Failed Conversion to JSON:", len(telemetry_data), e) if __name__ == "__main__": main() pmacct-1.7.8/docs/0000755000175000017500000000000014354105275012742 5ustar paolopaolopmacct-1.7.8/docs/relicense_effort/0000755000175000017500000000000014354105275016260 5ustar paolopaolopmacct-1.7.8/docs/relicense_effort/initial_outreach.txt0000644000175000017500000001620114354105275022344 0ustar paolopaoloarchived at https://www.mail-archive.com/pmacct-discussion@pmacct.net/msg03881.html Date: Wed, 8 Jan 2020 14:52:42 +0100 From: Job Snijders To: pmacct-news@pmacct.net, pmacct-discussion@pmacct.net Bcc: Job Snijders Subject: effort to relicense pmacct from GPL to a BSD-style license Message-ID: <20200108135242.GV93721@hanna.meerval.net> Reply-To: pmacct-discussion@pmacct.net MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit X-Clacks-Overhead: GNU Terry Pratchett Dear all, Summary: The pmacct project is looking to relicense its code from the current GPL license to a more liberal BSD-style license. A few weeks ago I had the pleasure to spend some face time with Paolo, which allowed for in-depth discussion about pmacct's current trajectory and bright future. We concluded it would be in the best interest of the pmacct project to attempt to relicense all code under a more permissive BSD-style license, for mainly two reasons: 1) Faced with our own mortality, it became clear that succession planning is of paramount importance for this project's continued success. We contemplated what happens in context of intellectual property rights should one of pmacct's contributors pass away, and realized potential heirs won't necessarily desire involvement in this open source project, potentially hampering changes to intellectual property policies in the project's future. 2) We suspect there are entities who violate the terms of pmacct's current GPL license, but at the same time we don't wish to litigate. Instead of getting infringers to change their behavior, relicensing the project could be another way to resolve the potential for conflict: we see benefits to removing rules we don't plan on enforcing anyway. Going forward, the preferred license under which we encourge people to contribute new work is a variant of the ISC license (also used by the OpenBSD project). The license template (to be used in file headers) can be found here: https://github.com/pmacct/pmacct/blob/master/LICENSE.template We need explicit approval from all contributors, and carefully keep track of those agreements. If a contributor doesn't agree or answer, we'll have to re-implement the contributed functionality or remove the contribution from the code base. REQUEST TO THE PMACCT CONTRIBUTOR COMMUNITY ------------------------------------------- If you have contributed to the pmacct project (your name may be listed below), please consider a reply-all to this email expressing your explicit consent (or disapproval) to change the license governing your contributions to the pmacct project, to the following license: """ Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ ------------------------------------------- The next action in this process will be to individually follow up with all contributors who didn't respond to the above request. Once the relicensing effort has been completed, we'll tag the resulting code base as pmacct version 2.0.0 and celebrate! Pmacct has many great years ahead of itself; Paolo's enthusiasm to do so is evident in this interview video :-) https://www.youtube.com/watch?v=QqmOcMAtGDM Please feel free to raise any questions you may have on the pmacct-discussion@pmacct.net list, or privately with me and/or Paolo. Kind regards, Job Snijders DRAFT LIST OF KNOWN PMACCT AUTHORS (based on 'git shortlog -sen') ================================================================= Commits Author 2921 Paolo Lucente 52 Marc Sune 20 Corentin Néau 17 Vincent Bernat 14 Job Snijders 12 Matthias Arnold 9 Raphaël P. Barazzutti 9 Claudio Ortega 8 Jonas Jensen 8 Matthias Arnold 8 Tim LaBerge 7 Jared Mauch 7 vittoriofoschi 7 Camilo Cardona 5 Aaron Finney 5 Vittorio Foschi 4 vphatarp 3 Alexander Brusilov 3 Emil Palm 3 Dusan Migra 3 Dan Berger 3 Markus Weber 2 Tim LaBerge 2 Guy Lowe 2 Hidde van der Heide 2 Jim Westfall 2 Lee Yongjae 2 Lennert Buytenhek 2 Matthieu Texier 2 Miki Takata 2 Pierre Dubouilh 2 Tiago Gomes 2 Vadim Tk 3 Thomas Graf 1 Junpei YOSHINO 1 root 1 Mehul Prajapati 1 Mike Jager 1 rouba002 1 Nimrod 1 Jeroen Roovers 1 PaweÅ‚ MaÅ‚achowski 1 Pier Carlo Chiodi 1 rsolsn <3997743+rsolsn@users.noreply.github.com> 1 Ivan F. Martinez 1 Raymond Russell 1 Rico29 1 Robert Wuttke 1 Seth N. Hetu 1 Arnold Matthias 1 Guo-Wei Su 1 Elisa Jasinska 1 Alexandros Couloumbis 1 Davíð Steinn Geirsson 1 David Higgs 1 Vyron Tsingaras 1 cozonac 1 ÐлекÑандр Шалаев 1 matthewsf 1 Manuel Mendez 1 Marc Sune 1 Kunshchikov Vladimir 1 Marcos Marado 1 Jonas Gröger pmacct-1.7.8/docs/relicense_effort/progress_report.txt0000644000175000017500000000605614354105275022267 0ustar paolopaoloCONTEXT: https://www.mail-archive.com/pmacct-discussion@pmacct.net/msg03881.html ------- CONSENT ------- Commits Author 2921 Paolo Lucente 53 Marc Sune 17 Vincent Bernat 21 Matthias Arnold 20 Corentin Néau 14 Job Snijders 12 Vittorio Foschi 10 Tim LaBerge / tlaberge@cisco.com 9 Claudio Ortega 8 Jonas Jensen 7 Camilo Cardona 7 Jared Mauch 5 Aaron Finney 4 vphatarp 3 Dan Berger / 3 Alexander Brusilov 3 Dusan Migra 3 Markus Weber 3 Thomas Graf 3 Emil Palm 2 Lennert Buytenhek 2 Guy Lowe 2 Hidde van der Heide 2 Pierre Dubouilh 2 Jim Westfall 2 Tiago Gomes 2 Matthieu Texier 2 Lee Yongjae 2 Miki Takata 1 Pier Carlo Chiodi 1 Mike Jager 1 Seth N. Hetu 1 Elisa Jasinska 1 cozonac 1 Marcos Marado 1 Alexandros Couloumbis 1 Ivan F. Martinez 1 Jonas Gröger 1 Nimrod 1 Guo-Wei Su 1 Robert Wuttke 1 PaweÅ‚ MaÅ‚achowski 1 Jeroen Roovers 1 Junpei YOSHINO 1 rouba002 1 David Higgs / higgsd@gmail.com Will Dowling Karl O. Pinc Stephen Clark ----- NO ANSWER YET ------ 9 Raphaël P. Barazzutti 2 Vadim Tk 1 root 1 Mehul Prajapati 1 rsolsn <3997743+rsolsn@users.noreply.github.com> 1 Raymond Russell 1 Rico29 1 Davíð Steinn Geirsson 1 Vyron Tsingaras 1 ÐлекÑандр Шалаев 1 matthewsf 1 Manuel Mendez 1 Kunshchikov Vladimir pmacct-1.7.8/docs/relicense_effort/README0000644000175000017500000000024614354105275017142 0ustar paolopaoloPmacct launched an initiative to relicense the pmacct code under a more permissive license. In this directory we keep track of which authors consented to the change. pmacct-1.7.8/docs/LOOKING_GLASS_FORMAT0000644000175000017500000000266714354105275016003 0ustar paolopaoloFollowing are documented the up-to-date BGP Looking Glass server request/reply formats. When upgrading from an earlier version, you may want to check out the UPGRADE document to verify if any impacting changes to the message formats were introduced. See CONFIG-KEYS and the 'Example: querying the BGP daemon via the Looking Glass server' section in QUICKSTART for more info. Query Type 1: IP address/prefix lookup * Request format: { "query_type": 1 "queries": <# of IP prefixes to lookup> } Followed by one JSON object per IP address/prefix to look up, ie.: { "ip_prefix": , "rd": , [OPTIONAL] "peer_ip_src": , "peer_tcp_port": [OPTIONAL] } * Reply format: { "query_type": 1, "results": <# of matching IP Prefixes> } Followed by one JSON object per matching IP address/prefix, ie.: { "peer_ip_src": , "event_type": "lglass", "afi": , "safi": , "ip_prefix": , } Query Type 2: Get Peers * Request format: { "query_type": 2 "queries": 1 } * Reply format: { "query_type": 2, "results": <# of BGP peers> } Followed by one JSON object per connected BGP peer: { "peer_ip_src": , "peer_id": , "peer_tcp_port": , "peer_as": } pmacct-1.7.8/docs/TRIGGER_VARS0000644000175000017500000001107014354105275014622 0ustar paolopaoloINTRODUCTION A feature to spawn external executables is part of all pmacct plugins (ie. sql_trigger_exec, print_trigger_exec, etc). In case of SQL plugins, executables may either be spawned each time a cache purging event occurs or at arbitrary time intervals (specified via sql_trigger_time); in all other plugins a trigger can be spawned only at a cache purging event. For time-sensitive triggers it is recommended to use crontab instead. Also, in case of SQL plugins some information is being passed to the triggered executable in the form of environment variables. The list of supported variables follows: VAR: $SQL_DB DESC: RDBMS database name. VAR: $SQL_TABLE DESC: SQL table name. VAR: $EFFECTIVE_SQL_TABLE DESC: SQL table name. This is defined only if the 'sql_table' value contains variables. Variables are replaced here by their actual values. This value will be inaccurate if multiple SQL tables are written as part of the same purge, ie. as a result of: 1) nfacctd daemon but nfacctd_time_new set to false (default); 2) $peer_src_ip part of the SQL table name. VAR: $SQL_HOST DESC: SQL server hostname (if any) VAR: $SQL_USER DESC: Username when authenticating to the SQL server. VAR: $SQL_REFRESH_TIME DESC: Time interval at which data is currently purged from the cache to the database. VAR: $SAMPLING_RATE DESC: Packet sampling ratio (1 out of N). It is defined only if packet sampling is actually enabled via a 'sampling_rate' configuration directive (see CONFIG-KEYS for further details about the key). VAR: $SQL_RECOVERY_BACKUP_HOST DESC: SQL server hostname contacted if the primary server fails. This is defined only if 'sql_recovery_backup_host' is activated (see CONFIG-KEYS for further details about the key). VAR: $TOTAL_ELEM_NUMBER DESC: Returns the total number of queued elements during the last purging event. Elements may be subsequently filtered out. It is defined only if 'sql_trigger_time' directive is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $EFFECTIVE_ELEM_NUMBER DESC: Returns the effective number of elements (that is, excluding those filtered out) on the queue being encapsulated in SQL queries during the last purging event. It is defined only if 'sql_trigger_time' is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $INSERT_QUERIES_NUMBER DESC: Returns the number of elements being successfully incapsulated into INSERT queries during the last cache-to-DB purging event. It is defined only if 'sql_trigger_time' is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $UPDATE_QUERIES_NUMBER DESC: Returns the number of elements being successfully incapsulated into UPDATE queries during the last cache-to-DB purging event. It is defined only if 'sql_trigger_time' is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $ELAPSED_TIME DESC: Returns the number of seconds the last purging event took to complete. It is defined only if 'sql_trigger_time' directive is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $SQL_HISTORY_BASETIME DESC: Returns the basetime of the current timeslot, if 'sql_history' is defined (see CONFIG-KEYS for further details about the key). It is the same value being inserted into 'stamp_inserted' field and is expressed as unixtime (seconds since Epoch). This is defined only if 'sql_trigger_time' is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $SQL_HISTORY_TIMESLOT DESC: Returns the timeslot size (in seconds), if 'sql_history' (see CONFIG-KEYS for further details about the key) is defined. Note that this value may change (it's recomputed) if monthly timeslot are in use. This is defined only if 'sql_trigger_time' is NOT defined (this causes the trigger to be launched each time the purging event occurs). VAR: $SQL_MAX_WRITERS DESC: Returns the maximum number of concurrent SQL writer processes allowed (see CONFIG-KEYS for details about 'sql_max_writers'). VAR: $SQL_ACTIVE_WRITERS DESC: Returns the active number of concurrent writer processes in place (see CONFIG-KEYS for details about 'sql_max_writers'). If used in conjunction with $SQL_MAX_WRITERS, this can prevent hitting the upper limit of writers by, say, taking corrective actions or sending proper warning notifications. pmacct-1.7.8/docs/IPFIX0000644000175000017500000000074214354105275013547 0ustar paolopaoloIPFIX: In June 2014 IANA assigned pmacct PEN #43874. Field types 1-32767 are reserved to official pmacct project fields definition. Users are welcome to define own field types (ie. due to customizations to the pmacct software) and can use for the purpose field types from 32768 onwards. Official pmacct project fields definition: ElementID Name Data Type Semantics Description 1 tag unsigned64 identifier tag primitive value 2 tag2 unsigned64 identifier tag2 primitive value pmacct-1.7.8/docs/MSGLOG_DUMP_FORMATS0000644000175000017500000001343214354105275015700 0ustar paolopaoloFollowing are documented the up-to-date BGP, BMP and Streaming Telemetry msglog (real-time logging) and dump (snapshot at regular, configurable, time intervals) formats. When upgrading from an earlier version, you may want to check out the UPGRADE document to verify if any impacting changes to the message formats were introduced. BGP msglog format: - log_init message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "log_init" } - log message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "log", "afi": , "safi": , "log_type": <"update", "withdraw", "delete">, } - log_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "log_close" } BGP dump format: - dump_init message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "dump_init", "dump_period": } - dump message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "dump", "afi": , "safi": , } - dump_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "peer_ip_src": , "event_type": "dump_close", "tables": , "entries": } BMP msglog format: - log_init message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "log_init" } - log routes message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "log", "afi": , "safi": , "bmp_msg_type": "route_monitor", "log_type": <"update", "withdraw", "delete">, "peer_ip": , } - log events message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "log", "bmp_msg_type": <"init", "term", "peer_up", "stats", "peer_down">, "peer_ip": , } - log_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "log_close" } BMP dump format: - dump_init message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "dump_init", "dump_period": } - dump routes message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "bmp_msg_type": "route_monitor", "event_type": "dump", "afi": , "safi": , "peer_ip": , } - dump events message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "dump", "event_timestamp": , "bmp_msg_type": <"init", "term", "peer_up", "stats", "peer_down">, "peer_ip": , } - dump_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "bmp_router": , "event_type": "dump_close" "tables": , "entries": } Streaming Telemetry msglog format: - log_init message: { "seq": , "writer_id": "/" (*), "timestamp": , "telemetry_node": , "event_type": "log_init" } - log message: { "seq": , "writer_id": "/" (*), "timestamp": , "telemetry_node": , "event_type": "log", "telemetry_port": , "serialization": <"json" | "gpb">, "telemetry_data": } - log_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "telemetry_node": , "event_type": "log_close" } Streaming Telemetry dump format: - dump_init message: { "seq": , "timestamp": , "telemetry_node": , "event_type": "dump_init", "dump_period": } - dump message: { "seq": , "writer_id": "/" (*), "timestamp": , "telemetry_node": , "event_type": "dump", "telemetry_port": , "serialization": <"json" | "gpb">, "telemetry_data": } - dump_close message: { "seq": , "writer_id": "/" (*), "timestamp": , "telemetry_node": , "event_type": "dump_close" } (*) Field included only when writing to a RabbitMQ or Kafka broker pmacct-1.7.8/docs/INTERNALS0000644000175000017500000007273714354105275014244 0ustar paolopaoloTABLE OF CONTENTS: I. Introduction II. Primitives III. The whole picture IV. Processes Vs. threads V. Communications between core process and plugins VI. Memory table plugin VII. SQL issues and *SQL plugins VIII. pmacctd flows counter implementation IX. Classifier and connection tracking engines X. Jumps and flow diversions in Pre-Tagging infrastructure XI. BGP daemon thread dimensioning I. Introduction The goal of this document would be to give extra insight on some of the internals of pmacct (useful for development or simply constructive critics). Since March 2005, this document is complemented by a paper about an architectural overview of the project 'pmacct: steps forward interface counters'; the referred paper is available for download at the pmacct homepage. II. Primitives Individual packets and specific traffic flows are identified by their header fields. The union of such header fields generates (a rather large) set of primitives. Traffic aggregates are typically identified by a reduced set of primitives instead. Packets or flows are merged into aggregates by defining a sub-set of primitives, by shaving off unused primitives from the original set and finally by summing their counters (ie. bytes and packets). Additional operations involved into the process can also include logical grouping of specific primitives into more general entities (ie. IP addresses into network prefixes), temporal aggregation (ie. splitting aggregates in time bins), tagging, sampling and filtering. What are primitives? They are atomic expressions ie. "src_port", "dst_host", "proto"; currently the unique boolean operator supported to glue expressions is "and". Hence, traffic could be aggregated translating a "who connects where, using which service" speech language statement into one recognized by pmacct: "src_host,dst_host,dst_port, proto". Comma, because of the unique logical connective "and", is simply intended as a separator. III. The high-level picture ----[ nfacctd loop ]-------------------------------------------- | | | [ check ] [ handle ] [ Correlate ] | | ... =====[ Allow ]===== [ maps ]===== [ BGP, IGP ] ... | | [ table ] | | nfacctd.c pretag.c bgp/bgp.c | | pretag_handlers.c isis/isis.c | | pretag-data.h | ---------------------------------------------------------------- \ | | -----[ core process ]-------------------------------------------------------------------------------- | | | | | [ apply ] [ evaluate ] [ handle ] [ write buffer ] | | | [ pre_tag_filter ] [ primitives ] |==[ channel buffer ]====[ to plugin ]==== ... | mirrored | / && && | | traffic | / [ apply ] [ apply ] | [ handle ] [ write buffer ] | ====================[ aggregate_filter ]====[ post_tag ]======|==[ channel buffer ]====[ to plugin ]==== ... | NetFlow | \ && | | | | [ evaluate ] | [ handle ] [ write buffer ] | | | [ packet sampling ] |==[ channel buffer ]====[ to plugin ]==== ... | | | | | \ plugin_hooks.c | ----------------------------------------------------------------------------------------------------- | | / ----[ pmacctd loop ]-------------------------------------------------------------------------------- | | | [ handle ] [ handle ] [ handle ] [ handle ] [ handle ] | | ... ====[ link layer ]=====[ IP layer ]====[ fragments ]==== [ flows ]==== [ classification ] ... | | ll.c nl.c ip_frag.c ip_flow.c nDPI library | | | | [ handle ] [ Correlate ] | | ... ====[ maps ]===== [ BGP, IGP ] ... | | pretag.c bgp/bgp.c | | pretag_handlers.c isis/isis.c | | pretag-data.h | ---------------------------------------------------------------------------------------------------- Except for the protocol specifics sfacctd loop is similar to nfacctd loop; same goes for uacctd being similar to pmacctd. IV. Processes Vs. threads pmacct daemons, ie. pmacctd, nfacctd, rely over both a multi-thread and multi-process architecture. Processes are used to encapsulate each plugin instance and, indeed, the Core Process. Threads are used to encapsulate specific functions within each process - ie. the BGP daemon thread within the Core Process. The Core Process either captures packets via the well-known libpcap API (pmacctd) or listens for specific packets coming from the network (nfacctd, for example, listens for NetFlow packets); packets are then processed (parsed, filtered, sampled, tagged, aggregated and buffered, if required as per runtime config) and sent to the active plugins. Plugins in turn pick and handle in some meaningful way aggregated data (struct pkt_data), ie. writing them to a RDBMS, a memory table, etc. A diagram follows: |===> [ pmacctd/plugin ] libpcap shared mem | ZeroMQ ===========> [ pmacctd/core ]==============|===> [ pmacctd/plugin ] socket To conclude a position on threads: threads are a necessity because of the tendency modern CPU are built (ie. multi-core). So far pmacct limits itself to a macro-usage of threads, ie. where it makes sense to save on IPC or where big memory structures would lead the pages' copy-on-write to perform horrendly. The rationale is that fine- grained multi-threading can often become a fertile source of bugs. V. Communications between core process and plugins A single running Core Process, which gathers packets or flows from the network, is able to feed aggregated data to multiple plugins; plugins are distinguished by their name. Names, for this purpose, need to be unique. Data is pushed to active plugins via either a home- grown circular queue or a ZeroMQ queue. Rest of this chapter focuses only on the home- grown circular queue; also, although the home-grown queue is still the default pick (as it does not bring any external library dependencies), the ZeroMQ queue is currently the recommended way to go. Each plugin has a private control channel with the Core Process. Circular queues are encapsulated into a more complex channel structure which also includes: copy of the aggregation method, an OOB (Out-of-Band) signalling channel, buffers, one or more filters and a pointer to the next free queue element. The Core Process simply loops around all established channels, in a round-robin fashion, feeding data to active plugins. The circular queue is effectively a shared memory segment; if the Plugin is sleeping (ie. because the arrival of new data from the network is not at sustained rates), then the Core Process kicks the specific Plugin flagging that new data is now available at the specified memory address; the Plugin catches the message and copies the buffer into its private memory space; if the Plugin is not sleeping instead, once finished processing the current element, will check the next queue element to see whether new data are available. Either cases, the Plugin continues processing the received buffer. 'plugin_pipe_size' configuration directive aims to tune manually the circular queue size; raising its size is vital when facing large volumes of traffic, because the amount of data pushed onto the queue is directly (linearly) proportional to the number of packets captured by the core process. A small additional space is allocated for the out-of-band signalling mechanism, which is UNIX pipe-based. 'plugin_buffer_size' defines the transfer buffer size and is disabled by default. Its value has to be <= the circular queue size, hence the queue will be divided into 'plugin_buffer_size'/'plugin_pipe_size' chunks. Let's write down a few simple equations: dss = Default Segment Size dbs = Default Buffer Size = sizeof(struct pkt_data) as = Address Size = sizeof(char *) (depends on hardware architecture) bs = 'plugin_buffer_size' value ss = 'plugin_pipe_size' value a) no 'plugin_buffer_size' and no 'plugin_pipe_size': circular queue size = 4MB signalling queue size = (4MB / dbs) * as b) 'plugin_buffer_size' defined but no 'plugin_pipe_size': circular queue size = 4MB signalling queue size = (4MB / bs) * as c) no 'plugin_buffer_size' but 'plugin_pipe_size' defined: circular queue size = ss signalling queue size = (ss / dbs) * as d) 'plugin_buffer_size' and 'plugin_pipe_size' defined: circular queue size = ss signalling queue size = (ss / bs) * as If 'plugin_buffer_size' is not defined, it is set to the minimum size possible in order to contain one element worth of data for the selected aggregation method. The signalling queue must be able to address the full circular buffer: should that not be possible due to OS restrictions, ie. on Linux systems /proc/sys/net/core/[rw]mem_max and /proc/sys/net/core/[rw]mem_default, a log message is printed (along the lines of "ctrl channel: obtained= bytes target= bytes", where Y is what is needed in order to address the circular queue and X is what the underlying OS conceded). Few final remarks: a) buffer size of 10KB and pipe size of 10MB are well-tailored for most common environments; b) by enabling buffering, attaching the collector to a mute interface and doing some pings will not show any result (... data are buffered); c) take care to the ratio between the buffer size and pipe size; choose for a ratio not less than 1:100. But keeping it around 1:1000 is strongly adviceable; selecting a reduced ratio could lead to filling the queue: when that happens a warning message indicating the risk of data loss is printed. You may alternatively do some calculations based on the knowledge of your network environment: average_traffic = packets per seconds in your network segment sizeof(struct pkt_data) = ~70 bytes pipe size >= average_traffic * sizeof(struct pkt_data) circular queue [ pmacctd/core ] =================================> [ pmacctd/plugin ] | | | | | | enqueued buffers free | | | |==|==|==|==|==|==|==|===========| | | | `-------------------------------------------' OOB signalling queue VI. Memory table plugin In-Memory Table plugin (IMT) stores the aggregates as they have been assembled by core process in a memory structure, organized as an hash table. Such table is divided in a number of buckets. Aggregates are framed into a structure defined as 'struct acc' and then direct mapped to a bucket by the mean of a modulo function. Collisions in each bucket are solved building collision chains. An auxiliar structure, a LSU cache (Last Recently Used), is provided to speed up searches and updates into the main table. LSU saves last updated or searched element for each bucket: when a new operation on the bucket is required, the LSU cache is compared first; if it doesn't match, the collision chain gets traversed. It's adviceable to use a prime number of buckets (defined by 'imt_buckets' configuration directive), because it helps in achieving better data dispersion when applying the modulo function. Collision chains are organized as linked lists of elements, so they should be kept short because of the linear search over them; having a flat table (so, raising the number of buckets) helps in keeping chains short. Memory is allocated in large chunks, called memory pools, to limit as possible bad effects (such as trashing) derived from dispersion through the memory pages. In fact, drawbacks of the dense use of malloc() calls are extensively described on every Operating Systems textbook. Memory allocations are tracked via a linked list of chunk descriptors (struct memory_pool_desc) for later jobs such as freeing unused memory chunks, operations over the list, etc. The memory structure can be allocated either 'fixed' or 'dynamic'; when dealing with a fixed table, all descriptors are allocated in a single shot when the daemon is fired up; when dealing with a 'dynamic' memory table (which is allowed to grow undefinitely in memory new chunks of memory are allocated and added to the list during the execution. Using a fixed table places a maximum limit to the number of entries the table is able to store; the following calculation may help in building a fixed table: ES (Entry Size) ~ 50 bytes NE (Number of entries) NE = ('imt_mem_pools_number' * 'imt_mem_pools_size') / ES Default values are: imt_mem_pools_number = 16; imt_mem_pools_size = 8192; this will let the default fixed table to contain a maximum of slightly more than 2600 aggregates. However note the entry size is indicative and can very consistently, ie. depending if IPv6 or Layer2 are enabled at compile time or whether BGP, MPLS, NAT, etc. primitives are in use as part of the aggregation key. When a fixed size table is needed, it is better to constrain it on the size rather than the estimated number of entries to fit. IMT plugin does not rely any way over the realloc() function, but only mmap(). Table grows and shrinks with the help of the above described tracking structures. This is because of a few assumptions about the use of realloc(): (a) try to reallocate on the original memory block and (b) if (a) failed, allocate another memory block and copy the contents of the original block to this new location. In this scheme (a) can be done in constant time; in (b) only the allocation of new memory block and the deallocation of original block are done in constant time, but the copy of previous memory area, for large in-memory tables, could perform horrendly. Data stored into the memory structure can be either fetched, erased or zeroed by a client tool, pmacct, communicating through a Unix Domain socket (/tmp/collect.pipe by default). The available queries are 'bulk data retrieval', 'group data retrieval' (partial match), 'single entry retrieval' (exact match) and 'erase table'. Additionally, both partial and full matches may supply a request for resetting the counters. On the server side, the client query is evaluated: requests that need just a short stroll through the memory structure are accomplished by the plugin itself, the others (for example batch queries or bulk data retrieval) are served by a child process spawned by the plugin. Because memory table is allocated 'shared', operations requiring table modifications by such child (eg. resetting counters for an entry) are handled by raising a flag instead: next time the plugin will update that entry, it will also serve any pending request. With the introduction of batch queries (which enable to group into a single query up to 4096 requests) transfers may be fragmented by the Operating System. IMT plugin will take care of recomposing all fragments, expecting also a '\x4' placeholder as 'End of Message' marker. If an incomplete message is received, it's discarded as soon as current transfer timeout expires (1s). VII. SQL issues and *SQL plugins Storing aggregates into a persistent backend leaves chances for advanced operations and so these plugins are intended to give a wider range of features (eg. write to a backup DB if the primary DB fails, counters breakdown, etc.) not available in other plugins. Let's firstly give a whole picture of how these SQL plugins work. As packets received from core process via communication channel get unpacked, they are inserted in a direct- mapped cache; then, at fixed time intervals (configurable via 'sql_refresh_time' key) the cache scanner kicks in and purges content to the database; optionally triggers may be executed (sql_trigger_exec, sql_trigger_time). Data to cache bucket mapping is computed via a modulo function. If the selected bucket already contains valid data then a conflict chain is built (or traversed if it already exists); the first free node encountered is used; if no free nodes are found then two more chances are explored: if any node has been marked as stale (it happens when an allocated node is unused for some consecutive time-bins) it is then reused by moving it away from its old chain; if no free nodes are available then a new one is allocated. Stale nodes are then retired if they still remain unused for longer times (RETIRE_TIME**2). To speed up nodes reuse and retirement, an additional LRU list of nodes is also mantained. If out of memory or the maximum number of allowed elements in the cache is reached data is immediately written to the database so to make room for further elements. The maximum number of allowed elements is defined to prevent the cache to grow in memory without any control. Such limit is internally calculated as: max cache elements = sql_cache_entries + ( sql_refresh_time * 100 ) As said before, aggregates are pushed into the DB at regular intervals; to speed up such operation a queue of pending queries is built as nodes are used; this allows to avoid long walks through the whole cache structure given, for various reasons (ie. classification, sql_startup_delay) not all elements might be eligible for purging. When the cache scanner kicks in a new writer process is spawned and in charge of processing the pending elements queue; SQL statements are built and sent to the RDBMS. Writers can, depending on the conditions of the DB, take long time before completing, ie. longer than pmacct interval to purge to the DB, sql_refresh_time. A sql_max_writers feature allows to impose a maximum number of writers to prevent forming an endless queue, hence starving system resources, and at the expense of data loss. Because we, at this moment, don't known if INSERT queries would create duplicates, an UPDATE query is launched first and only if no rows are affected, then an INSERT query is trapped. 'sql_dont_try_update' twists this behaviour and skips directly to INSERT queries; when enabling this configuration directive, you must be sure there are no risks of duplicate aggregates to avoid data loss. Data in the cache is never erased but simply marked as invalid; this way while correctess of data is still preserved, we avoid the waste of CPU cycles (if there is no immediate need to free memory up). The number of cache buckets is tunable via the 'sql_cache_entries' configuration key; a prime number is strongly advisable to ensure a better data dispersion through the cache. Three notes about the above described process: (a) some time ago the concept of lazy data refresh deadlines has been introduced. Expiration of timers is checked without the aid of UNIX signals but when new data comes in. If such data arrival rate is low, data is not kept stale into the cache but a poll() timeout makes the wheel spin. (b) SQL plugins main loop has been purposedly kept sufficiently fast thanks to no direct interaction with the RDBMS: it only gets data, computes modulo and handles both cache and queries queue. (c) cache has been thought to exploit a kind of temporal locality in internet flows. A picture follows: |====> [ cache ] ===| pipe | | ======> [ pmacctd/SQL plugin ] =====|====> [ cache ] ===|=============+=====| primary DB |=====> | | | |====> [ cache ] ===| `-----| secondary DB |===> Now, let's keep an eye on how aggregates are structured on the DB side. Data is simply organized in flat tuples, without any external references. After being not full convinced about better normalized solutions aimed to satifsy an abstract concept of flexibility, we've (and here come into play the load of mails exchanged with Wim Kerkhoff) found that simple means faster. And spinning the wheel quickly is a key achievement, because pmacct needs not only to insert new records but also update existing ones, putting under heavy pressure RDBMS when placed in busy network environments and an high number of primitives are required. Now a pair of concluding practical notes: (a) default SQL table and its primary key are suitable for many normal usages, however unused fields will be filled by zeroes. We took this choice a long time ago to allow people to compile sources and quickly get involved into the game, without caring too much about SQL details (assumption: who is involved in network management, shoult not have necessarily to be also involved into SQL stuff). So, everyone with a busy network segment under his feet has to carefully tune the table himself to avoid performance constraints; 'sql_optimize_clauses' configuration key evaluates what primitives have been selected and avoids long 'WHERE' clauses in 'INSERT' and 'UPDATE' queries. This may involve the creation of auxiliar indexes to let the execution of 'UPDATE' queries to work smoothly. A custom table might be created, trading flexibility with disk space wasting. (b) when using timestamps to break down aggregates into timeframes ('sql_history' key), validity of data is connected not only to data itself but also to its timeframe; as stated before, aggregates are pushed into DB at regular intervals ('sql_refresh_time' key). Connecting these two elements (refresh time and historical timeframe width) with a multiplicative factor helps in avoiding transient cache aliasing phenomena and in fully exploiting cache benefits. VIII. pmacctd flows counter implementation Let's take the definition of IP flows from RFC3954, titled 'Cisco Systems NetFlow Services Export Version 9': an IP flow is defined as a set of IP packets passing an observation point in the network during a certain time interval. All packets that belong to a particular flow have a set of common properties derived both from the data contained in the packet and from the packet treatment at the observation point. Packets belonging to a specific flow also feature a very high temporal locality. While the handmade IP flows implementation in pmacctd mantains the fore-mentioned properties, it behaves quite differently when compared with NetFlow. In fact, the typical NetFlow implementation accumulates packets belonging to the same flow into a single memory object; when it comes to expire (because either the flow hits a timeout or an intercepted quit message - ie. TCP FIN/RST -) it is released and pushed into a NetFlow packet which is in turn sent to the collector. On the contrary, pmacctd does not accumulate; each packet is looked up against the flow buffer - a memory structure for active flows bookeping -: if it belongs to an already active flows its 'new flow' flag is deactivated (0); otherwise it's activated (1). While the above method is savy in terms of resource consumption, it could have some side-effects: for example it causes an entry to have a flow value '0' after either a reset of the backend memory structure (ie. pmacct -e, pmacct ... -r, etc.) or the beginning of a new timeframe when historical accounting is enabled (ie. print plugin, 'sql_history', etc.). IX. Classifier and connection tracking engines Classification and connection tracking features were introduced in pmacctd and uacctd daemons as early as 0.10.0 release. As of pmacct 1.7, classification is switched from the mixed home-grown implementation + L7 layer project to the nDPI library. Firstly, let's give a look to the global picture; then how they work: ----[ pmacctd loop ]------------------------------------------------------------- | [ regular ] | | [ expression ] | | ___[ patterns ] | | / / | | / ______/ | | | / | | | / | | [ fragment ] [ flow ] [ flow ] [ connection ] | | ... ==>[ handling ]==>[ handling ]==>[ classification ]==>[ tracking ]==> ... | | [ engine ] [ engine ] [ engine ] [ engine ] | | ip_frag.c ip_flow.c nDPI library \ conntrack.c | | | \___ | | \ \ | | \ [ shared ] | | --[ object ] | | [ pattern ] | --------------------------------------------------------------------------------- As the above picture shows, the classification engine is hooked to the flow handling engine. In fact, being able to successfully classify single packets means we can mark accordingly the whole bi-directional flow (referred also as stream) they belong to. The flow engine determines whether a flow is either newly established or terminated, sets its timeouts per protocol and state and handles timestamps. The classification engine coordinates the efforts to classify the packets by setting a maximum number of classification tentatives, handling bytes/packets accumulators for (still) unknown flows and attaching connection tracking modules whenever required. In case of successful classification, accumulators are released and sent to the active plugins, which, in turn, whenever possible (ie. counters have not been cleared, sent to the DB, etc.) will move such amounts from the 'unknown' class to the newly determined one. A connection tracking module might be assigned to certain classified streams if they belong to a protocol which is known to be based over a control channel (ie. FTP, RTSP, SIP, H.323, etc.). However, some protocols (ie. MSN messenger) spawn data channels that can still be distinguished because of some regular patterns into the payload; in such cases a classificator exists rather than a tracking module. Connection tracking modules hint IP address/port couples for upcoming data streams as signalled by one of the parties into the control channel; such pieces of information are then meant to classify the new data streams. In this context, 'snaplen' directive, which specifies the maximum number of bytes to capture for each packet, has key importance. In fact, some protocols (mostly text-based eg. RTSP, SIP, etc.) benefit of extra bytes because they give more chances to identify new data streams spawned by by the control channel. But it must be also noted that capturing larger packet portion require more system resources. Thus, the right value need to be traded-off. By enabling classification, values under 200 bytes are often meaningless. 500-750 bytes should be enough even for text-based protocols. X. Jumps and flow diversions in Pre-Tagging infrastructure Pre-Tagging infrastructure allows to flexibly mark either packets or flows collected from the network. It's basically a chain of rules: the first matching rule wins (ie. tags collected data). This approach is effective to mantain a 1-to-1 relationship between data and tags; but this is somewhat limiting in some scenarios, ie. the need to account internal data to both the sender and the receiver: this time you would need a 1-to-2 relationship. In this context, being able to handle 1-to-2 relationships becomes a requirement when sampling comes into play as any single sample is required to be assigned to both parties in order for the algorithms to work correctly. Relationships 1-to-1 are precisely the aim for jeq, stack and return keys. XI. BGP daemon thread dimensioning Memory structure of the BGP daemon thread can be broken down in three modules: IP prefixes, BGP information and BGP attributes. Up to version 0.12.3 the multi-RIB nature of the BGP daemon was achieved separating IP prefixes and BGP information on a per active BGP peer basis, while BGP attributes were shared among all the peers. From a logical point these structures were relating each other as follows: IP prefix -(1:1)-> BGP information -(N:1)-> BGP attributes. Version 0.12.4 sees introduction of a memory model by which also IP prefixes are being shared among the BGP peers - leading to consistent memory savings whenever multiple BGP peers export full tables due to the almost total overlap of information. In this new model, structures are relating each other as follows: IP prefix -(1:N)-> BGP information -(N:1)-> BGP attributes. The longest match nature of IP lookups required to raise BGP peer awareness of the lookup algorithm in order to fully support the newly established 1:N relation. Following are some calculations that can ease memory dimensioning in order to support a certain number of peers, num(B), each exporting the same full-routing table, T, which consists of num(P) number of prefixes. The shared base of BGP attributes, A, is estimated in roughly 200MB. The BGP information base, I, is also calculated. sz(P) = 16 (size of an IP prefix) sz(Tn) = 48 (size of routing table node) sz(In) = 32 (size of BGP information base node) sz(THn) = 8 (size of routing table hash node) T = num(P) * (sz(Tn) + sz(P) + (sz(THn) * bgp_table_peer_buckets)) I = num(B) * num(P) * sz(In) RIB = T + I + A Sizes are based on worse-case scenario, ie. 64-bit executable with support for IPv6 compiled in. num(P) is a way to simplify calculations while retaining good accuracy; whereas higher precision can be achieved by using union(P), which is the union of all prefixes exported by all BGP peers. bgp_table_peer_buckets is set by default to 13 and is adviceable to keep its value to 1/10 of the expected number of BGP peers; increasing such ratio improves lookup performances at the expense of more sustained memory usage. As an example, let's imagine a scenario where 500 BGP peers export the same 500K IPv4 routes and 50K IPv6 routes and bgp_table_peer_buckets is set to a value of 50: T = (500K+50K) * (48 + 16 + (8 * 50)) = 256MB I = 500 * (500K+50K) * 32 = 8.8GB A = ~200MB RIB = 256MB + 8.8GB + 200MB = ~9.26GB Still, this example assumes a 64-bit executable. For an educated guess on how 32-bit executables would look like, it's sufficient to divide by half output of the sz() functions presented above. pmacct-1.7.8/docs/PLUGINS0000644000175000017500000000611014354105275014004 0ustar paolopaoloPMACCT PLUGIN WRITING HOW-TO SHORT OVERVIEW pmacct plugin architecture is thought to allow to implement own backends without knowing much of core collectors functionalities and independently by other plugins. Below are listed a few steps to hook a new plugin in pmacct; pmacct is also extremely open to new ideas, so if you wish to contribute your work, you will be the most welcome. - minor hacks to configure.in script following the example of what has been done there for mysql plugin; same goes for requirements like paths to headers or libraries. By making use of the PLUGINS variable, it will not be required to touch the "src/Makefile.am" script. Definitions in configure.in (ie. AC_DEFINE(WITH_MYSQL, 1)) whose existence can be checked via compiler preprocessor is an easy way to propagate user configuration choices at compilation time. - [OPTIONAL] If the plugin needs to take configurable values, this can be achieved by defining configuration handlers (pmacct-data.h, cfg_handlers.h, cfg_handlers.c) and declaring config variables to deliver configured values to the plugin (cfg.h, struct configuration). If command-line parameters are also required, some getopt() related code needs to be dealt with (pmacct-defines.h and ie. pmacctd.c, nfacctd.c, sfacctd.c and uacctd.c). - Define the new plugin in pmacct; this can be done by adding an entry to the plugin_types_list[] array (pmacct-data.h). An entry consists of two fields: an id string and a pointer to a function to be called. The first is the string which will be used to call the plugin from within the configuration or command-line. The second is effectively the entry point to the plugin. - [OPTIONAL] If the plugin needs any checks that require visibility in the global configuration for example for compatibility against other plugins instantiated (ie. tee plugin not compatible with any plugins) or the daemon itself (ie. nfprobe plugin only supported in pmacctd and uacctd daemons), such checks can be performed in the daemon code itself (ie. pmacctd.c, nfacctd.c, etc. - look in these files for the "PLUGIN_ID" string for examples). - Develop the plugin code. One of the existing plugins can be used as reference - of course, as long as the purpose of the plugin under development is same or similar in function (ie. data is extracted from the circular buffer, then aggregated and cached in memory for a configurable amount of time, ie. print_refresh_time, and finally purged to the backend. Structures for parsing data coming out of the circular buffer are defined in the network.h file; structures for data caching are in print_common.h (at least three generations of caches were conceived over time: first the one used in the memory plugin; second the one used in SQL plugins, rich in features but challenging to control in size; third, and current, the one used in print, MongoDB and AMQP plugins which is defined, as said, in print_common.h). The basic layout for the main plugin loop can be grasped in the print_plugin.c file by looking at content of the "for (;;)" loop. pmacct-1.7.8/docs/BGP_BMP_METRICS.md0000644000175000017500000004272614354105275015573 0ustar paolopaolo# Collecting BGP metrics with pmacct Pmacct can export BGP updates and withdrawals received from a BGP or BMP (BGP Monitoring Protocol) peer (bmp_daemon_msglog, bgp_daemon_msglog) or dump the collected BGP RIB in regular intervals (bmp_table_dump,bgp_table_dump) from a BGP router. This documents describes, dependent if they are collected through BGP or BMP, which metrics are collected with sample configurations for Apache Kafka export. --- ## BGP collected local RIB metrics ### pmacct example configuration ~~~~ bgp_daemon: true bgp_daemon_ip: 192.0.2.1 bgp_daemon_port: 179 bgp_daemon_max_peers: 255 ! bgp_daemon_msglog_kafka_broker_host: kafka.example.com bgp_daemon_msglog_kafka_broker_port: 9093 bgp_daemon_msglog_kafka_topic: topic.name.example.com bgp_daemon_msglog_kafka_config_file: /etc/pmacct/librdkafka.conf ! bgp_table_dump_kafka_broker_host: kafka.example.com bgp_table_dump_kafka_broker_port: 9093 bgp_table_dump_kafka_topic: topic.name.example.com bgp_table_dump_kafka_config_file: /etc/pmacct/librdkafka.conf bgp_table_dump_refresh_time: 60 ~~~~ ### BGP metric description Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `log_type` | pmacct log type. One of "update", "withdraw", "delete" or "end-of-rib" `timestamp` | pmacct time stamp of data collection `peer_ip_src` | IP address of BGP router which peers to pmacct `peer_tcp_port` | TCP port of BGP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `afi` | BGP Address Family Indicator (RFC 4760 - Multiprotocol Extensions for BGP-4) `safi` | BGP Subsequent Address Family Identifier (RFC 4760 - Multiprotocol Extensions for BGP-4) `ip_prefix` | BGP Prefix `bgp_nexthop` | BGP next hop `as_path` | BGP AS path `comms` | BGP standard community string `ecomms` | BGP extended community string `origin` | BGP origin attribute `local_pref` | BGP local preference `rd` | BGP Route Distinguisher `rd_origin` | BGP Route Distinguisher origin. It can be either of "bgp" or "flow". `label` | BGP MPLS VPN label `as_path_id` | BGP ADD-Path attribute (https://tools.ietf.org/html/rfc7911#section-3) `aigp` | BGP AIGP attribute (https://tools.ietf.org/html/rfc7311#section-3) `psid_li` | BGP Prefix-SID Label Index attribute (https://tools.ietf.org/html/rfc8669#section-3.1) `writer_id` | pmacct process name and id ### Example BGP metrics In case of table dump. Each batch of metric will start with "log_init" and end with "log_close" event_type meta data. This meta data includes the time of the data collection, the peering IP address and TCP port and which pmacct process name and id exported the metrics. ~~~~ { "seq": 1161, "timestamp": "2020-06-13 14:11:38.515220", "peer_ip_src": "192.0.2.2", "peer_tcp_port": 25344, "event_type": "log_init", "writer_id": "pmacct-bgp01c/4852" } { "seq": 1162, "log_type": "update", "timestamp": "2020-06-13 14:11:39.092808", "peer_ip_src": "192.0.2.2", "peer_tcp_port": 25344, "event_type": "log", "afi": 2, "safi": 128, "ip_prefix": "2001:db8::/32", "bgp_nexthop": "203.0.113.1", "as_path": "64496 64497", "comms": "64496:1 64497:2 64498:3", "ecomms": "RT:64496:100", "origin": "i", "local_pref": 0, "rd": "0:64499:1", "rd_origin": "bgp", "label": "25", "writer_id": "pmacct-bgp01c/4857" } { "seq": 1163, "timestamp": "2020-06-13 14:11:39.627806", "peer_ip_src": "192.0.2.2", "peer_tcp_port": 31402, "event_type": "log_close", "writer_id": "pmacct-bgp01c/4857" } ~~~~ --- ## BMP collected adjacent RIB in metrics ### pmacct example configuration ~~~~ bmp_daemon_ip: 192.0.2.1 bmp_daemon_port: 1790 bmp_daemon_max_peers: 255 bmp_daemon_msglog_kafka_broker_host: kafka.example.com bmp_daemon_msglog_kafka_broker_port: 9093 bmp_daemon_msglog_kafka_topic: topic.name.example.com bmp_daemon_msglog_kafka_config_file: /etc/pmacct/librdkafka.conf ~~~~ ### BMP message type 0, route monitoring metrics Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `log_type` | pmacct log type. One of "update", "withdraw", "delete" or "end-of-rib" `timestamp` | time stamp when data was generated on router `timestamp_arrival` | time stamp of BMP data export `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "route_monitoring" for BMP message type 0 `path_status` | BMP path-marking status https://tools.ietf.org/html/draft-cppy-grow-bmp-path-marking-tlv#section-2.1 `reason_code` | BMP path-marking reason_code https://tools.ietf.org/html/draft-cppy-grow-bmp-path-marking-tlv#section-2.1 `is_in` | Boolean, if present and true it indicates data from Local-RIB `is_out` | Boolean, if present and true it indicates data from Adj-Rib-Out `is_post` | Boolean, if present and true it indicates post-policy data (in conjunction with is_in, is_out) `peer_ip` | BGP peer IP address where BGP metrics are received from `afi` | BGP Address Family Indicator (RFC 4760 - Multiprotocol Extensions for BGP-4) `safi` | BGP Subsequent Address Family Identifier (RFC 4760 - Multiprotocol Extensions for BGP-4) `ip_prefix` | BGP Prefix `bgp_nexthop` | BGP next hop `as_path` | BGP AS path `comms` | BGP standard community string `ecomms` | BGP extended community string `origin` | BGP origin attribute `local_pref` | BGP local preference `rd` | BGP Route Distinguisher `rd_origin` | BGP Route Distinguisher origin. It can be either of "bgp", "bmp" or "flow". `label` | BGP MPLS VPN label `as_path_id` | BGP ADD-Path attribute (https://tools.ietf.org/html/rfc7911#section-3) `aigp` | BGP AIGP attribute (https://tools.ietf.org/html/rfc7311#section-3) `psid_li` | BGP Prefix-SID Label Index attribute (https://tools.ietf.org/html/rfc8669#section-3.1) ~~~~ { "seq": 67938379, "log_type": "update", "timestamp": "2020-12-17T11:54:54.000000+01:00", "timestamp_arrival": "2020-12-17T11:54:55.000000", "is_post": 1, "is_in": 1, "rd": "0:64499:82", "rd_origin": "bmp", "path_status": [ "Non-selected", "Backup" ], "reason_code": "0x0014", "peer_ip": "192.0.32.154", "is_post": 0, "is_out": 1, "peer_ip": "198.51.100.72", "peer_tcp_port": 0, "event_type": "log", "afi": 1, "safi": 1, "ip_prefix": "203.0.113.82/32", "bgp_nexthop": "192.0.32.154", "as_path": "65000 65539", "comms": "64496:299 64496:1001 64496:1033 64497:3 64499:81", "ecomms": "SoO:64497:63", "origin": "i", "local_pref": 0, "timestamp_arrival": "2020-12-17T11:54:56.005522+01:00", "bmp_router": "192.0.2.72", "bmp_router_port": 52306, "bmp_msg_type": "route_monitor", "writer_id": "ietfint_nfacctd-bmp01_c/1958020" } ~~~~ ### BMP message type 1, statistics report Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | time stamp of BMP data export `timestamp_arrival` | pmacct time stamp of data collection `is_loc` | Boolean, if present and true it indicates data from Loc-Rib `is_filtered` | Boolean, if present and true it indicates filtered data (in conjunction with is_loc) `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "stats" for BMP message type 1 `peer_ip` | BGP peer IP address where BGP metrics are received from `peer_asn` | BGP peer BGP AS number `peer_type` | Type of BGP peer (https://www.iana.org/assignments/bmp-parameters/bmp-parameters.xhtml#peer-types) `rd` | BGP peer Route Distinguisher (https://tools.ietf.org/html/rfc7854#section-4.2) `rd_origin` | BGP peer Route Distinguisher origin. It will be set to "bmp". `counter_type` | Statistics type field code (https://www.iana.org/assignments/bmp-parameters/bmp-parameters.xhtml#statistics-types) `counter_type_str` | Statistics description `counter_value` | Statistics counter value ~~~~ { "event_type": "log", "seq": 18271, "timestamp": "2020-12-17T11:53:37.539446+01:00", "timestamp_arrival": "2020-12-17T11:53:37.669796+01:00", "is_filtered": 0, "is_in": 1, "bmp_router": "192.0.2.2", "bmp_router_port": 45047, "bmp_msg_type": "stats", "peer_ip": "203.0.113.1", "peer_asn": 60633, "peer_type": 0, "rd": "0:64499:2", "rd_origin": "bmp", "counter_type": 0, "counter_type_str": "Number of prefixes rejected by inbound policy", "counter_value": 0 } ~~~~ ### BMP message type 2, peer down Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | time stamp of BMP data export `timestamp_arrival` | pmacct time stamp of data collection `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "peer_down" for BMP message type 2 `peer_ip` | BGP peer IP address where BGP metrics are received from `peer_asn` | BGP peer BGP AS number `peer_type` | Type of BGP peer (https://www.iana.org/assignments/bmp-parameters/bmp-parameters.xhtml#peer-types) `peer_type_str` | type of BGP peer description `rd` | BGP peer Route Distinguisher (https://tools.ietf.org/html/rfc7854#section-4.2) `rd_origin` | BGP peer Route Distinguisher origin. It will be set to "bmp". `reason_type` | Reason type why BGP went down (https://www.iana.org/assignments/bmp-parameters/bmp-parameters.xhtml#peer-down-reason-codes) `reason_str` | Reason description why BGP went down ~~~~ { "event_type": "log", "seq": 18696, "timestamp": "2020-12-17T11:53:37.539446+01:00", "timestamp_arrival": "2020-12-17T11:53:37.669796+01:00", "bmp_router": "192.0.2.2", "bmp_router_port": 45047, "bmp_msg_type": "peer_down", "peer_ip": "203.0.113.3", "peer_asn": 64496, "peer_type": 0, "peer_type_str": "Global Instance Peer", "rd": "0:64499:2", "rd_origin": "bmp", "reason_type": 1, "reason_str": "The local system closed the session" } ~~~~ ### BMP message type 3, peer up Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | time stamp of BMP data export `timestamp_arrival` | pmacct time stamp of data collection `is_in` | Boolean, if present and true it indicates data from Adj-Rib-In `is_post` | Boolean, if present and true it indicates post-policy data (in conjunction with is_in, is_out) `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "peer_up" for BMP message type 3 `peer_ip` | BGP peer IP address where BGP metrics are received from `peer_asn` | BGP peer BGP AS number `peer_type` | Type of BGP peer (https://www.iana.org/assignments/bmp-parameters/bmp-parameters.xhtml#peer-types) `peer_type_str` | type of BGP peer description `rd` | BGP peer Route Distinguisher (https://tools.ietf.org/html/rfc7854#section-4.2) `rd_origin` | BGP peer Route Distinguisher origin. It will be set to "bmp". `bgp_id` | BGP router ID of remote peer from BGP open message `local_port` | BGP peer local TCP port `remote_port` | BGP peer remote TCP port `local_ip` | BGP peer local IP address ~~~~ { "event_type": "log", "seq": 10, "timestamp": "2020-12-17T11:53:37.539446+01:00", "timestamp_arrival": "2020-12-17T11:53:37.669796+01:00", "is_post": 1, "is_in": 1, "bmp_router": "192.0.2.2", "bmp_router_port": 45047, "bmp_msg_type": "peer_up", "peer_ip": "203.0.113.2", "peer_asn": 64496, "peer_type": 0, "peer_type_str": "Global Instance Peer", "rd": "0:64499:2", "rd_origin": "bmp", "bgp_id": "192.0.2.2", "local_port": 26354, "remote_port": 179, "local_ip": "203.0.113.1" } ~~~~ ### BMP message type 4, initiation Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | unsupported - zeroed out `timestamp_arrival` | pmacct time stamp of data collection `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "init" for BMP message type 4 `bmp_init_info_sysdescr` | BGP software version of router peering to pmacct `bmp_init_info_sysname` | BGP hostname of router peering to pmacct `writer_id` | pmacct process name and id ~~~~ { "event_type": "log", "seq": 9, "timestamp": "0000-00-00 00:00:00.000000", "timestamp_arrival": "2020-12-17T11:53:37.669796+01:00", "bmp_router": "192.0.2.2", "bmp_router_port": 17677, "bmp_msg_type": "init", "bmp_init_info_sysdescr": "6.5.2", "bmp_init_info_sysname": "bgprouter.example.com", "writer_id": "daisy62bmp01c/9254" } ~~~~ ### BMP message type 5, termination Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | unsupported - zeroed out `timestamp_arrival` | pmacct time stamp of data collection `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "term" for BMP message type 5 `bmp_term_info_reason` | BMP termination reason `writer_id` | pmacct process name and id ~~~~ { "event_type": "log", "seq": 6432, "timestamp": "0000-00-00 00:00:00.000000", "timestamp_arrival": "2020-12-17T11:53:37.669796+01:00", "bmp_router": "192.0.2.52", "bmp_router_port": 60720, "bmp_msg_type": "term", "bmp_term_info_reason": "Session administratively closed" } ~~~~ ### BMP message type TBD, Route Policy and Attribute Trace Title | Description :----- | :----------- `seq` | pmacct sequence number. Uniquely identifies each metric. `timestamp` | time stamp of BMP data export `timestamp_arrival` | pmacct time stamp of data collection `bmp_router` | IP address of BMP router which peers to pmacct `bmp_router_port` | TCP port of BMP router which peers to pmacct `event_type` | pmacct event type. Can be either "log" for msglog or "dump" for table_dump. `bmp_msg_type` | "rpat" for BMP message type 6 `rd` | BGP peer Route Distinguisher `rd_origin` | BGP peer Route Distinguisher origin. It will be set to "bmp". `prefix` | BGP prefix `prefix_len` | BGP prefix mask `bgp_id` | BGP router-id `afi` | BGP Address Family Indicator (RFC 4760 - Multiprotocol Extensions for BGP-4) `safi` | BGP Subsequent Address Family Identifier (RFC 4760 - Multiprotocol Extensions for BGP-4) `vrf_id` | VRF identifier (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.1) `vrf_name` | VRF name string (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.1) `policy_is_match` | route-policy matched (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_is_permit` | route-policy permitted (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_is_diff` | route-policy modified (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_is_class` | route-policy type (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_name` | route-policy name (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_id` | route-policy sequence id (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `policy_nf` | next route-policy is chained (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.2) `bmp_rpat_info_pre_policy_attr` | Pre Route-Policy (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.3) `bmp_rpat_info_post_policy_attr` | Post Route-Policy (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.4) `bmp_rpat_info_strin` | String (https://tools.ietf.org/html/draft-xu-grow-bmp-route-policy-attr-trace#section-2.3.5) `writer_id` | pmacct process name and id ~~~~ { "event_type": "log", "seq": 68222721, "timestamp": "2020-12-17T12:09:42.275678+01:00", "timestamp_arrival": "2020-12-17T12:09:44.285191+01:00", "bmp_router": "192.0.2.72", "bmp_router_port": 52306, "seq": 360, "bmp_router": "192.0.2.52", "bmp_router_port": 49531, "bmp_msg_type": "rpat", "rd": "0:64499:82", "rd_origin": "bmp", "prefix": "203.0.113.72", "prefix_len": 32, "bgp_id": "192.0.32.155", "afi": 1, "safi": 1, "vrf_id": 3, "vrf_name": "C20", "policy_is_match": 1, "policy_is_permit": 1, "policy_is_diff": 0, "policy_class": "Inbound policy", "peer_bgp_id": "198.51.100.55", "peer_ip": "192.0.32.155", "peer_asn": 65000, "policy_name": [ "RP-C20-IP-IN" ], "policy_id": [ "10" ], "policy_nf": [ null ], "bmp_rpat_info_pre_policy_attr": "40-01-01-00-40-02-12-02-04-00-00-FD-E8-00-01-00-03-00-01-00-00-00-01-00-01-40-03-04-C0-00-20-9B-C0-08-18-FB-F0-00-14-FB-F0-03-E9-FB-F0-04-09-FB-F1-00-03-FB-F3-00-47-FB-F3-00-65-C0-10-08-00-03-FB-F1-00-00-00-40", "bmp_rpat_info_post_policy_attr": null, "bmp_rpat_info_string": [ "xmlns:rtp=\"urn:huawei:yang:huawei-routing-policy\" select=\"/rtp:routing-policy/rtp:policy-definitions/rtp:policy-definition[rtp:name='RP-C20-IP-IN']/rtp:nodes/rtp:node[rtp:sequence='10']" ], "writer_id": "ietfint_nfacctd-bmp01_c/1958020" } ~~~~ pmacct-1.7.8/docs/SIGNALS0000644000175000017500000000754114354105275013774 0ustar paolopaoloSIGNALS: Here follows a list of supported signals and their meaning. If a signal is not being properly delivered to the daemon, and this is on a system running SELinux, check for SELinux interferences. Core process: SIGCHLD: used by the Core Process to handle gracefully his loved child processes (plugins). This is internal, ie. should not be sent by users. To end gracefully the daemon use SIGINT; SIGHUP: reopens the logging infrastructure. Works with both syslog and logfiles; it also works with streamed logging of BGP messages/ events (bgp_daemon_msglog_file), streamed logging of BMP data/ stats/events (bmp_daemon_msglog_file) and streamed logging of sFlow counters (sfacctd_counter_file); this signal must be sent to all running processes; SIGUSR1: returns various stats via the configured log output (logfile, syslog) or, if none is configured, to console; the syslog level used is NOTICE and the facility is selected through config. The feature is implemented for pmacctd, uacctd, nfacctd and sfacctd daemons. Following is an example of the output emitted by flow daemons, nfacctd and sfacctd: NOTICE ( default/core ): +++ NOTICE ( default/core ): stats [0.0.0.0:2100] agent=X.X.X.X:0 time=1515772618 packets=1 bytes=496 seq_good=1 seq_jmp_fwd=0 seq_jmp_bck=0 NOTICE ( default/core ): stats [0.0.0.0:2100] agent=Y.Y.Y.Y:0 time=1515772618 packets=2 bytes=992 seq_good=2 seq_jmp_fwd=0 seq_jmp_bck=0 NOTICE ( default/core ): stats [0.0.0.0:2100] time=1515772618 discarded_packets=0 NOTICE ( default/core ): --- Following is an example of the output emitted by pmacctd: NOTICE ( default/core ): +++ NOTICE ( default/core ): stats [XXX, 0] time=1515772618 received_packets=1000 dropped_packets=0 NOTICE ( default/core ): stats [YYY, 1] time=1515772618 received_packets=1000 dropped_packets=0 NOTICE ( default/core ): --- Note: stats for nfacctd and sfacctd daemons are logged at the next useful flow packet being collected (only worth nothing in test and lab scenarios). This signal applies to Core Process only; SIGUSR2: if 'maps_refresh' config directive is enabled, it causes maps to be reloaded (ie. pre_tag_map, bgp_agent_map, etc.). If also indexing is enabled, ie. maps_index, indexes are re-computed; depending which process loads a map (ie. Core Process, [some of the active] Plugins, etc.), the signal must target the right process in order to be effective; where a map is computed can be derived by the logs, ie.: INFO ( default/core ): [/path/to/primitives.lst] (re)loading map. INFO ( default/core ): [/path/to/primitives.lst] map successfully (re)loaded. primitives.lst is loaded by the core process and a signal to reload such map should be sent to the Core Process. There is usually no harm in sending this signal to all processes unless in presence of a use-case to relad different maps at different time intervals. SIGINT: the signal is used by the Core Process itself and propagated to each running plugin for graceful termination (ie. send BGP NOTIFICATION message to established BGP sessions, close open files, remove PID files, purge data, etc.). See Q16 of the FAQS document for recommendations on how to best send SIGINT signals to the daemon; SIGTERM: not handled (which means it follows the default behaviour for the OS) if the daemon is started in background; otherwise it works like SIGINT; SIGPIPE: ignored; Plugin (SQL, noSQL, memory, print, tee, probes, etc.) processes: SIGPIPE: ignored; SIGCHLD: ignored; SIGHUP: reopens the logging infrastructure. Works with both syslog and logfiles; SIGUSR1: ignored; SIGUSR2: if 'maps_refresh' configuration directive is enabled it causes maps loaded by the Plugin to be reloaded; SIGINT: causes the process to exit gracefully; if directed to a specific Plugin, it will cause shut down iof only that one plugin. pmacct-1.7.8/docs/DOCKER.md0000644000175000017500000002330014354105275014231 0ustar paolopaolo# Official pmacct docker containers documentation Docker images are one of the easiest ways to start using pmacct. They are also a powerful and simple technology to deploy pmacct in production, for example combining it with [docker-compose](https://docs.docker.com/compose/) or deploying them on a [Kubernetes cluster (k8s)](https://kubernetes.io/). ## Where to download them The official pmacct docker image registry is in [docker hub](https://hub.docker.com/r/pmacct). Available daemon containers: * [nfacctd](https://hub.docker.com/r/pmacct/nfacctd) * [pmacctd](https://hub.docker.com/r/pmacct/pmacctd) * [pmbgpd](https://hub.docker.com/r/pmacct/pmbgpd) * [pmbmpd](https://hub.docker.com/r/pmacct/pmbmpd) * [pmtelemetryd](https://hub.docker.com/r/pmacct/pmtelemetryd) * [sfacctd](https://hub.docker.com/r/pmacct/sfacctd) * [uacctd](https://hub.docker.com/r/pmacct/uacctd) All daemons come with **all plugins and supports compiled-in**. ### Tags Containers are published with the following tags: * `latest`: latest stable image of that container * `vX.Y.Z`: version specific tag. This container will always exist, once released. * `bleeding-edge`: only for the brave. Latest commit on `master`. This container is not recommended to be used in production. ## How to use them (docker/docker-compose only) ``` ~# docker pull pmacct/pmacctd:latest ~# docker run -v /path/to/pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd ``` To use another daemon, e.g. `nfacctd`, just replace `pmacct/pmacctd` with `pmacct/nfacctd` in both commands. ### Configuration files All daemons expect a pmacct configuration file in `/etc/pmacct/.conf`. Note: When using `-v` ([bind mounts](https://docs.docker.com/storage/bind-mounts/)), make sure the HOST path is an **absolute path**. ### Operations Once running, regular `docker` tools can be used for basic things. A non-extensive list: * `docker ps`: list the docker containers in the system * `docker logs`: inspect logs * `docker stats`: monitor container resource usage * `docker pause`/`docker unpause`: pause/unpause the execution of a container ### Sniffing on network interfaces (`libpcap`) By default, docker containers run in an isolated network enviornment. If daemons need to access to host network interfaces to sniff traffic (e.g. `pmacctd`), [privileged mode ](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) and [host network](https://docs.docker.com/network/host/) is required. ``` marc@pmacct:~/tmp$ docker run --privileged --network host -v /home/marc/tmp/pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd:latest ``` ## Troubleshooting a pmacct docker container When reporting a bug, you might be asked to add additional debugging information. This section covers the basics on some of these procedures. Troubleshooting typically involves starting containers manually, and in interactive mode, to install additional debugging tools. To do so, launch the container with the options: ``` marc@pmacct:~/tmp$ docker run -it -v /home/marc/tmp/pmacctd.conf:/etc/pmacct/pmacctd.conf --entrypoint /bin/bash pmacct/pmacctd:latest root@dca4471bf893:/# ``` ### Core dumps Containers can be started (`docker`/`docker-compose`) with the option to generate a coredump on abort (`--ulimit core=-1`). Docker containers run in the kernel of the HOST, and therefore inherit the coredump configuration (`core_pattern`). To modify it, refer to your OS/Distribution manual. One thing to mention is that the location of the coredumps is important. It simplifies things that coredumps are outputted in a dedicated folder (e.g. `/tmp/cores/`). Container's filesystem is, by definition, volatile, so coredump(s) will be lost after the daemon aborts and container is destroyed/restarted. To avoid that it should be mounted as a volume: ``` marc@pmacct:~/tmp$ mkdir -p cores marc@pmacct:~/tmp$ docker run --ulimit core=-1 -v /home/marc/tmp/cores:/tmp/cores -v /home/marc/tmp/pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd:latest ``` ### Using a debugger (`gdb`/`cgdb`) In the shell of the container, start the program with `gdb` and follow the regular debugging process: ``` root@dca4471bf893:/# gdb pmacctd GNU gdb (Debian 8.2.1-2+b3) 8.2.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from pmacctd...done. (gdb) run ``` ### Using `valgrind` `valgrind` is a great tool to help the debugging memory errors, among other things. Please note that `valgrind` slows down significantly the execution. In the shell of the container do: _Step 1_: install `valgrind`: ``` root@dca4471bf893:/# apt-get update && apt-get -y install valgrind Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] Get:2 http://deb.debian.org/debian buster InRelease [121 kB] Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] ... ``` _Step 2_: launch the daemon with `valgrind` and options, and let the error condition happen or run for a while: ``` root@dca4471bf893:/# valgrind --leak-check=full --track-origins=yes --trace-children=yes pmacctd ==536== Memcheck, a memory error detector ==536== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==536== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info ==536== Command: pmacctd ==536== WARN: [cmdline] No plugin has been activated; defaulting to in-memory table. ... ``` _Step 3_: if the program is still running after the condition stop it with `Ctrl+C`. You should see a final report, like: ``` ... ==538== ==538== HEAP SUMMARY: ==538== in use at exit: 24,154 bytes in 58 blocks ==538== total heap usage: 1,345 allocs, 1,287 frees, 297,541 bytes allocated ==538== ==538== 456 (96 direct, 360 indirect) bytes in 1 blocks are definitely lost in loss record 27 of 29 ==538== at 0x483577F: malloc (vg_replace_malloc.c:299) ==538== by 0x1607B1: initsetproctitle (setproctitle.c:101) ==538== by 0x118705: main (pmacctd.c:577) ==538== ==538== LEAK SUMMARY: ==538== definitely lost: 96 bytes in 1 blocks ==538== indirectly lost: 360 bytes in 11 blocks ==538== possibly lost: 0 bytes in 0 blocks ==538== still reachable: 23,698 bytes in 46 blocks ==538== suppressed: 0 bytes in 0 blocks ==538== Reachable blocks (those to which a pointer was found) are not shown. ==538== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==538== ==538== For counts of detected and suppressed errors, rerun with: -v ==538== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) ``` Make sure to send the entire log until and including the final report. ### Opening a shell on a running container You can open a shell on an existing running container. _Step 1_: identify the container: ``` marc@pmacct:~/tmp$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dca4471bf893 pmacct/pmacctd:latest "pmacctd" 2 hours ago Up 2 hours adoring_keldysh ``` _Step 2_: open a shell: ``` marc@pmacct:~/tmp$ docker exec -it dca4471bf893 /bin/bash root@dca4471bf893:/# ``` ## FAQ 1. Problem: ``` ERROR: [/etc/pmacct/.conf] path is not a regular file. ``` This happens when the container can't find `/etc/pmacct/.conf`, and typically happens when either: * HOST file path is not an absolute path: ``` marc@pmacct:~/tmp$ docker run -v pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd:latest ERROR: [/etc/pmacct/pmacctd.conf] path is not a regular file. ``` * There is typo in the TARGET file path. E.g: missing a `d` in the configuration file name in the TARGET: ``` marc@pmacct:~/tmp$ docker run -v /home/marc/tmp/pmacctd.conf:/etc/pmacct/pmacct.conf pmacct/pmacctd:latest ERROR: [/etc/pmacct/pmacctd.conf] file not found. marc@Mriya:~/tmp$ ``` Solution: ``` docker run -v /home/marc/tmp/pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd:latest ``` 2. Question: ``` If i want to daemonize pmacct running inside a Docker container, should i use either the "daemonize: true" config knob or the -d pmacct command-line flag? ``` Answer: No. That would cause the container to end. pmacct should never be daemonized when running inside a container. Instead, depending on the environment, if one wants to daemonize the container, the option may be to run docker with the -d command-line flag, ie.: ``` docker run -d --name pmacctd --privileged --network host -v /etc/pmacct/pmacctd.conf:/etc/pmacct/pmacctd.conf pmacct/pmacctd:latest ``` ## Advanced ### Creating a custom layer on top A special container, [base](https://hub.docker.com/r/pmacct/base) container, that is the base of the rest of containers, with all pmacct daemons installed and `bash` as an entry point is also published, with the same tag structure as the rest of the containers. This image can be used to to create your customized docker image, with different entrypoints or other tools in. ### Building your Docker image from scratch If you still feel you need to compile your own custom version of pmacct, you can take a look at the `Dockerfile` in the folder `docker/base` as a starting point. pmacct-1.7.8/docs/FLOW_AUGMENTATION_PROCESS_DESCRIPTION.md0000644000175000017500000002027314354105275021053 0ustar paolopaolo# Introduction pmacct adapts different data sources to a single output model of flow data. In this document, we aim to provide details on how the application, based on its configuration, extracts the information from these sources to populate BGP related fields. # Short description of pmacct flow model The output of pmacct corresponds to aggregated flow data. Data is aggregated in time and over flow attributes. Time aggregation is out of the scope of this document. Flow attribute aggregation reduce the number of output fields by aggregating the bytes/packets of the flows with the same characteristics. The aggregation fields that are used to define a flow can be configured with the "aggregate" keyword. The next are the particular fields that we aim to describe here: * BGP fields: 'src_as', 'dst_as', 'peer_src_as' , 'peer_dst_as', 'peer_dst_ip' * NET fields: 'dst_net', 'src_mask', 'dst_mask', 'src_net' * OTHER fields: 'peer_src_ip' Most of these fields are self-descriptive. The only two that require further explanation are peer_src_ip, which is the device exporting flows (aka the netflow exporter IP), and peer_dst_ip, which is the BGP next-hop. Both fields are valuable when one wants to find node-to-node, interface-to-interface, or peer-to-peer traffic matrices, especially when collecting flow in ingress direction. In this case, peer_src_ip represents the entry point into the observed network. # Sources of data The aforementioned BGP and NET fields can be populated using any of the flow protocols (netflow, ipfix, sflow), but they can also be populated using BGP, BMP, IGP, files, etc. The configuration parameters used to select the data to populate the fields is controlled using nfacctd_as and nfacctd_net (sfacctd_as and sfacctd_net if using sflow). Next, we describe how the fields are extracted from each of these protocols. Although the application offers the flexibility to model different scenarios, it makes sense that the two configuration knobs are set aligned and hence **we assume that they both are configured to the same value**. The same lookup procedure is performed for the src and dst ip. ## Netflow/IPFIX nfacctd supports Netflow version 5 and version 9. IPFIX behaves similarly to Netflow version 9. ### Netflow v5 Netflow v5 does carry full NET information but carries limited BGP information: only the src_as and dst_as. pmacct offers the use_ip_next_hop keyword, which commands nfacctd to use the ip_next_hop as source for the peer_dst_ip field. ip_next_hop represents the IP address configured on the far end of the output link of the exporting device and hence finds little use in producing traffic matrices. ### Netflow v9/IPFIX Netflow v9 and IPFIX both carry full NET information and also include optional fields that contain the BGP data, including but not limited to BGP next-hop. Note that the information is optional and, even if device supports these protocols, it is not guaranteed that it will populate the NET and BGP fields. "nfacctd -a" tells all supported fields and provides a description of each field. ### Sflow sFlow v5 is able to optionally carry NET and BGP information. Just like NetFlow v9/IPFIX, being a modular protocol, even if device supports this protocol, it is not guaranteed that it will populate the NET and BGP fields. "sfacctd -a" tells all supported fields and provides a description of each field. ## BGP pmacct can BGP peer with the same devices exporting flows and use their BGP RIBs to complement or augment flow data with BGP information. The process to find the BGP peer for a certain received flow is: - If the IP address of the flow exporter corresponds to an existing BGP peer (either BGP ID or transport address), pmacct uses that peer BGP table. - Alternatively, the bgp_agent_map can be used to relate a flow source to a BGP peer. After pmacct selects a BGP peer, it retrieves the paths for the flow by doing a lookup of the flow dst ip. If a (single) path is found, it is used to populate the BGP and NET fields. In cases in which multiple paths are available for the flow (for instance, when the BGP peer advertises multiple paths to pmacct using the ADD-PATH capability), the result can be ambiguous (for example, in case the network runs BGP next-hop self). In this case, pmacct tries to match the flow to one of the available paths; if available, this is done by using the BGP next-hop field. A lookup is performed also against the flow src ip, for example, to determine the source ASN of a flow. ## BMP pmacct can BMP peer with the same devices exporting flows or with a BMP route-server that collects and advertises (to pmacct) the BGP RIBs of the devices exporting flows. Brief digression being: in the former case the implementation of draft-ietf-grow-bmp-adj-loc-rib should be waited for as correlating flow data against BGP Adj-RIB-In information (that is, the BMP implementation according to rfc7854) could lead to inaccuracies; the latter case kind of solves this limitation that exists at time of this writing. Since BMP is a transport for the original BGP information (BMP provides also some statistics and extra visibility which is all out of the scope for this document), all that was said about BGP in the previous paragraph applies to BMP too. In other words, BGP information contained in BMP is used by pmacct to populate BGP RIBs for the BGP peers advertised in BMP. ## Files The purpose of a networks_file is twofold: 1) define IP prefixes, for example statics or from an IGP that is not supported, and 2) associate to them some optional characteristics including BGP next-hop, origin ASN and peer ASN that may, or may not, make sense depending on the specific scenario. Files can be used instead of a BGP peering or to complement visibility in BGP - for example in the case of BGP only containing supernets with on-net more specifics being statics or IGP routes. ## Longest pmacct uses the src and dst nets from each of the methods (that is, BGP, BMP, files) to select the source of the data to populate the BGP and NET fields. If the prefix is equal, the preference becomes networks_file < sFlow/NetFlow < IGP <= BGP. Note that if some of the information from the source is empty, that will be the value output by pmacct. As it was said in the BMP paragraph, since BMP is a transport for the original BGP information, the use of BGP peerings and BMP is currently mutual exclusive. # Network scenarios Let us discuss different network/monitoring scenarios base on the information of the previous sections. ## Multiple BGP paths received in the collector BMP and BGP, using the ADD-PATH capability, can announce multiple paths for a specific prefix. However, the protocols still do not have the capability of signaling the paths installed in the FIB. Even in the case in which a single path is used for forwarding, announcing multiple paths to pmacct can make the result ambiguous (for example, in case the network runs BGP next-hop self). Unless ADD-PATH is enabled network-wide, it is recommended to only announce single paths if relying on BGP to populate BGP fields. ## Prefix forwarded using multiple BGP paths In general, Networks with a heavy use of load balancing across BGP paths should rely on flow protocols populating BGP fields for correct accounting. BGP and BMP do not contain the mechanims to signal which BGP paths are used for forwarding. Even if future modifications of these protocols could signal the paths used for forwarding, allowing pmacct to add them all to the flow output, one may still need to simulate the hashing algorithm of the router to infer the balancing among the paths (even if not running BGP next-hop self; for example, in corner cases where multiple statics, BGP multi-hop sessions, etc. are advertised for the same prefix in ADD-PATH by the same router). ## Using RRs to obtain BGP data It is recommended to establish BGP sessions from every router exporting flows. Some networks might want to reduce the number of BGP sessions by establishing them from their RR. To allow this, the bgp_agent_map could be used to link the edge routers to the RRs. Let's remember pmacct does not embed a BGP best-path algorithm and hence this setup would work only if each edge router is mapped to a RR that would choose the same paths as the edge router and hence, in general, this approach is not recommended. pmacct-1.7.8/Makefile.in0000644000175000017500000012524214354105415014061 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @USING_BGP_BINS_TRUE@am__append_1 = examples/lg @USING_SQL_TRUE@am__append_2 = src/sql_common_m.c subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pmacct_data_dir)" \ "$(DESTDIR)$(pmacct_docs_dir)" \ "$(DESTDIR)$(pmacct_examples_dir)" \ "$(DESTDIR)$(pmacct_examples_amqp_dir)" \ "$(DESTDIR)$(pmacct_examples_avro_dir)" \ "$(DESTDIR)$(pmacct_examples_custom_dir)" \ "$(DESTDIR)$(pmacct_examples_kafka_dir)" \ "$(DESTDIR)$(pmacct_examples_lg_dir)" \ "$(DESTDIR)$(pmacct_examples_lg_arch_dir)" \ "$(DESTDIR)$(pmacct_sql_dir)" DATA = $(pmacct_data__DATA) $(pmacct_docs__DATA) \ $(pmacct_examples__DATA) $(pmacct_examples_amqp__DATA) \ $(pmacct_examples_avro__DATA) $(pmacct_examples_custom__DATA) \ $(pmacct_examples_kafka__DATA) $(pmacct_examples_lg__DATA) \ $(pmacct_examples_lg_arch__DATA) $(pmacct_sql__DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = src examples/custom examples/lg am__DIST_COMMON = $(srcdir)/Makefile.in AUTHORS COPYING ChangeLog \ INSTALL compile config.guess config.sub install-sh ltmain.sh \ missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src examples/custom $(am__append_1) ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = include sql examples docs CONFIG-KEYS FAQS QUICKSTART \ UPGRADE $(am__append_2) pmacct_data_dir = $(datarootdir)/pmacct pmacct_libs_dir = $(libdir)/pmacct pmacct_docs_dir = $(pmacct_data_dir)/docs pmacct_examples_dir = $(pmacct_data_dir)/examples pmacct_examples_arch_dir = $(pmacct_libs_dir)/examples pmacct_examples_kafka_dir = $(pmacct_examples_dir)/kafka pmacct_examples_amqp_dir = $(pmacct_examples_dir)/amqp pmacct_examples_avro_dir = $(pmacct_examples_dir)/avro @USING_BGP_BINS_TRUE@pmacct_examples_lg_dir = $(pmacct_examples_dir)/lg @USING_BGP_BINS_TRUE@pmacct_examples_lg_arch_dir = $(pmacct_examples_arch_dir)/lg pmacct_examples_custom_dir = $(pmacct_examples_arch_dir)/custom @USING_SQL_TRUE@pmacct_sql_dir = $(pmacct_data_dir)/sql pmacct_data__DATA = CONFIG-KEYS FAQS QUICKSTART UPGRADE pmacct_docs__DATA = docs/IPFIX docs/LOOKING_GLASS_FORMAT docs/SIGNALS \ docs/MSGLOG_DUMP_FORMATS docs/TRIGGER_VARS pmacct_examples__DATA = examples/allow.lst.example examples/bgp_agent.map.example \ examples/bgp_md5.lst.example examples/bgp_xconnects.map.example \ examples/flow_to_rd.map.example examples/networks.lst.example \ examples/peers.map.example examples/pcap_interfaces.map.example \ examples/pmacctd-imt.conf.example examples/pmacctd-multiple-plugins.conf.example \ examples/ports.lst.example examples/pretag.map.example \ examples/primitives.lst.example examples/probe_netflow.conf.example \ examples/probe_sflow.conf.example examples/sampling.map.example \ examples/tee_receivers.lst.example examples/nfacctd-sql.conf.example \ examples/pmacctd-sql.conf.example examples/pmacctd-sqlite3.conf.example pmacct_examples_kafka__DATA = examples/kafka/kafka_consumer.py pmacct_examples_amqp__DATA = examples/amqp/amqp_receiver.py pmacct_examples_avro__DATA = examples/avro/avro_file_decoder.py @USING_BGP_BINS_TRUE@pmacct_examples_lg__DATA = examples/lg/pmbgp.py @USING_BGP_BINS_TRUE@pmacct_examples_lg_arch__DATA = examples/lg/pmbgp pmacct_examples_custom__DATA = examples/custom/libcustom.la @USING_SQL_TRUE@pmacct_sql__DATA = sql/pmacct-create-db_bgp_v1.mysql sql/pmacct-create-db.pgsql \ @USING_SQL_TRUE@ sql/pmacct-create-db_v1.mysql sql/pmacct-create-db_v2.mysql \ @USING_SQL_TRUE@ sql/pmacct-create-db_v3.mysql sql/pmacct-create-db_v4.mysql \ @USING_SQL_TRUE@ sql/pmacct-create-db_v5.mysql sql/pmacct-create-db_v6.mysql \ @USING_SQL_TRUE@ sql/pmacct-create-db_v7.mysql sql/pmacct-create-db_v8.mysql \ @USING_SQL_TRUE@ sql/pmacct-create-db_v9.mysql sql/pmacct-create-table_bgp_v1.pgsql \ @USING_SQL_TRUE@ sql/pmacct-create-table_bgp_v1.sqlite3 sql/pmacct-grant-db.mysql \ @USING_SQL_TRUE@ sql/pmacct-create-table_v1.pgsql sql/pmacct-create-table_v1.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v2.pgsql sql/pmacct-create-table_v2.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v3.pgsql sql/pmacct-create-table_v3.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v4.pgsql sql/pmacct-create-table_v4.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v5.pgsql sql/pmacct-create-table_v5.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v6.pgsql sql/pmacct-create-table_v6.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v7_v8.pgsql sql/pmacct-create-table_v7.sqlite3 \ @USING_SQL_TRUE@ sql/pmacct-create-table_v8.sqlite3 sql/pmacct-create-table_v9.pgsql \ @USING_SQL_TRUE@ sql/pmacct-create-table_v9.sqlite3 sql/README.cos \ @USING_SQL_TRUE@ sql/README.custom_primitives sql/README.etype sql/README.export_proto \ @USING_SQL_TRUE@ sql/README.GeoIP sql/README.iface sql/README.label sql/README.mask \ @USING_SQL_TRUE@ sql/README.mpls sql/README.mysql sql/README.nat sql/README.pgsql \ @USING_SQL_TRUE@ sql/README.sampling sql/README.sqlite3 sql/README.tag2 sql/README.tunnel \ @USING_SQL_TRUE@ sql/README.timestamp all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pmacct_data_DATA: $(pmacct_data__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_data__DATA)'; test -n "$(pmacct_data_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_data_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_data_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_data_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_data_dir)" || exit $$?; \ done uninstall-pmacct_data_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_data__DATA)'; test -n "$(pmacct_data_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_data_dir)'; $(am__uninstall_files_from_dir) install-pmacct_docs_DATA: $(pmacct_docs__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_docs__DATA)'; test -n "$(pmacct_docs_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_docs_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_docs_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_docs_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_docs_dir)" || exit $$?; \ done uninstall-pmacct_docs_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_docs__DATA)'; test -n "$(pmacct_docs_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_docs_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_DATA: $(pmacct_examples__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples__DATA)'; test -n "$(pmacct_examples_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_dir)" || exit $$?; \ done uninstall-pmacct_examples_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples__DATA)'; test -n "$(pmacct_examples_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_amqp_DATA: $(pmacct_examples_amqp__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_amqp__DATA)'; test -n "$(pmacct_examples_amqp_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_amqp_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_amqp_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_amqp_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_amqp_dir)" || exit $$?; \ done uninstall-pmacct_examples_amqp_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_amqp__DATA)'; test -n "$(pmacct_examples_amqp_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_amqp_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_avro_DATA: $(pmacct_examples_avro__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_avro__DATA)'; test -n "$(pmacct_examples_avro_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_avro_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_avro_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_avro_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_avro_dir)" || exit $$?; \ done uninstall-pmacct_examples_avro_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_avro__DATA)'; test -n "$(pmacct_examples_avro_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_avro_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_custom_DATA: $(pmacct_examples_custom__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_custom__DATA)'; test -n "$(pmacct_examples_custom_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_custom_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_custom_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_custom_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_custom_dir)" || exit $$?; \ done uninstall-pmacct_examples_custom_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_custom__DATA)'; test -n "$(pmacct_examples_custom_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_custom_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_kafka_DATA: $(pmacct_examples_kafka__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_kafka__DATA)'; test -n "$(pmacct_examples_kafka_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_kafka_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_kafka_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_kafka_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_kafka_dir)" || exit $$?; \ done uninstall-pmacct_examples_kafka_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_kafka__DATA)'; test -n "$(pmacct_examples_kafka_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_kafka_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_lg_DATA: $(pmacct_examples_lg__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_lg__DATA)'; test -n "$(pmacct_examples_lg_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_lg_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_lg_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_lg_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_lg_dir)" || exit $$?; \ done uninstall-pmacct_examples_lg_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_lg__DATA)'; test -n "$(pmacct_examples_lg_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_lg_dir)'; $(am__uninstall_files_from_dir) install-pmacct_examples_lg_arch_DATA: $(pmacct_examples_lg_arch__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_examples_lg_arch__DATA)'; test -n "$(pmacct_examples_lg_arch_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_examples_lg_arch_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_examples_lg_arch_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_examples_lg_arch_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_examples_lg_arch_dir)" || exit $$?; \ done uninstall-pmacct_examples_lg_arch_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_examples_lg_arch__DATA)'; test -n "$(pmacct_examples_lg_arch_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_examples_lg_arch_dir)'; $(am__uninstall_files_from_dir) install-pmacct_sql_DATA: $(pmacct_sql__DATA) @$(NORMAL_INSTALL) @list='$(pmacct_sql__DATA)'; test -n "$(pmacct_sql_dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pmacct_sql_dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pmacct_sql_dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pmacct_sql_dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pmacct_sql_dir)" || exit $$?; \ done uninstall-pmacct_sql_DATA: @$(NORMAL_UNINSTALL) @list='$(pmacct_sql__DATA)'; test -n "$(pmacct_sql_dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pmacct_sql_dir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pmacct_data_dir)" "$(DESTDIR)$(pmacct_docs_dir)" "$(DESTDIR)$(pmacct_examples_dir)" "$(DESTDIR)$(pmacct_examples_amqp_dir)" "$(DESTDIR)$(pmacct_examples_avro_dir)" "$(DESTDIR)$(pmacct_examples_custom_dir)" "$(DESTDIR)$(pmacct_examples_kafka_dir)" "$(DESTDIR)$(pmacct_examples_lg_dir)" "$(DESTDIR)$(pmacct_examples_lg_arch_dir)" "$(DESTDIR)$(pmacct_sql_dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pmacct_data_DATA install-pmacct_docs_DATA \ install-pmacct_examples_DATA install-pmacct_examples_amqp_DATA \ install-pmacct_examples_avro_DATA \ install-pmacct_examples_custom_DATA \ install-pmacct_examples_kafka_DATA \ install-pmacct_examples_lg_DATA \ install-pmacct_examples_lg_arch_DATA install-pmacct_sql_DATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pmacct_data_DATA uninstall-pmacct_docs_DATA \ uninstall-pmacct_examples_DATA \ uninstall-pmacct_examples_amqp_DATA \ uninstall-pmacct_examples_avro_DATA \ uninstall-pmacct_examples_custom_DATA \ uninstall-pmacct_examples_kafka_DATA \ uninstall-pmacct_examples_lg_DATA \ uninstall-pmacct_examples_lg_arch_DATA \ uninstall-pmacct_sql_DATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip dist-zstd distcheck distclean \ distclean-generic distclean-libtool distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-pmacct_data_DATA install-pmacct_docs_DATA \ install-pmacct_examples_DATA install-pmacct_examples_amqp_DATA \ install-pmacct_examples_avro_DATA \ install-pmacct_examples_custom_DATA \ install-pmacct_examples_kafka_DATA \ install-pmacct_examples_lg_DATA \ install-pmacct_examples_lg_arch_DATA install-pmacct_sql_DATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-pmacct_data_DATA \ uninstall-pmacct_docs_DATA uninstall-pmacct_examples_DATA \ uninstall-pmacct_examples_amqp_DATA \ uninstall-pmacct_examples_avro_DATA \ uninstall-pmacct_examples_custom_DATA \ uninstall-pmacct_examples_kafka_DATA \ uninstall-pmacct_examples_lg_DATA \ uninstall-pmacct_examples_lg_arch_DATA \ uninstall-pmacct_sql_DATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/sql/0000755000175000017500000000000014354105275012611 5ustar paolopaolopmacct-1.7.8/sql/pmacct-create-table_v2.sqlite30000755000175000017500000000131714354105275020330 0ustar paolopaoloDROP TABLE IF EXISTS acct_v2; CREATE TABLE acct_v2 ( agent_id INT(8) NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db.pgsql0000755000175000017500000000062714354105275016764 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d template1 -f pmacct-create-db.pgsql -- -- NOTE: you should have a line like "local all password" in your pg_hba.conf -- to authenticate local users against Postgres userbase passwords. -- DROP DATABASE pmacct; CREATE DATABASE pmacct; CREATE USER pmacct; ALTER USER pmacct WITH PASSWORD 'arealsmartpwd'; pmacct-1.7.8/sql/README.export_proto0000644000175000017500000000216614354105275016241 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. export_proto fields. Such fields are being introduced to inform about different aspects (typically part of the headers) of the export protocol (ie. NetFlow, sFlow, IPFIX). Guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * export_proto_seqno field: - "export_proto_seqno INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., export_proto_seqno, ...)" to put it in the primary key * export_proto_version field: - "export_proto_version INT(2) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., export_proto_version, ...)" to put it in the primary key * export_proto_sysid field: - "export_proto_sysid INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., export_proto_sysid, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/README.label0000644000175000017500000000130514354105275014546 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'label' field. Such field carries variable string tags and is equivalent in purpose to tag and tag2, with the exception tag and tag2 are numerical-only. The guidelines below (typically in MySQL format) are to add such primitive to the SQL schema: * label field: - "label VARCHAR(255) NOT NULL," to declare the field itself - "PRIMARY KEY (..., label, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-table_v2.pgsql0000755000175000017500000000634314354105275020076 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v2.pgsql -- -- Tables DROP TABLE IF EXISTS acct_uni_v2; CREATE TABLE acct_uni_v2 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_uni_v2_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS acct_v2; CREATE TABLE acct_v2 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v2_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS acct_as_v2; CREATE TABLE acct_as_v2 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src INT NOT NULL DEFAULT 0, ip_dst INT NOT NULL DEFAULT 0, port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_as_v2_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_uni_v2 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v2 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_as_v2 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_v6.sqlite30000755000175000017500000000165414354105275020340 0ustar paolopaoloDROP TABLE IF EXISTS acct_v6; CREATE TABLE acct_v6 ( agent_id INT(8) NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, as_src INT(8) NOT NULL DEFAULT 0, as_dst INT(8) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.iface0000644000175000017500000000162514354105275014543 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'iface_in' and 'iface_out' fields. Such fields are being introduced to natively support input/output interface indexes as received from sFlow, NetFlow or NFLOG packet capturing framework. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * iface_in field: - "iface_in INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., iface_in, ...)" to put it in the primary key * iface_out field: - "iface_out INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., iface_out, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/README.pgsql0000644000175000017500000003167414354105275014631 0ustar paolopaoloSee how to configure and compile pmacct for PostgreSQL use in the "Configuring pmacct for compilation and installing" chapter of QUICKSTART. To create the database and grant default permission to the daemon you have to execute the two scripts below, in the same order; which user has to execute them and how to autenticate with the PostgreSQL server depends upon your current configuration. Keep in mind that both scripts need postgres superuser permissions to execute commands successfully: shell> cp -p *.pgsql /tmp shell> su - postgres - To create v1 tables: * psql -d template1 -f /tmp/pmacct-create-db.pgsql * psql -d pmacct -f /tmp/pmacct-create-table_v1.pgsql - To use v1 tables: * data will be available in 'acct' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. - To create v2 tables: * psql -d template1 -f /tmp/pmacct-create-db.pgsql * psql -d pmacct -f /tmp/pmacct-create-table_v2.pgsql - To use v2 tables: * data will be available in 'acct_v2' table of 'pmacct' DB. * Add 'sql_table_version: 2' line to your configuration. [ ... ] - To create v7 or v8 tables: * psql -d template1 -f /tmp/pmacct-create-db.pgsql * psql -d pmacct -f /tmp/pmacct-create-table_v7_v8.pgsql - To use v7 or v8 tables: * data will be available in 'acct_v7' table of 'pmacct' DB. * Add 'sql_table_version: 7' line to your configuration. Similarly, BGP tables: - To create BGP v1 tables: * psql -d template1 -f /tmp/pmacct-create-db.pgsql * psql -d pmacct -f /tmp/pmacct-create-table_bgp_v1.pgsql - To use BGP v1 tables: * data will be available in 'acct_bgp' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. * Add 'sql_table_type: bgp' line to your configuration. Until SQL table schemas v5 a few tables are created in the 'pmacct' database: 'acct' (or 'acct_vN') table is the default table where data will be written when in 'typed' mode (see 'sql_data' option in CONFIG-KEYS text file; default value is 'typed'); 'acct_uni' (or 'acct_uni_vN') is the default table where data will be written when in 'unified' mode. Starting with v6 unified schemas are no longer supplied as part of the PostgreSQL table creation script. - To understand difference between the various table versions: * Do you need any of the BGP primitives ? Then look the next section. * Do you need tags for traffic tagging ? Then you have to use v9. * Do you need TCP flags ? Then you have to use v7. * Do you need both IP addresses and AS numbers in the same table ? Then you have to use v6. * Do you need packet classification ? Then you have to use v5. * Do you need flows (other than packets) accounting ? Then you have to use v4. * Do you need ToS/DSCP field (QoS) accounting ? Then you have to use v3. * Do you need VLAN traffic accounting ? Then you have to use v2. * If all of the above points sound useless, then use v1. * v8 changes field names so to bring all supported databases to the same naming convention. - To understand difference between the various BGP table versions: * Only BGP table v1 is currently available. - Aggregation primitives to SQL schema mapping. Although default schemas come all with "NOT NULL", this is optional and depending on the scenario: for example, if mixed L2 (containing L2 only info) and L3 (containing L2 and L3 info) flows are collected, maybe L3-related fields like src_host or dst_host are best defined without the "NOT NULL" constraint. Aggregation primitive => SQL table field * tag => agent_id (BIGINT NOT NULL DEFAULT 0) - or tag => tag (BIGINT NOT NULL DEFAULT 0, if sql_table_version >= 9) * tag2 => tag2 (BIGINT NOT NULL DEFAULT 0, see README.tag2) * label => label (VARCHAR(255) NOT NULL DEFAULT ' ', see README.label) * src_as => as_src (BIGINT NOT NULL DEFAULT 0) - or src_as => ip_src (BIGINT NOT NULL DEFAULT 0, if sql_table_version < 6) * dst_as => as_dst (BIGINT NOT NULL DEFAULT 0) - or dst_as => ip_dst (BIGINT NOT NULL DEFAULT 0, if sql_table_version < 6) * peer_src_as => peer_as_src (BIGINT NOT NULL DEFAULT 0) * peer_dst_as => peer_as_dst (BIGINT NOT NULL DEFAULT 0) * peer_src_ip => peer_ip_src (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * peer_dst_ip => peer_ip_dst (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * mpls_vpn_rd => mpls_vpn_rd (CHAR(18) NOT NULL DEFAULT ' ') * std_comm => comms (CHAR(24) NOT NULL DEFAULT ' ') * ext_comm => ecomms (CHAR(24) NOT NULL DEFAULT ' ') * lrg_comm => lcomms (CHAR(24) NOT NULL DEFAULT ' ') * as_path => as_path (CHAR(21) NOT NULL DEFAULT ' ') * local_pref => local_pref (BIGINT NOT NULL DEFAULT 0) * med => med (BIGINT NOT NULL DEFAULT 0) * dst_roa => roa_dst (CHAR(1) NOT NULL DEFAULT ' ') * src_std_comm => comms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_ext_comm => ecomms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_lrg_comm => lcomms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_as_path => as_path_src (CHAR(21) NOT NULL DEFAULT ' ') * src_local_pref => local_pref_src (BIGINT NOT NULL DEFAULT 0) * src_med => med_src (BIGINT NOT NULL DEFAULT 0) * src_roa => roa_src (CHAR(1) NOT NULL DEFAULT ' ') * in_iface => iface_in (BIGINT NOT NULL DEFAULT 0, see README.iface) * out_iface => iface_out (BIGINT NOT NULL DEFAULT 0, see README.iface) * src_mask => mask_src (SMALLINT NOT NULL DEFAULT 0, see README.mask) * dst_mask => mask_dst (SMALLINT NOT NULL DEFAULT 0, see README.mask) * cos => cos (SMALLINT NOT NULL DEFAULT 0, see README.cos) * etype => etype (CHAR(5) NOT NULL DEFAULT ' ', see README.etype) * src_host_country => country_ip_src (CHAR (2) NOT NULL DEFAULT '--', see README.GeoIP) * dst_host_country => country_ip_dst (CHAR (2) NOT NULL DEFAULT '--', see README.GeoIP) * src_host_pocode => pocode_ip_src (CHAR (12) NOT NULL DEFAULT ' ', see README.GeoIP) * dst_host_pocode => pocode_ip_dst (CHAR (12) NOT NULL DEFAULT ' ', see README.GeoIP) * src_host_coords => lat_ip_src (REAL NOT NULL DEFAULT 0, see README.GeoIP) * src_host_coords => lon_ip_src (REAL NOT NULL DEFAULT 0, see README.GeoIP) * dst_host_coords => lat_ip_dst (REAL NOT NULL DEFAULT 0, see README.GeoIP) * dst_host_coords => lon_ip_dst (REAL NOT NULL DEFAULT 0, see README.GeoIP) * sampling_rate => sampling_rate (BIGINT NOT NULL DEFAULT 0, see README.sampling) * sampling_direction => sampling_direction (CHAR (1) NOT NULL DEFAULT ' ', see README.sampling) * class => class_id (CHAR(16) NOT NOT NULL DEFAULT ' ') * src_mac => mac_src (macaddr NOT NULL DEFAULT '0:0:0:0:0:0') * dst_mac => mac_dst (macaddr NOT NULL DEFAULT '0:0:0:0:0:0') * vlan => vlan (INT NOT NULL DEFAULT 0) * in_vlan => vlan_in (INT NOT NULL DEFAULT 0) * out_vlan => vlan_out (INT NOT NULL DEFAULT 0) * src_as => as_src (BIGINT NOT NULL DEFAULT 0) * dst_as => as_dst (BIGINT NOT NULL DEFAULT 0) * src_host => ip_src (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * dst_host => ip_dst (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * src_net => net_src (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * dst_net => net_dst (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * src_port => port_src (INT NOT NULL DEFAULT 0) * dst_port => port_dst (INT NOT NULL DEFAULT 0) * tcpflags => tcp_flags (SMALLINT NOT NULL DEFAULT 0) * proto => ip_proto (SMALLINT NOT NULL DEFAULT 0) * tos => tos (INT NOT NULL DEFAULT 0) * post_nat_src_host => post_nat_ip_src (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * post_nat_dst_host => post_nat_ip_dst (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * post_nat_src_port => post_nat_port_src (INT NOT NULL DEFAULT 0) * post_nat_dst_port => post_nat_port_dst (INT NOT NULL DEFAULT 0) * nat_event => nat_event (INT NOT NULL DEFAULT 0) * fwd_status => fwd_status (INT NOT NULL DEFAULT 0) - or (VARCHAR(50) NOT NULL DEFAULT ' ', if fwd_status_encode_as_string: true) * mpls_label_top => mpls_label_top (INT NOT NULL DEFAULT 0) * mpls_label_bottom => mpls_label_bottom (INT NOT NULL DEFAULT 0) * mpls_label_stack => mpls_label_stack (VARCHAR(255) NOT NULL DEFAULT ' ') * tunnel_src_mac => tunnel_mac_src (macaddr NOT NULL DEFAULT '0:0:0:0:0:0') * tunnel_dst_mac => tunnel_mac_dst (macaddr NOT NULL DEFAULT '0:0:0:0:0:0') * tunnel_src_host => tunnel_ip_src (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * tunnel_dst_host => tunnel_ip_dst (inet NOT NULL DEFAULT '0.0.0.0', see README.IPv6) * tunnel_proto => tunnel_ip_proto (SMALLINT NOT NULL DEFAULT 0) * tunnel_tos => tunnel_tos (INT NOT NULL DEFAULT 0) * tunnel_src_port => tunnel_port_src (INT NOT NULL DEFAULT 0) * tunnel_dst_port => tunnel_port_dst (INT NOT NULL DEFAULT 0) * tunnel_tcpflags => tunnel_tcp_flags (SMALLINT NOT NULL DEFAULT 0) * timestamp_start => timestamp_start, timestamp_start_residual: - timestamp_start timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00', see README.timestamp) - timestamp_start_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_end => timestamp_end, timestamp_end_residual: - timestamp_end timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00', see README.timestamp) - timestamp_end_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_arrival => timestamp_arrival, timestamp_arrival_residual: - timestamp_arrival timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00', see README.timestamp) - timestamp_arrival_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_min => timestamp_min, timestamp_min_residual: - timestamp_min timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00', see README.timestamp) - timestamp_min_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_max => timestamp_max, timestamp_max_residual: - timestamp_max timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00', see README.timestamp) - timestamp_max_residual INT NOT NULL DEFAULT 0, see README.timestamp) * export_proto_seqno => export_proto_seqno (INT NOT NULL DEFAULT 0, see README.export_proto) * export_proto_version => export_proto_version (SMALLINT NOT NULL DEFAULT 0, see README.export_proto) * export_proto_sysid => export_proto_sysid (INT NOT NULL DEFAULT 0, see README.export_proto) - If not using COPY statements (sql_use_copy, sql_dont_try_update both enabled) 'packets' and 'bytes' counters need to be defined as part of the SQL schema whenever traffic flows are being accounted for; they are not required, and are zeroed, if accounting for events, ie. using Cisco NEL; if instead COPY is in use, 'packets' and 'bytes' counters are mandatory. 'stamp_inserted' and 'stamp_updated' time references are mandatory only if temporal aggregation (sql_history) is enabled: * packets (INT NOT NULL) - or (packets BIGINT NOT NULL) * flows (INT NOT NULL) - or (flows BIGINT NOT NULL) * bytes (BIGINT NOT NULL) * stamp_inserted (timestamp without time zone NOT NULL DEFAULT '0000-01-01 00:00:00') or (stamp_inserted bigint NOT NULL DEFAULT 0, if timestamps_since_epoch: true) * stamp_updated (timestamp without time zone) or (stamp_updated bigint DEFAULT 0, if timestamps_since_epoch: true) - For custom-defined primitives refer to the README.custom_primitives doc. - What is the difference between 'typed' and 'unified' modes ? Read this section only if using a table schema v5 or below and does not apply to BGP table schemas. The 'unified' table has IP addresses and MAC addresses specified as standard CHAR strings, slower but flexible; 'typed' tables feature PostgreSQL own types (inet, mac, etc.), faster but rigid. When not specifying your own 'sql_table', this switch instructs the plugin which tables has to use, default being 'typed'. Since v6 this is all deprecated but default typed schemas, the only still supplied as part of the PostgreSQL table creation script, can still be customized transparently to pmacct. - What is the 'proto' table ? The auxiliar 'proto' table will be created by default. Its tuples are simply number-string pairs: the protocol field of both typed and unified tables is numerical. This table helps in looking up protocol names by their number and viceversa. Because joins are expensive, 'proto' table has been created *only* for your personal reference. NOTE: certain primitives, ie. BGP attributtes like AS-PATH and communities (as_path, std_comm, etc.), can get arbitrarily long if not properly scoped (ie. bgp_aspath_radius, bgp_stdcomm_pattern, etc.) and hence not fit in default field definitions (ie. CHAR(21) or CHAR(24)). It is possible to define these as arbitrarily-long variable-length strings using VARCHAR or TEXT data types. Consult latest PostgreSQL docs for examples and notes (charset choices, etc.). NOTE: mind to specify EVERYTIME which SQL table version you intend to adhere to by using the following config directives: * sql_table_version: [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ] * sql_table_type: [ bgp ] NOTE: specifying a non-documented SQL table profile will result in an non-determined behaviour. Unless this will create crashes to the application, such situations will not be supported. pmacct-1.7.8/sql/README.tunnel0000644000175000017500000000420114354105275014772 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'vxlan', and 'tunnel_*' fields. Such fields are being introduced to support tunnel primitives. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * vxlan field: - "vxlan INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., vxlan, ...)" to put it in the primary key * tunnel_mac_src field: - "tunnel_mac_src (CHAR(17) NOT NULL)," to declare the field itself - "PRIMARY KEY (..., tunnel_mac_src, ...)" to put it in the primary key * tunnel_mac_dst field: - "tunnel_mac_dst (CHAR(17) NOT NULL)," to declare the field itself - "PRIMARY KEY (..., tunnel_mac_dst, ...)" to put it in the primary key * tunnel_ip_src field: - "tunnel_ip_src CHAR(45) NOT NULL," to declare the field itself (*) - "PRIMARY KEY (..., tunnel_ip_src, ...)" to put it in the primary key * tunnel_ip_dst field: - "tunnel_ip_dst CHAR(45) NOT NULL," to declare the field itself (*) - "PRIMARY KEY (..., tunnel_ip_dst, ...)" to put it in the primary key * tunnel_ip_proto field: - "tunnel_ip_proto CHAR(6) NOT NULL," to declare the field itself (**) - "PRIMARY KEY (..., tunnel_ip_proto, ...)" to put it in the primary key * tunnel_ip_tos field: - "tunnel_ip_tos INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., tunnel_ip_tos, ...)" to put it in the primary key * tunnel_port_src field: - "tunnel_port_src (INT(2) UNSIGNED NOT NULL)," to declare the field itself - "PRIMARY KEY (..., tunnel_port_src, ...)" to put it in the primary key * tunnel_port_dst field: - "tunnel_port_dst (INT(2) UNSIGNED NOT NULL)," to declare the field itself - "PRIMARY KEY (..., tunnel_port_dst, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. (*) Field must be longer for IPv6 addresses. See README.IPv6 (**) Field must be defined as "INT(1) UNSIGNED NOT NULL" if sql_num_protos: true pmacct-1.7.8/sql/README.mysql0000644000175000017500000002563414354105275014647 0ustar paolopaoloSee how to configure and compile pmacct for MySQL/MariaDB use in the "Configuring pmacct for compilation and installing" chapter of QUICKSTART. To create the database and grant default permission to pmacctd you have to execute the two scripts below, in the same order (assuming mysql command is in the path): - To create v1 tables: * mysql -u root -p < pmacct-create-db_v1.mysql * mysql -u root -p < pmacct-grant-db.mysql - To use v1 tables: * data will be available in 'acct' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. Similarly, v2 to v9 tables: - To create v2 tables: * mysql -u root -p < pmacct-create-db_v2.mysql * mysql -u root -p < pmacct-grant-db.mysql - To use v2 tables: * data will be available in 'acct_v2' table of 'pmacct' DB. * Add 'sql_table_version: 2' line to your configuration. [ ... ] - To create v9 tables: * mysql -u root -p < pmacct-create-db_v9.mysql * mysql -u root -p < pmacct-grant-db.mysql - To use v9 tables: * data will be available in 'acct_v9' table of 'pmacct' DB. * Add 'sql_table_version: 9' line to your configuration. Similarly, BGP tables: - To create BGP v1 tables: * mysql -u root -p < pmacct-create-db_bgp_v1.mysql * mysql -u root -p < pmacct-grant-db.mysql - To use BGP v1 tables: * data will be available in 'acct_bgp' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. * Add 'sql_table_type: bgp' line to your configuration. - To understand difference between the various table versions: * Do you need any of the BGP primitives ? Then look the next section. * Do you need tags for traffic tagging ? Then you have to use v9. * Do you need TCP flags ? Then you have to use v7. * Do you need both IP addresses and AS numbers in the same table ? Then you have to use v6. * Do you need packet classification ? Then you have to use v5. * Do you need flows (other than packets) accounting ? Then you have to use v4. * Do you need ToS/DSCP field (QoS) accounting ? Then you have to use v3. * Do you need VLAN traffic accounting ? Then you have to use v2. * If all of the above points sound useless, then use v1. * v8 changes field names so to bring all supported databases to the same naming convention. - To understand difference between the various BGP table versions: * Only BGP table v1 is currently available. - Aggregation primitives to SQL schema mapping. Although default schemas come all with "NOT NULL", this is optional and depending on the scenario: for example, if mixed L2 (containing L2 only info) and L3 (containing L2 and L3 info) flows are collected, maybe L3-related fields like src_host or dst_host are best defined without the "NOT NULL" constraint. Aggregation primitive => SQL table field: * tag => agent_id (INT(4) UNSIGNED NOT NULL) - or tag => tag (INT(4) UNSIGNED NOT NULL, if sql_table_version >= 9) * tag2 => tag2 (INT(4) UNSIGNED NOT NULL, see README.tag2) * label => label (VARCHAR(255) NOT NULL, see README.label) * src_as => as_src (INT(4) UNSIGNED NOT NULL) - or src_as => ip_src (INT(4) UNSIGNED NOT NULL), if sql_table_version < 6) * dst_as => as_dst (INT(4) UNSIGNED NOT NULL) - or dst_as => ip_dst (INT(4) UNSIGNED NOT NULL), if sql_table_version < 6) * peer_src_as => peer_as_src (INT(4) UNSIGNED NOT NULL) * peer_dst_as => peer_as_dst (INT(4) UNSIGNED NOT NULL) * peer_src_ip => peer_ip_src (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * peer_dst_ip => peer_ip_dst (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * mpls_vpn_rd => mpls_vpn_rd (CHAR(18) NOT NULL) * std_comm => comms (CHAR(24) NOT NULL) * ext_comm => ecomms (CHAR(24) NOT NULL) * lrg_comm => lcomms (CHAR(24) NOT NULL) * as_path => as_path (CHAR(21) NOT NULL) * local_pref => local_pref (INT(4) UNSIGNED NOT NULL) * med => med (INT(4) UNSIGNED NOT NULL) * dst_roa => roa_dst (CHAR(1) NULL) * src_std_comm => comms_src (CHAR(24) NOT NULL) * src_ext_comm => ecomms_src (CHAR(24) NOT NULL) * src_lrg_comm => lcomms_src (CHAR(24) NOT NULL) * src_as_path => as_path_src (CHAR(21) NOT NULL) * src_local_pref => local_pref_src (INT(4) UNSIGNED NOT NULL) * src_med => med_src (INT(4) UNSIGNED NOT NULL) * src_roa => roa_src (CHAR(1) NULL) * in_iface => iface_in (INT(4) UNSIGNED NOT NULL, see README.iface) * out_iface => iface_out (INT(4) UNSIGNED NOT NULL, see README.iface) * src_mask => mask_src (INT(1) UNSIGNED NOT NULL, see README.mask) * dst_mask => mask_dst (INT(1) UNSIGNED NOT NULL, see README.mask) * cos => cos (INT(1) UNSIGNED NOT NULL, see README.cos) * etype => etype (CHAR(5) NOT NULL, see README.etype) * src_host_country => country_ip_src (CHAR(2) NOT NULL, see README.GeoIP) * dst_host_country => country_ip_dst (CHAR(2) NOT NULL, see README.GeoIP) * src_host_pocode => pocode_ip_src (CHAR(12) NOT NULL, see README.GeoIP) * dst_host_pocode => pocode_ip_dst (CHAR(12) NOT NULL, see README.GeoIP) * src_host_coords => lat_ip_src (FLOAT NOT NULL, see README.GeoIP) * src_host_coords => lon_ip_src (FLOAT NOT NULL, see README.GeoIP) * dst_host_coords => lat_ip_dst (FLOAT NOT NULL, see README.GeoIP) * dst_host_coords => lon_ip_dst (FLOAT NOT NULL, see README.GeoIP) * sampling_rate => sampling_rate (INT(4) UNSIGNED NOT NULL, see README.sampling) * sampling_direction => sampling_direction (CHAR(1) NOT NULL, see README.sampling) * class => class_id (CHAR(16) NOT NULL) * src_mac => mac_src (CHAR(17) NOT NULL) * dst_mac => mac_dst (CHAR(17) NOT NULL) * vlan => vlan (INT(2) UNSIGNED NOT NULL) * in_vlan => vlan_in (INT(2) UNSIGNED NOT NULL) * out_vlan => vlan_out (INT(2) UNSIGNED NOT NULL) * src_as => as_src (INT(4) UNSIGNED NOT NULL) * dst_as => as_dst (INT(4) UNSIGNED NOT NULL) * src_host => ip_src (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * dst_host => ip_dst (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * src_net => net_src (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * dst_net => net_dst (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * src_port => src_port (INT(2) UNSIGNED NOT NULL) - or src_port => port_src (INT(2) UNSIGNED NOT NULL, if sql_table_version >= 8) * dst_port => dst_port (INT(2) UNSIGNED NOT NULL) - or dst_port => port_dst (INT(2) UNSIGNED NOT NULL, if sql_table_version >= 8) * tcpflags => tcp_flags (INT(2) UNSIGNED NOT NULL) * proto => ip_proto (CHAR(6) NOT NULL) - or (INT(1) UNSIGNED NOT NULL, if sql_num_protos: true) * tos => tos (INT(4) UNSIGNED NOT NULL) * post_nat_src_host => post_nat_ip_src (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * post_nat_dst_host => post_nat_ip_dst (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * post_nat_src_port => post_nat_port_src (INT(2) UNSIGNED NOT NULL) * post_nat_dst_port => post_nat_port_dst (INT(2) UNSIGNED NOT NULL) * nat_event => nat_event (INT(1) UNSIGNED NOT NULL) * fwd_status => fwd_status (INT(1) UNSIGNED NOT NULL) - or (VARCHAR(50) NOT NULL, if fwd_status_encode_as_string: true) * mpls_label_top => mpls_label_top (INT(4) UNSIGNED NOT NULL) * mpls_label_bottom => mpls_label_bottom (INT(4) UNSIGNED NOT NULL) * mpls_label_stack => mpls_label_stack (VARCHAR(255) NOT NULL) * tunnel_src_mac => tunnel_mac_src (CHAR(17) NOT NULL) * tunnel_dst_mac => tunnel_mac_dst (CHAR(17) NOT NULL) * tunnel_src_host => tunnel_ip_src (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * tunnel_dst_host => tunnel_ip_dst (CHAR(45) NOT NULL) - or (VARBINARY(16) NOT NULL, if sql_num_hosts: true) * tunnel_proto => tunnel_ip_proto (CHAR(6) NOT NULL) - or (INT(1) UNSIGNED NOT NULL, if sql_num_protos: true) * tunnel_tos => tunnel_tos (INT(4) UNSIGNED NOT NULL) * tunnel_src_port => tunnel_port_src (INT(2) UNSIGNED NOT NULL) * tunnel_dst_port => tunnel_port_dst (INT(2) UNSIGNED NOT NULL) * tunnel_tcpflags => tunnel_tcp_flags (INT(2) UNSIGNED NOT NULL) * timestamp_start => timestamp_start, timestamp_start_residual: - timestamp_start DATETIME NOT NULL, see README.timestamp) - timestamp_start_residual INT NOT NULL, see README.timestamp) * timestamp_end => timestamp_end, timestamp_end_residual: - timestamp_end DATETIME NOT NULL, see README.timestamp) - timestamp_end_residual INT NOT NULL, see README.timestamp) * timestamp_arrival => timestamp_arrival, timestamp_arrival_residual: - timestamp_arrival DATETIME NOT NULL, see README.timestamp) - timestamp_arrival_residual INT NOT NULL, see README.timestamp) * timestamp_min => timestamp_min, timestamp_min_residual: - timestamp_min DATETIME NOT NULL, see README.timestamp) - timestamp_min_residual INT NOT NULL, see README.timestamp) * timestamp_max => timestamp_max, timestamp_max_residual: - timestamp_max DATETIME NOT NULL, see README.timestamp) - timestamp_max_residual INT NOT NULL, see README.timestamp) * export_proto_seqno => export_proto_seqno (INT(4) UNSIGNED NOT NULL, see README.export_proto) * export_proto_version => export_proto_version (INT(2) UNSIGNED NOT NULL, see README.export_proto) * export_proto_sysid => export_proto_sysid (INT(4) UNSIGNED NOT NULL, see README.export_proto) - 'packets' and 'bytes' counters need to be defined as part of the SQL schema whenever traffic flows are being accounted for; they are not required, and are zeroed, if accounting for events, ie. using Cisco NEL; 'stamp_inserted' and 'stamp_updated' time references are mandatory only if temporal aggregation (sql_history) is enabled: * flows (INT UNSIGNED NOT NULL) - or (flows BIGINT UNSIGNED NOT NULL) * packets (INT UNSIGNED NOT NULL) - or (packets BIGINT UNSIGNED NOT NULL) * bytes (BIGINT UNSIGNED NOT NULL) * stamp_inserted (DATETIME NOT NULL) - or (stamp_inserted BIGINT UNSIGNED NOT NULL, if timestamps_since_epoch: true) * stamp_updated (DATETIME) - or (stamp_updated BIGINT UNSIGNED, if timestamps_since_epoch: true) - For custom-defined primitives refer to the README.custom_primitives doc. NOTE: certain primitives, ie. BGP attributtes like AS-PATH and communities (as_path, std_comm, etc.), can get arbitrarily long if not properly scoped (ie. bgp_aspath_radius, bgp_stdcomm_pattern, etc.) and hence not fit in default field definitions (ie. CHAR(21) or CHAR(24)). It is possible to define these as arbitrarily-long variable-length strings using VARCHAR or TEXT data types. Consult latest MySQL/MariaDB docs for examples and notes (charset choices, etc.). NOTE: mind to specify EVERYTIME which SQL table version you intend to adhere to by using the following config directives: * sql_table_version: [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ] * sql_table_type: [ bgp ] NOTE: specifying a non-documented SQL table profile will result in an non-determined behaviour. Unless this will create crashes to the application, such situations will not be supported. pmacct-1.7.8/sql/pmacct-create-table_v9.sqlite30000755000175000017500000000171314354105275020337 0ustar paolopaoloDROP TABLE IF EXISTS acct_v9; CREATE TABLE acct_v9 ( tag INT(8) NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, as_src INT(8) NOT NULL DEFAULT 0, as_dst INT(8) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT(4) NOT NULL DEFAULT 0, port_dst INT(4) NOT NULL DEFAULT 0, tcp_flags INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (tag, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.sampling0000644000175000017500000000205414354105275015303 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'sampling_rate' and 'sampling_direction' fields. Sampling rate is being introduced to inform about the renormalization factor that has to be applied to entries. If renormalization is enabled then value of this field is, intuitively, 1. Sampling direction informs whether data is captured ingress vs egress. Guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * sampling_rate field: - "sampling_rate INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., sampling_rate, ...)" to put it in the primary key * sampling_direction field: - "sampling_direction CHAR(1) NOT NULL," to declare the field itself - "PRIMARY KEY (..., sampling_direction, ...)" to put it in the primary key The primitives are not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-db_v1.mysql0000755000175000017500000000111314354105275017400 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct; create table acct ( mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (mac_src, mac_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v3.pgsql0000755000175000017500000000652214354105275020076 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v3.pgsql -- -- Tables DROP TABLE IF EXISTS acct_uni_v3; CREATE TABLE acct_uni_v3 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_uni_v3_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_v3; CREATE TABLE acct_v3 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v3_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_as_v3; CREATE TABLE acct_as_v3 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src INT NOT NULL DEFAULT 0, ip_dst INT NOT NULL DEFAULT 0, port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_as_v3_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_uni_v3 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v3 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_as_v3 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_v4.pgsql0000755000175000017500000000667014354105275020103 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v4.pgsql -- -- Tables DROP TABLE IF EXISTS acct_uni_v4; CREATE TABLE acct_uni_v4 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_uni_v4_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_v4; CREATE TABLE acct_v4 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v4_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_as_v4; CREATE TABLE acct_as_v4 ( agent_id BIGINT NOT NULL DEFAULT 0, mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src INT NOT NULL DEFAULT 0, ip_dst INT NOT NULL DEFAULT 0, port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_as_v4_pk PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_uni_v4 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v4 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_as_v4 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_bgp_v1.sqlite30000755000175000017500000000152714354105275021162 0ustar paolopaoloDROP TABLE IF EXISTS acct_bgp; CREATE TABLE acct_bgp ( agent_id INT(8) NOT NULL DEFAULT 0, as_src INT(8) NOT NULL DEFAULT 0, as_dst INT(8) NOT NULL DEFAULT 0, peer_as_src INT(8) NOT NULL DEFAULT 0, peer_as_dst INT(8) NOT NULL DEFAULT 0, peer_ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', peer_ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', comms CHAR(24) NOT NULL DEFAULT ' ', as_path CHAR(21) NOT NULL DEFAULT ' ', local_pref INT(8) NOT NULL DEFAULT 0, med INT(8) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, as_src, as_dst, peer_as_src, peer_as_dst, peer_ip_src, peer_ip_dst, comms, as_path, local_pref, med, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db_v4.mysql0000755000175000017500000000136414354105275017413 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v4; create table acct_v4 ( agent_id INT(4) UNSIGNED NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v5.sqlite30000755000175000017500000000152014354105275020327 0ustar paolopaoloDROP TABLE IF EXISTS acct_v5; CREATE TABLE acct_v5 ( agent_id INT(8) NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db_v7.mysql0000755000175000017500000000164014354105275017413 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v7; create table acct_v7 ( agent_id INT(4) UNSIGNED NOT NULL, class_id CHAR(16) NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, tcp_flags INT(4) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db_v5.mysql0000755000175000017500000000143614354105275017414 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v5; create table acct_v5 ( agent_id INT(4) UNSIGNED NOT NULL, class_id CHAR(16) NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.custom_primitives0000644000175000017500000000433014354105275017255 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. Custom-defined primitives: SQL schema field name. The field name of custom-defined primitives is derived from the primitive name, ie. if, in a aggregate_primitives file, is defined a primitive with name 'blabla' then it is expected the SQL schema will contain a field named 'blabla'. Custom-defined primitives: SQL schema field definition. The field definition should be worked out intuitively starting from the definition of the primitive itself in the aggregate_primitives file. Following the SQL schema (in MySQL format) worked out for the couple of examples provided as part of the 'examples/primitives.lst' doc: name=mtla field_type=47 len=4 semantics=ip Semantics is 'ip', so the field contains an IP address, length being 4 meaning only IPv4 addresses are expected. The corresponding SQL field can be defined as follows: "mtla CHAR(15) NOT NULL". If the primitive would have been suitable to also travel IPv6 addresses, the field could have been defined according to guidelines in the README.IPv6 doc (essentially CHAR(45) instead of CHAR(15). name=mtlpl field_type=91 len=1 semantics=u_int Semantics is 'u_int', so the field contains a positive integer number, length being a single byte. The corresponding SQL field can be defined as follows: "mtlpl INT(1) UNSIGNED NOT NULL". name=custom_vlen_primitive field_type=43874:255 len=vlen semantics=str Semantics is 'str', so the field contains a string of variable-length. The corresponding SQL field can be defined as follows: "custom_vlen_primitive VARCHAR(255) NOT NULL". Custom-defined primitives: primary key and concluding remarks. Custom-defined primitives can be no problem included as part of the primary key or any other SQL table index. Inclusion is not any different from natively supported primitives. For example a primary key including both 'mtla' and 'mtlpl' primitives: "PRIMARY KEY (..., mtla, mtlpl, ...)". Custom-defined primitives intuitively are not declared as part of any default table version; although they will not fail version checks, it is recommended to set to true the 'sql_optimize_clauses' feature. pmacct-1.7.8/sql/README.GeoIP0000644000175000017500000000343614354105275014441 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'country_ip_src' and 'country_ip_dst', 'pocode_ip_src', 'pocode_ip_dst', 'lat_ip_src', 'lon_ip_src', 'lat_ip_dst' and 'lon_ip_dst' fields. Such fields are being introduced to natively support source/destination GeoIP lookups against a defined database or map. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * country_ip_src field: - "country_ip_src CHAR(2) NOT NULL," to declare the field itself - "PRIMARY KEY (..., country_ip_src, ...)" to put it in the primary key * country_ip_dst field: - "country_ip_dst CHAR(2) NOT NULL," to declare the field itself - "PRIMARY KEY (..., country_ip_dst, ...)" to put it in the primary key * pocode_ip_src field: - "country_ip_src CHAR(12) NOT NULL," to declare the field itself - "PRIMARY KEY (..., pocode_ip_src, ...)" to put it in the primary key * pocode_ip_dst field: - "country_ip_dst CHAR(12) NOT NULL," to declare the field itself - "PRIMARY KEY (..., pocode_ip_dst, ...)" to put it in the primary key * lat_ip_src and lon_ip_src fields: - "lat_ip_src FLOAT NOT NULL," to declare the field itself - "lon_ip_src FLOAT NOT NULL," to declare the field itself - "PRIMARY KEY (..., lat_ip_src, lon_ip_src ...)" to put them in the primary key * lat_ip_dst and lon_ip_dst fields: - "lat_ip_dst FLOAT NOT NULL," to declare the field itself - "lon_ip_dst FLOAT NOT NULL," to declare the field itself - "PRIMARY KEY (..., lat_ip_dst, lon_ip_dst ...)" to put them in the primary key The primitives are not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-db_v9.mysql0000755000175000017500000000162614354105275017421 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v9; create table acct_v9 ( tag INT(4) UNSIGNED NOT NULL, class_id CHAR(16) NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, port_src INT(2) UNSIGNED NOT NULL, port_dst INT(2) UNSIGNED NOT NULL, tcp_flags INT(4) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (tag, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db_v6.mysql0000755000175000017500000000157014354105275017414 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v6; create table acct_v6 ( agent_id INT(4) UNSIGNED NOT NULL, class_id CHAR(16) NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.nat0000644000175000017500000000330314354105275014251 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'post_nat_ip_src', 'post_nat_ip_dst', 'post_nat_port_src', 'post_nat_port_dst'and 'nat_event' fields. Such fields are being introduced to support NAT primitives as implemented, for example, by Cisco NEL implementation. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * post_nat_ip_src field: - "post_nat_ip_src CHAR(15) NOT NULL," to declare the field itself (*) - "PRIMARY KEY (..., post_nat_ip_src, ...)" to put it in the primary key * post_nat_ip_dst field: - "post_nat_ip_dst CHAR(15) NOT NULL," to declare the field itself (*) - "PRIMARY KEY (..., post_nat_ip_dst, ...)" to put it in the primary key * post_nat_port_src field: - "post_nat_port_src INT(2) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., post_nat_port_src, ...)" to put it in the primary key * post_nat_port_dst field: - "post_nat_port_dst INT(2) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., post_nat_port_dst, ...)" to put it in the primary key * nat_event field: - "nat_event INT(1) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., nat_event, ...)" to put it in the primary key * fwd_status field: - "fwd_status INT(1) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., fwd_status, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. (*) Field must be longer for IPv6 addresses. See README.IPv6 pmacct-1.7.8/sql/pmacct-create-db_bgp_v1.mysql0000755000175000017500000000145414354105275020240 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_bgp; create table acct_bgp ( agent_id INT(4) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, peer_as_src INT(4) UNSIGNED NOT NULL, peer_as_dst INT(4) UNSIGNED NOT NULL, peer_ip_src CHAR(45) NOT NULL, peer_ip_dst CHAR(45) NOT NULL, comms CHAR(24) NOT NULL, as_path CHAR(21) NOT NULL, local_pref INT(4) UNSIGNED NOT NULL, med INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, as_src, as_dst, peer_as_src, peer_as_dst, peer_ip_src, peer_ip_dst, comms, as_path, local_pref, med, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v4.sqlite30000755000175000017500000000143214354105275020330 0ustar paolopaoloDROP TABLE IF EXISTS acct_v4; CREATE TABLE acct_v4 ( agent_id INT(8) NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v6.pgsql0000755000175000017500000000350014354105275020072 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v6.pgsql -- -- Tables DROP TABLE IF EXISTS acct_v6; CREATE TABLE acct_v6 ( agent_id BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, as_src BIGINT NOT NULL DEFAULT 0, as_dst BIGINT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v6_pk PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v6 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_bgp_v1.pgsql0000755000175000017500000000211214354105275020713 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_bgp_v1.pgsql -- -- Tables DROP TABLE IF EXISTS acct_bgp; CREATE TABLE acct_bgp ( agent_id BIGINT NOT NULL DEFAULT 0, as_src BIGINT NOT NULL DEFAULT 0, as_dst BIGINT NOT NULL DEFAULT 0, peer_as_src BIGINT NOT NULL DEFAULT 0, peer_as_dst BIGINT NOT NULL DEFAULT 0, peer_ip_src inet NOT NULL DEFAULT '0.0.0.0', peer_ip_dst inet NOT NULL DEFAULT '0.0.0.0', comms CHAR(24) NOT NULL DEFAULT ' ', as_path CHAR(21) NOT NULL DEFAULT ' ', local_pref BIGINT NOT NULL DEFAULT 0, med BIGINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_bgp_pk PRIMARY KEY (agent_id, as_src, as_dst, peer_as_src, peer_as_dst, peer_ip_src, peer_ip_dst, comms, as_path, local_pref, med, stamp_inserted) ); -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_bgp TO pmacct; pmacct-1.7.8/sql/README.etype0000644000175000017500000000121614354105275014616 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'etype' field. Such field is being introduced to support Ethertype field part of the Ethernet header. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * etype field: - "etype CHAR(5) NOT NULL," to declare the field itself - "PRIMARY KEY (..., etype, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-table_v9.pgsql0000755000175000017500000000354114354105275020102 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v9.pgsql -- -- Tables DROP TABLE IF EXISTS acct_v9; CREATE TABLE acct_v9 ( tag BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, as_src BIGINT NOT NULL DEFAULT 0, as_dst BIGINT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, tcp_flags SMALLINT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v9_pk PRIMARY KEY (tag, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v9 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_v3.sqlite30000755000175000017500000000137014354105275020330 0ustar paolopaoloDROP TABLE IF EXISTS acct_v3; CREATE TABLE acct_v3 ( agent_id INT(8) NOT NULL DEFAULT 0, mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.tag20000644000175000017500000000152114354105275014324 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'tag2' field. Such field is being introduced to better support traffic matrix scenarios, where it can be handy to have a tag to represent "qualities" of the source (say, tag) and an additional one to represent "qualities" of the destination (say, tag2). But of course this is only an example. The guidelines below (typically in MySQL format) are to add such primitive to the SQL schema: * tag2 field: - "tag2 INT(4) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., tag2, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-db_v3.mysql0000755000175000017500000000132314354105275017405 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v3; create table acct_v3 ( agent_id INT(4) UNSIGNED NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v7.sqlite30000755000175000017500000000172514354105275020340 0ustar paolopaoloDROP TABLE IF EXISTS acct_v7; CREATE TABLE acct_v7 ( agent_id INT(8) NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, as_src INT(8) NOT NULL DEFAULT 0, as_dst INT(8) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, tcp_flags INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.mpls0000644000175000017500000000325014354105275014443 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'mpls_vpn_rd' field. Such field is being introduced to support BGP/MPLS VPN Route Distinguisher (RD) field. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * mpls_vpn_rd field: - "mpls_vpn_rd CHAR(18) NOT NULL," to declare the field itself - "PRIMARY KEY (..., mpls_vpn_rd, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. The 'mpls_label_top', 'mpls_label_bottom' and 'mpls_label_stack' fields. These fields are being introduced to support traffic export MPLS-enabled core interfaces. 'mpls_label_top' can be useful to get insight into BGP next-hop; 'mpls_label_bottom' can be useful to map traffic to a specific L2/L3 MPLS VPN; 'mpls_label_stack' allows to get full insight in the MPLS label stack and its depth; the guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * mpls_label_top field: - "mpls_label_top INT(4) UNSIGNED NOT NULL, " to declare the field itself - "PRIMARY KEY (..., mpls_label_top, ...)" to put it in the primary key * mpls_label_bottom field: - "mpls_label_bottom INT(4) UNSIGNED NOT NULL, " to declare the field itself - "PRIMARY KEY (..., mpls_label_bottom, ...)" to put it in the primary key * mpls_label_stack field: - "mpls_label_stack VARCHAR(255) NOT NULL," to declare the field itself - "PRIMARY KEY (..., mpls_label_stack, ...)" to put it in the primary key pmacct-1.7.8/sql/README.cos0000644000175000017500000000116714354105275014261 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'cos' field. Such field is being introduced to support 802.1p priority bits. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * cos field: - "cos INT(1) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., cos, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-create-table_v7_v8.pgsql0000755000175000017500000000355614354105275020523 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v7_v8.pgsql -- -- Tables DROP TABLE IF EXISTS acct_v7; CREATE TABLE acct_v7 ( agent_id BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, as_src BIGINT NOT NULL DEFAULT 0, as_dst BIGINT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, tcp_flags SMALLINT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v7_pk PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v7 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-db_v2.mysql0000755000175000017500000000125314354105275017406 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v2; create table acct_v2 ( agent_id INT(4) UNSIGNED NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, src_port INT(2) UNSIGNED NOT NULL, dst_port INT(2) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, mac_src, mac_dst, vlan, ip_src, ip_dst, src_port, dst_port, ip_proto, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-db_v8.mysql0000755000175000017500000000164014354105275017414 0ustar paolopaolodrop database if exists pmacct; create database pmacct; use pmacct; drop table if exists acct_v8; create table acct_v8 ( agent_id INT(4) UNSIGNED NOT NULL, class_id CHAR(16) NOT NULL, mac_src CHAR(17) NOT NULL, mac_dst CHAR(17) NOT NULL, vlan INT(2) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, ip_src CHAR(45) NOT NULL, ip_dst CHAR(45) NOT NULL, port_src INT(2) UNSIGNED NOT NULL, port_dst INT(2) UNSIGNED NOT NULL, tcp_flags INT(4) UNSIGNED NOT NULL, ip_proto CHAR(6) NOT NULL, tos INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, flows INT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/README.timestamp0000644000175000017500000000474114354105275015501 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'timestamp_start', 'timestamp_end', 'timestamp_arrival', 'timestamp_min' and 'timestamp_max' fields. 'timestamp_start' and 'timestamp_end' fields are being introduced to support logging of traffic and events via pmacct (mainly NetFlow/IPFIX feature). 'timestamp_arrival' records libpcap packet timestamp and sFlow/NetFlow/IPFIX packet arrival time at the collector; 'timestamp_min' and 'timestamp_max' fields support stitching of flows (or samples if sfacctd or packets if pmacctd), for more info see nfacctd_stitching feature in CONFIG-KEYS. Timestamps resolution is up to the msec level and for this reason time residual fields are optionally introduced ie. 'timestamp_start_residual', 'timestamp_end_residual': this is because support for resolutions beyond the secs level is something not popular among the supported RDBMS, ie. only recent versions of MySQL >= 5.6.4 appear to support it, hence the choice to go for two separate fields. Timestamp resolution can be cut to secs level by setting timestamps_secs config directive to 'true': in this case the residual fields can be omitted in the table schema. The guidelines below (typically n MySQL format) are to add all the described primitives to the SQL schema: * timestamp_start and timestamp_start_residual fields: - To declare the fields: - "timestamp_start DATETIME NOT NULL," - "timestamp_start_residual INT UNSIGNED NOT NULL," - To add them to the primary key: - "PRIMARY KEY (..., timestamp_start, timestamp_start_residual, ...)" * timestamp_end and timestamp_end_residual fields: - To declare the fields: - "timestamp_end DATETIME NOT NULL," - "timestamp_end_residual INT UNSIGNED NOT NULL," - To add them to the primary key: - "PRIMARY KEY (..., timestamp_end, timestamp_end_residual, ...)" * timestamp_arrival and timestamp_arrival_residual fields: - To declare the fields: - "timestamp_arrival DATETIME NOT NULL," - "timestamp_arrival_residual INT UNSIGNED NOT NULL," - To add them to the primary key: - "PRIMARY KEY (..., timestamp_arrival, timestamp_arrival_residual, ...)" This works similarly for 'timestamp_min', 'timestamp_min_residual', 'timestamp_max' and 'timestamp_max_residual'. The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/sql/pmacct-grant-db.mysql0000755000175000017500000000016614354105275016651 0ustar paolopaoloCREATE USER 'pmacct'@'localhost' IDENTIFIED BY 'arealsmartpwd'; GRANT ALL PRIVILEGES ON pmacct.* TO pmacct@localhost; pmacct-1.7.8/sql/pmacct-create-table_v1.sqlite30000755000175000017500000000115414354105275020326 0ustar paolopaoloDROP TABLE IF EXISTS acct; CREATE TABLE acct ( mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', src_port INT(4) NOT NULL DEFAULT 0, dst_port INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (mac_src, mac_dst, ip_src, ip_dst, src_port, dst_port, ip_proto, stamp_inserted) ); pmacct-1.7.8/sql/README.sqlite30000644000175000017500000002633714354105275015067 0ustar paolopaoloSee how to configure and compile pmacct for SQLite use in the "Configuring pmacct for compilation and installing" chapter of QUICKSTART. To create the database and the table you have to execute the following scripts. Remember that SQLite - unlike MySQL and PostgreSQL - does not endorse concepts of authentication (username and password couple) and permissions which are embedded into the filesystem instead. The database filename '/tmp/pmacct.db' is just a trivial example: you are free to build the database wherever fits better for you on the system (e.g., to follow a partitioning scheme, impose specific permissions, etc.). - To create v1 tables: * sqlite3 /tmp/pmacct.db < pmacct-create-table.sqlite3 - To use v1 tables: * data will be available in 'acct' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. Similarly, v2 to v9 tables: - To create v2 tables: * sqlite3 /tmp/pmacct.db < pmacct-create-table_v2.sqlite3 - To use v2 tables: * data will be available in 'acct_v2' table of 'pmacct' DB. * Add 'sql_table_version: 2' line to your configuration. [ ... ] - To create v9 tables: * sqlite3 /tmp/pmacct.db < pmacct-create-table_v9.sqlite3 - To use v9 tables: * data will be available in 'acct_v9' table of 'pmacct' DB. * Add 'sql_table_version: 7' line to your configuration. Similarly, BGP tables: - To create BGP v1 tables: * sqlite3 /tmp/pmacct.db < pmacct-create-table_bgp_v1.sqlite3 - To use BGP v1 tables: * data will be available in 'acct_bgp' table of 'pmacct' DB. * Add 'sql_table_version: 1' line to your configuration. * Add 'sql_table_type: bgp' line to your configuration. - To understand difference between the various table versions: * Do you need any of the BGP primitives ? Then look the next section. * Do you need tags for traffic tagging ? Then you have to use v9. * Do you need TCP flags ? Then you have to use v7. * Do you need both IP addresses and AS numbers in the same table ? Then you have to use v6. * Do you need packet classification ? Then you have to use v5. * Do you need flows (other than packets) accounting ? Then you have to use v4. * Do you need ToS/DSCP field (QoS) accounting ? Then you have to use v3. * Do you need VLAN traffic accounting ? Then you have to use v2. * If all of the above points sound useless, then use v1. * v8 changes field names so to bring all supported databases to the same naming convention. - To understand difference between the various BGP table versions: * Only BGP table v1 is currently available. - Aggregation primitives to SQL schema mapping. Although default schemas come all with "NOT NULL", this is optional and depending on the scenario: for example, if mixed L2 (containing L2 only info) and L3 (containing L2 and L3 info) flows are collected, maybe L3-related fields like src_host or dst_host are best defined without the "NOT NULL" constraint. Aggregation primitive => SQL table field * tag => agent_id (INT(8) NOT NULL DEFAULT 0) - or tag => tag (INT(8) NOT NULL DEFAULT 0, if sql_table_version >= 9) * tag2 => tag2 (INT(8) NOT NULL DEFAULT 0, see README.tag2) * label => label (VARCHAR(255) NOT NULL DEFAULT ' ', see README.label) * src_as => as_src (INT(8) NOT NULL DEFAULT 0) - src_as => ip_src (INT(8) NOT NULL DEFAULT 0, if sql_table_version < 6) * dst_as => as_dst (INT(8) NOT NULL DEFAULT 0) - dst_as => ip_dst (INT(8) NOT NULL DEFAULT 0, if sql_table_version < 6) * peer_src_as => peer_as_src (INT(8) NOT NULL DEFAULT 0) * peer_dst_as => peer_as_dst (INT(8) NOT NULL DEFAULT 0) * peer_src_ip => peer_ip_src (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * peer_dst_ip => peer_ip_dst (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * mpls_vpn_rd => mpls_vpn_rd (CHAR(18) NOT NULL DEFAULT ' ') * std_comm => comms (CHAR(24) NOT NULL DEFAULT ' ') * ext_comm => ecomms (CHAR(24) NOT NULL DEFAULT ' ') * lrg_comm => lcomms (CHAR(24) NOT NULL DEFAULT ' ') * as_path => as_path (CHAR(21) NOT NULL DEFAULT ' ') * local_pref => local_pref (INT(8) NOT NULL DEFAULT 0) * med => med (INT(8) NOT NULL DEFAULT 0) * dst_roa => roa_dst (CHAR(1) NOT NULL DEFAULT ' ') * src_std_comm => comms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_ext_comm => ecomms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_lrg_comm => lcomms_src (CHAR(24) NOT NULL DEFAULT ' ') * src_as_path => as_path_src (CHAR(21) NOT NULL DEFAULT ' ') * src_local_pref => local_pref_src (INT(8) NOT NULL DEFAULT 0) * src_med => med_src (INT(8) NOT NULL DEFAULT 0) * src_roa => roa_src (CHAR(1) NOT NULL DEFAULT ' ') * in_iface => iface_in (INT(8) NOT NULL DEFAULT 0, see README.iface) * out_iface => iface_out (INT(8) NOT NULL DEFAULT 0, see README.iface) * src_mask => mask_src (INT(2) NOT NULL DEFAULT 0, see README.mask) * dst_mask => mask_dst (INT(2) NOT NULL DEFAULT 0, see README.mask) * cos => cos (INT(2) NOT NULL DEFAULT 0, see README.cos) * etype => etype (CHAR(5) NOT NULL DEFAULT ' ', see README.etype) * src_host_country => country_ip_src (CHAR(2) NOT NULL DEFAULT '--', see README.GeoIP) * dst_host_country => country_ip_dst (CHAR(2) NOT NULL DEFAULT '--', see README.GeoIP) * src_host_pocode => pocode_ip_src (CHAR(12) NOT NULL DEFAULT ' ', see README.GeoIP) * dst_host_pocode => pocode_ip_dst (CHAR(12) NOT NULL DEFAULT ' ', see README.GeoIP) * src_host_coords => lat_ip_src (REAL NOT NULL DEFAULT 0, see README.GeoIP) * src_host_coords => lon_ip_src (REAL NOT NULL DEFAULT 0, see README.GeoIP) * dst_host_coords => lat_ip_dst (REAL NOT NULL DEFAULT 0, see README.GeoIP) * dst_host_coords => lon_ip_dst (REAL NOT NULL DEFAULT 0, see README.GeoIP) * sampling_rate => sampling_rate (INT(8) NOT NULL DEFAULT 0, see README.sampling) * sampling_direction => sampling_direction (CHAR(1) NOT NULL DEFAULT ' ', see README.sampling) * class => class_id (CHAR(16) NOT NOT NULL DEFAULT ' ') * src_mac => mac_src (CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0') * dst_mac => mac_dst (CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0') * vlan => vlan (INT(4) NOT NULL DEFAULT 0) * in_vlan => vlan_in (INT(4) NOT NULL DEFAULT 0) * out_vlan => vlan_out (INT(4) NOT NULL DEFAULT 0) * src_as => as_src (INT(8) NOT NULL DEFAULT 0) * dst_as => as_dst (INT(8) NOT NULL DEFAULT 0) * src_host => ip_src (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * src_net => net_src (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * dst_net => net_dst (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * src_port => src_port (INT(4) NOT NULL DEFAULT 0) - or src_port => port_src (INT(4) NOT NULL DEFAULT 0, if sql_table_version >= 8 or sql_table_type == bgp) * dst_port => dst_port (INT(4) NOT NULL DEFAULT 0) - or dst_port => port_dst (INT(4) NOT NULL DEFAULT 0, if sql_table_version >= 8 or sql_table_type == bgp * tcpflags => tcp_flags (INT(2) NOT NULL DEFAULT 0) * proto => ip_proto (CHAR(6) NOT NULL DEFAULT ' ') - or (INT(2) DEFAULT 0, if sql_num_protos: true) * tos => tos (INT(4) NOT NULL DEFAULT 0) * post_nat_src_host => post_nat_ip_src (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * post_nat_dst_host => post_nat_ip_dst (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * post_nat_src_port => post_nat_port_src (INT(4) NOT NULL DEFAULT 0) * post_nat_dst_port => post_nat_port_dst (INT(4) NOT NULL DEFAULT 0) * nat_event => nat_event (INT(2) NOT NULL DEFAULT 0) * fwd_status => fwd_status (INT(2) NOT NULL DEFAULT 0) - or (VARCHAR(50) NOT NULL DEFAULT ' ', if fwd_status_encode_as_string: true) * mpls_label_top => mpls_label_top (INT(4) NOT NULL DEFAULT 0) * mpls_label_bottom => mpls_label_bottom (INT(4) NOT NULL DEFAULT 0) * mpls_label_stack => mpls_label_stack (VARCHAR(255) NOT NULL DEFAULT ' ') * tunnel_src_mac => tunnel_mac_src (CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0') * tunnel_dst_mac => tunnel_mac_dst (CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0') * tunnel_src_host => tunnel_ip_src (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * tunnel_dst_host => tunnel_ip_dst (CHAR(45) NOT NULL DEFAULT '0.0.0.0') - or (INT(32) DEFAULT 0, if sql_num_hosts: true) * tunnel_proto => tunnel_ip_proto (CHAR(6) NOT NULL DEFAULT ' ') - or (INT(2) DEFAULT 0, if sql_num_protos: true) * tunnel_tos => tunnel_tos (INT(4) NOT NULL DEFAULT 0) * tunnel_src_port => tunnel_port_src (INT(4) NOT NULL DEFAULT 0) * tunnel_dst_port => tunnel_port_dst (INT(4) NOT NULL DEFAULT 0) * tunnel_tcpflags => tunnel_tcp_flags (INT(2) NOT NULL DEFAULT 0) * timestamp_start => timestamp_start, timestamp_start_residual: - timestamp_start DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', see README.timestamp) - timestamp_start_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_end => timestamp_end, timestamp_end_residual: - timestamp_end DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', see README.timestamp) - timestamp_end_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_arrival => timestamp_arrival, timestamp_arrival_residual: - timestamp_arrival DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', see README.timestamp) - timestamp_arrival_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_min => timestamp_min, timestamp_min_residual: - timestamp_min DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', see README.timestamp) - timestamp_min_residual INT NOT NULL DEFAULT 0, see README.timestamp) * timestamp_max => timestamp_max, timestamp_max_residual: - timestamp_max DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', see README.timestamp) - timestamp_max_residual INT NOT NULL DEFAULT 0, see README.timestamp) * export_proto_seqno => export_proto_seqno (INT(4) NOT NULL DEFAULT 0, see README.export_proto) * export_proto_version => export_proto_version (INT(2) NOT NULL DEFAULT 0, see README.export_proto) * export_proto_sysid => export_proto_sysid (INT(4) NOT NULL DEFAULT 0, see README.export_proto) - 'packets' and 'bytes' counters need to be defined as part of the SQL schema whenever traffic flows are being accounted for; they are not required, and are zeroed, if accounting for events, ie. using Cisco NEL; 'stamp_inserted' and 'stamp_updated' time references are mandatory only if temporal aggregation (sql_history) is enabled: * packets (INT(8) NOT NULL DEFAULT 0) * bytes (INT(8) NOT NULL DEFAULT 0) * stamp_inserted (DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00') - or (stamp_inserted INT(8) NOT NULL DEFAULT 0, if timestamps_since_epoch: true) * stamp_updated (DATETIME) - or (stamp_updated INT(8) DEFAULT 0, if timestamps_since_epoch: true) - For custom-defined primitives refer to the README.custom_primitives doc. NOTE: mind to specify EVERYTIME which SQL table version you intend to adhere to by using the following config directives: * sql_table_version: [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ] * sql_table_type: [ bgp ] NOTE: specifying a non-documented SQL table profile will result in an non-determined behaviour. Unless this will create crashes to the application, such situations will not be supported. pmacct-1.7.8/sql/pmacct-create-table_v5.pgsql0000755000175000017500000000713214354105275020076 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table_v5.pgsql -- -- Tables DROP TABLE IF EXISTS acct_uni_v5; CREATE TABLE acct_uni_v5 ( agent_id BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_uni_v5_pk PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_v5; CREATE TABLE acct_v5 ( agent_id BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_v5_pk PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS acct_as_v5; CREATE TABLE acct_as_v5 ( agent_id BIGINT NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT NOT NULL DEFAULT 0, ip_src INT NOT NULL DEFAULT 0, ip_dst INT NOT NULL DEFAULT 0, port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, tos INT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00', stamp_updated timestamp without time zone, CONSTRAINT acct_as_v5_pk PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_uni_v5 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_v5 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_as_v5 TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/pmacct-create-table_v8.sqlite30000755000175000017500000000172514354105275020341 0ustar paolopaoloDROP TABLE IF EXISTS acct_v8; CREATE TABLE acct_v8 ( agent_id INT(8) NOT NULL DEFAULT 0, class_id CHAR(16) NOT NULL DEFAULT ' ', mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', vlan INT(4) NOT NULL DEFAULT 0, as_src INT(8) NOT NULL DEFAULT 0, as_dst INT(8) NOT NULL DEFAULT 0, ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT(4) NOT NULL DEFAULT 0, port_dst INT(4) NOT NULL DEFAULT 0, tcp_flags INT(4) NOT NULL DEFAULT 0, ip_proto CHAR(6) NOT NULL DEFAULT 0, tos INT(4) NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, flows INT NOT NULL DEFAULT 0, stamp_inserted DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', stamp_updated DATETIME, PRIMARY KEY (agent_id, class_id, mac_src, mac_dst, vlan, as_src, as_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, tos, stamp_inserted) ); pmacct-1.7.8/sql/pmacct-create-table_v1.pgsql0000755000175000017500000000565314354105275020100 0ustar paolopaolo-- -- # su - postgres (or whatever your database runs as ... usually postgres) -- $ psql -d pmacct -f pmacct-create-table.pgsql -- -- Tables DROP TABLE IF EXISTS acct_uni; CREATE TABLE acct_uni ( mac_src CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst CHAR(17) NOT NULL DEFAULT '0:0:0:0:0:0', ip_src CHAR(45) NOT NULL DEFAULT '0.0.0.0', ip_dst CHAR(45) NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP(0), stamp_updated timestamp without time zone, CONSTRAINT acct_uni_pk PRIMARY KEY (mac_src, mac_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS acct; CREATE TABLE acct ( mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', ip_src inet NOT NULL DEFAULT '0.0.0.0', ip_dst inet NOT NULL DEFAULT '0.0.0.0', port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP(0), stamp_updated timestamp without time zone, CONSTRAINT acct_pk PRIMARY KEY (mac_src, mac_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS acct_as; CREATE TABLE acct_as ( mac_src macaddr NOT NULL DEFAULT '0:0:0:0:0:0', mac_dst macaddr NOT NULL DEFAULT '0:0:0:0:0:0', ip_src INT NOT NULL DEFAULT 0, ip_dst INT NOT NULL DEFAULT 0, port_src INT NOT NULL DEFAULT 0, port_dst INT NOT NULL DEFAULT 0, ip_proto SMALLINT NOT NULL DEFAULT 0, packets INT NOT NULL, bytes BIGINT NOT NULL, stamp_inserted timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP(0), stamp_updated timestamp without time zone, CONSTRAINT acct_as_pk PRIMARY KEY (mac_src, mac_dst, ip_src, ip_dst, port_src, port_dst, ip_proto, stamp_inserted) ); DROP TABLE IF EXISTS proto; CREATE TABLE proto ( num SMALLINT NOT NULL, description CHAR(20), CONSTRAINT proto_pk PRIMARY KEY (num) ); COPY proto FROM stdin USING DELIMITERS ','; 0,ip 1,icmp 2,igmp 3,ggp 4,ipencap 5,st 6,tcp 8,egp 9,igp 17,udp 18,mux 27,rdp 29,iso-tp4 30,netblt 37,ddp 39,idpr-cmtp 41,ipv6 43,ipv6-route 44,ipv6-frag 46,rsvp 47,gre 50,ipv6-crypt 51,ipv6-auth 55,mobile 56,tlsp 58,ipv6-icmp 59,ipv6-nonxt 60,ipv6-opts 80,iso-ip 83,vines 88,eigrp 89,ospf 90,sprite-rpc 93,ax-25 94,ipip 98,encap 102,pnni 108,IPcomp 111,ipx-in-ip 112,vrrp 115,l2tp 124,isis 132,sctp 133,fc \. -- Perms GRANT SELECT, INSERT, UPDATE, DELETE ON acct_uni TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON acct_as TO pmacct; GRANT SELECT, INSERT, UPDATE, DELETE ON proto TO pmacct; pmacct-1.7.8/sql/README.mask0000644000175000017500000000200114354105275014414 0ustar paolopaoloThis document doesn't replace documentation relevant to the database software you are using, ie. README.mysql, README.pgsql or README.sqlite3. The 'mask_src' and 'mask_dst' fields. Such fields are being introduced to support source and destination IP prefix masks. Values are grasped as configured in [nf|sf|pm|u]acctd_net directive: NetFlow/sFlow protocols, BGP, Network files (networks_file) or static (networks_mask) being valid data sources. The guidelines below (typically in MySQL format) are to add such primitives to the SQL schema: * mask_src field: - "mask_src INT(1) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., mask_src, ...)" to put it in the primary key * mask_dst field: - "mask_dst INT(1) UNSIGNED NOT NULL," to declare the field itself - "PRIMARY KEY (..., mask_dst, ...)" to put it in the primary key The primitive is not declared as part of any default table version; yet will not fail version checks which are enabled when 'sql_optimize_clauses' feature is disabled. pmacct-1.7.8/examples/0000755000175000017500000000000014354105275013630 5ustar paolopaolopmacct-1.7.8/examples/allow.lst.example0000644000175000017500000000042014354105275017120 0ustar paolopaolo! ! Sample allow file; enabled via 'nfacctd_allow_file' and equivalent keys. ! ! * Allow individual IPv4/IPv6 addresses ! 192.168.0.1 ! 192.168.1.254 ! ! * Allow IPv4/IPv6 prefixes ! 192.168.2.0/24 ! ! * Allow all ! 0.0.0.0/0 ! ! * Reject all with an empty allow file ! pmacct-1.7.8/examples/pmacctd-sqlite3.conf.example0000644000175000017500000000103614354105275021126 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! libpcap daemon configs ! pcap_interface: eth0 ! ! Plugins definitions ! plugins: sqlite3[foo] ! ! 'foo' plugin configuration ! aggregate[foo]: src_host, dst_host sql_db[foo]: /path/to/pmacct.db sql_table_version[foo]: 1 ! sql_table_version[foo]: 2 ! sql_table_version[foo]: 3 sql_refresh_time[foo]: 60 sql_history[foo]: 1m sql_history_roundoff[foo]: m pmacct-1.7.8/examples/sampling.map.example0000644000175000017500000000255414354105275017601 0ustar paolopaolo! ! sampling_map: given at least a router IP, returns a sampling rate ! ! File syntax is key-based. Position of keys inside the same row (rule) is not ! relevant; Spaces are not allowed (ie. 'id = 1' is not valid). The first full ! match wins (like in firewall rules). Negative values mean negations (ie. match ! data NOT entering interface 2: 'in=-2'); 'id' and 'ip' keys don't support ! negative values. ! ! nfacctd: valid keys: id, ip, in, out ! ! sfacctd: valid keys: id, ip, in, out ! ! list of currently supported keys follows: ! ! 'id' SET: sampling rate assigned to a matching packet, flow ! or sample. The result is used to renormalize packet and ! bytes count if [nf|sf]acctd_renormalize configuration ! directive is set to true. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN).0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' MATCH: Input interface ! 'out' MATCH: Output interface ! ! ! Examples: ! id=1024 ip=192.168.1.1 id=2048 ip=192.168.2.1 in=5 id=4096 ip=192.168.3.1 out=3 pmacct-1.7.8/examples/bgp_agent.map.example0000644000175000017500000000512714354105275017714 0ustar paolopaolo! ! bgp_agent_map: NetFlow/sFlow agent to BGP peer map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! list of currently supported keys follow: ! ! 'bgp_ip' SET: IPv4/IPv6 session address or Router ID of the ! BGP peer. ! 'bmp_ip' An alias for 'bgp_ip' for mapping agents to the IPv4/ ! IPv6 session address of BMP peers. ! 'bgp_port' SET: TCP port used by the BGP peer to establish the ! session, useful in NAT traversal scenarios. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' MATCH: Input interface. In NFv9/IPFIX this is compared ! against IE #10 and, if not existing, against IE #252. ! 'out' MATCH: Output interface. In NFv9/IPFIX this is compared ! against IE #14 and, if not existing, against IE #253. ! 'filter' MATCH: incoming data is compared against the supplied ! filter expression (expected in libpcap syntax); the ! filter needs to be enclosed in quotes ('). In this map ! this is meant to discriminate among IPv4 ('ip', 'vlan ! and ip') and IPv6 ('ip6', 'vlan and ip6') traffic. ! ! Examples: ! bgp_ip=192.168.1.1 ip=192.168.100.1 ! ! The following maps something which any Netflow/sFlow agent to the specified ! BGP peer. This syntax applies also to non-telemetry daemons, ie. pmacctd and ! uacctd. ! ! bgp_ip=10.0.0.1 ip=0.0.0.0/0 ! ! The following maps flows ingressing a specific interface of the NetFlow/sFlow ! agent to the specified BGP peer. This may be relevant to MPLS VPN scenarios. ! ! bgp_ip=192.168.1.1 ip=192.168.200.1 in=100 ! ! In scenarios where there are distinct v4 and v6 BGP sessions with the same ! peer (by design or due to distinct BGP agents for v4 and v6), traffic can ! be directed onto the right session with a filter. pmacct needs somehow to ! distinguish the sessions to make the correlation properly work: if the IP ! address of the BGP sessions is the same, ie. pmacct is co-located with the ! BGP agent, the peers will need to have a different Router ID configured: ! ! bgp_ip=10.10.0.1 ip=0.0.0.0/0 filter='ip or (vlan and ip)' ! bgp_ip=fd00::1:8:0 ip=0.0.0.0/0 filter='ip6 or (vlan and ip6)' pmacct-1.7.8/examples/bgp_md5.lst.example0000644000175000017500000000024314354105275017322 0ustar paolopaolo! ! Sample BGP MD5 map; enabled by 'bgp_daemon_md5_file' key. ! ! Format supported: , ! 192.168.1.1, arealsmartpwd 192.168.1.2, TestTest ! ... pmacct-1.7.8/examples/tee_receivers.lst.example0000644000175000017500000000423314354105275020634 0ustar paolopaolo! ! tee_receivers: Tee receivers map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! nfacctd, sfacctd: valid keys: id, ip, tag, balance-alg, src_port; mandatory ! keys: id, ip. ! ! list of currently supported keys follows: ! ! 'id' SET: Unique pool ID, must be greater than zero. ! 'ip' MATCH: Comma-separated list of receivers in : ! format. Host can be a FQDN or an IPv4/IPv6 ! address. ! 'tag' MATCH: Comma-separated list of tags for filtering ! purposes; tags are previously applied to datagrams ! via a pre_tag_map map and then matched here with a ! tee_receivers map. ! 'balance-alg' SET: Enables balancing of datagrams to receivers ! within the pool. Supported algorithms: 'rr' round- ! robin, 'hash-tag' hashing of tag (pre_tag_map) ! against the number of receivers in pool, 'hash-agent' ! hashing of the exporter/agent IP address against ! the number of receivers in pool, 'hash-crc32' same ! as hash-agent but uses crc32 as hash function. ! 'src_port' SET: When in non-transparent replication mode, use ! the specified UDP port to send data to receiver(s) ! 'kafka_broker' SET: Defines the Kafka broker host to emit to. It ! expects a string like 'localhost:9092'. ! 'kafka_topic' SET: Defines the Kafka topic to emit to. Mandatory ! to specify when a kafka_broker is defined. ! 'zmq_address' SET: Defines the ZeroMQ queue address to bind to. ! It expects a string like '127.0.0.1:50000'. ! ! ! Examples: ! ! Just replicate to one or multiple collectors: ! id=1 ip=192.168.1.1:2100 id=2 ip=192.168.2.1:2100,192.168.2.2:2100 id=3 ip=[::1]:2100 ! ! ! Replicate with selective filtering. Replicate datagrams tagged as 100 and ! 150 to pool #1; replicate datagrams tagged as 105 and within the tag range ! 110-120 to pool #2. Replicate all datagrams but those tagged as 150 to pool ! #3. ! id=1 ip=192.168.1.1:2100 tag=100,150 id=2 ip=192.168.2.1:2100,192.168.2.2:2100 tag=105,110-120 id=3 ip=192.168.3.1:2100 tag=-150 ! ! ! Replicate with balancing. Round-robin enabled in pool#1 ! id=1 ip=192.168.1.1:2100,192.168.1.2:2100 balance-alg=rr pmacct-1.7.8/examples/systemd/0000755000175000017500000000000014354105275015320 5ustar paolopaolopmacct-1.7.8/examples/systemd/systemd_service_file.md0000644000175000017500000000261314354105275022053 0ustar paolopaoloSystemd-Service-File -------------------------- login to your pmacct collector server get root (sudo -i) vim /etc/systemd/system/nfacctd-bgp01.service [Unit] Description=Netflow-BGP-Collector After=network-online.target Wants=network-online.target [Service] Environment=LD_LIBRARY_PATH=/usr/local/lib Type=simple ExecStart=/usr/local/sbin/nfacctd -f /etc/pmacct/nfacctd-bgp01.conf KillSignal=SIGTERM TimeoutStopSec=30 KillMode=control-group PrivateTmp=true RemainAfterExit=no Restart=on-failure RestartSec=30s [Install] WantedBy=multi-user.target Config-File -------------------------- Set on the pmacct-configfile (a.e. on /etc/pmacct/nfacctd-bgp01.conf) the config-key daemonize to false: vim /etc/pmacct/nfacctd-bgp01.conf ... daemonize: false ... Systemd-Commands -------------------------- `systemctl daemon-reload` `systemctl enable nfacctd-bgp01` it will return something like: > Created symlink > /etc/systemd/system/multi-user.target.wants/nfacctd-bgp01.service -> > /etc/systemd/system/nfacctd-bgp01.service. some other usefull systemd commands: `systemctl status nfacctd-bgp01` `systemctl start nfacctd-bgp01` `systemctl stop nfacctd-bgp01` checkout the logmessages of your systemd service: `journalctl -fu nfacctd-bgp01` pmacct-1.7.8/examples/probe_sflow.conf.example0000644000175000017500000000046214354105275020454 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys ! supported by 'nfacctd' and 'pmacctd' ? ! ! debug: true daemonize: true pcap_interface: eth0 plugins: sfprobe sfprobe_agentsubid: 1402 sfprobe_receiver: 192.168.1.1:6343 sampling_rate: 20 pmacct-1.7.8/examples/amqp/0000755000175000017500000000000014354105275014566 5ustar paolopaolopmacct-1.7.8/examples/amqp/amqp_receiver.py0000755000175000017500000002041214354105275017764 0ustar paolopaolo#!/usr/bin/env python # # Pika is a pure-Python implementation of the AMQP 0-9-1 protocol and # is available at: # https://pypi.python.org/pypi/pika # http://www.rabbitmq.com/tutorials/tutorial-one-python.html # # UltraJSON, an ultra fast JSON encoder and decoder, is available at: # https://pypi.python.org/pypi/ujson # # The Apache Avro Python module is available at: # https://avro.apache.org/docs/1.8.1/gettingstartedpython.html # # Binding to the routing key specified by amqp_routing_key (by default 'acct') # allows to receive messages published by an 'amqp' plugin, in JSON format. # Similarly for BGP daemon bgp_*_routing_key and BMP daemon bmp_*_routing_key. # # Binding to the reserved exchange 'amq.rabbitmq.trace' and to routing keys # 'publish.pmacct' or 'deliver.' allows to receive a copy of the # messages that published via a specific exchange or delivered to a specific # queue. RabbitMQ Firehose Tracer feature should be enabled first with the # following command: # # 'rabbitmqctl trace_on' enables RabbitMQ Firehose tracer # 'rabbitmqctl list_queues' lists declared queues # # Two pipelines are supported in this script: # * RabbitMQ -> REST API # * RabbitMQ -> stdout # # Two data encoding formats are supported in this script: # * JSON # * Apache Avro import sys, os, getopt, pika, StringIO, time import ujson as json try: import avro.io import avro.schema import avro.datafile avro_available = True except ImportError: avro_available = False avro_schema = None http_url_post = None print_stdout = 0 print_stdout_num = 0 print_stdout_max = 0 convert_to_json_array = 0 stats_interval = 0 time_count = 0 elem_count = 0 def usage(tool): print "" print "Usage: %s [Args]" % tool print "" print "Mandatory Args:" print " -e, --exchange".ljust(25) + "Define the exchange to bind to" print " -k, --routing_key".ljust(25) + "Define the routing key to use" print " -q, --queue".ljust(25) + "Specify the queue to declare" print "" print "Optional Args:" print " -h, --help".ljust(25) + "Print this help" print " -H, --host".ljust(25) + "Define RabbitMQ broker host [default: 'localhost']" print " -p, --print".ljust(25) + "Print data to stdout" print " -n, --num".ljust(25) + "Number of rows to print to stdout [default: 0, ie. forever]" print " -u, --url".ljust(25) + "Define a URL to HTTP POST data to" print " -a, --to-json-array".ljust(25) + "Convert list of newline-separated JSON objects in a JSON array" print " -s, --stats-interval".ljust(25) + "Define a time interval, in secs, to get statistics to stdout" print " -P, --pidfile".ljust(25) + "Set a pidfile to record active processes PID" if avro_available: print " -d, --decode-with-avro".ljust(25) + "Define the file with the " \ "schema to use for decoding Avro messages" def post_to_url(http_req, value): try: urllib2.urlopen(http_req, value) except urllib2.HTTPError, err: print "WARN: urlopen() returned HTTP error code:", err.code sys.stdout.flush() except urllib2.URLError, err: print "WARN: urlopen() returned URL error reason:", err.reason sys.stdout.flush() def callback(ch, method, properties, body): global avro_schema global http_url_post global print_stdout global print_stdout_num global print_stdout_max global convert_to_json_array global stats_interval global time_count global elem_count if stats_interval: time_now = int(time.time()) if avro_schema: inputio = StringIO.StringIO(body) decoder = avro.io.BinaryDecoder(inputio) datum_reader = avro.io.DatumReader(avro_schema) avro_data = [] while inputio.tell() < len(inputio.getvalue()): x = datum_reader.read(decoder) avro_data.append(str(x)) # # XXX: data enrichments, manipulations, correlations, filtering etc. go here # if stats_interval: elem_count += len(avro_data) if print_stdout: print " [x] Received %r" % (",".join(avro_data),) sys.stdout.flush() print_stdout_num += 1 if (print_stdout_max == print_stdout_num): sys.exit(0) if http_url_post: http_req = urllib2.Request(http_url_post) http_req.add_header('Content-Type', 'application/json') post_to_url(http_req, ("\n".join(avro_data))) else: value = body try: jsonObj = json.loads(value) except ValueError: print("ERROR: json.loads: '%s'. Skipping." % value) return # # XXX: data enrichments, manipulations, correlations, filtering etc. go here # if stats_interval: elem_count += value.count('\n') elem_count += 1 if convert_to_json_array: value = "[" + value + "]" value = value.replace('\n', ',\n') value = value.replace(',\n]', ']') if print_stdout: print " [x] Received %r" % (value,) sys.stdout.flush() print_stdout_num += 1 if (print_stdout_max == print_stdout_num): sys.exit(0) if http_url_post: http_req = urllib2.Request(http_url_post) http_req.add_header('Content-Type', 'application/json') post_to_url(http_req, value) if stats_interval: if time_now >= (time_count + stats_interval): print("INFO: stats: [ interval=%d records=%d ]" % (stats_interval, elem_count)) sys.stdout.flush() time_count = time_now elem_count = 0 def main(): global avro_schema global http_url_post global print_stdout global print_stdout_num global print_stdout_max global convert_to_json_array global stats_interval global time_count global elem_count try: opts, args = getopt.getopt(sys.argv[1:], "he:k:q:H:u:d:pn:as:P:", ["help", "exchange=", "routing_key=", "queue=", "host=", "url=", "decode-with-avro=", "print=", "num=", "to-json-array=", "stats-interval=", "pidfile="]) except getopt.GetoptError as err: # print help information and exit: print str(err) # will print something like "option -a not recognized" usage(sys.argv[0]) sys.exit(2) amqp_exchange = None amqp_routing_key = None amqp_queue = None amqp_host = "localhost" pidfile = None required_cl = 0 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit() elif o in ("-e", "--exchange"): required_cl += 1 amqp_exchange = a elif o in ("-k", "--routing_key"): required_cl += 1 amqp_routing_key = a elif o in ("-q", "--queue"): required_cl += 1 amqp_queue = a elif o in ("-H", "--host"): amqp_host = a elif o in ("-u", "--url"): http_url_post = a elif o in ("-p", "--print"): print_stdout = 1 elif o in ("-n", "--num"): print_stdout_max = int(a) elif o in ("-a", "--to-json-array"): convert_to_json_array = 1 elif o in ("-s", "--stats-interval"): stats_interval = int(a) if stats_interval < 0: sys.stderr.write("ERROR: `--stats-interval` must be positive\n") sys.exit(1) elif o in ("-d", "--decode-with-avro"): if not avro_available: sys.stderr.write("ERROR: `--decode-with-avro` given but Avro package was " "not found\n") sys.exit(1) if not os.path.isfile(a): sys.stderr.write("ERROR: '%s' does not exist or is not a file\n" % (a,)) sys.exit(1) with open(a) as f: avro_schema = avro.schema.parse(f.read()) elif o in ("-P", "--pidfile"): pidfile = a else: assert False, "unhandled option" amqp_type = "direct" if (required_cl < 3): print "ERROR: Missing required arguments" usage(sys.argv[0]) sys.exit(1) if pidfile: pidfile_f = open(pidfile, 'w') pidfile_f.write(str(mypid)) pidfile_f.write("\n") pidfile_f.close() connection = pika.BlockingConnection(pika.ConnectionParameters(host=amqp_host)) channel = connection.channel() channel.exchange_declare(exchange=amqp_exchange, type=amqp_type) channel.queue_declare(queue=amqp_queue) channel.queue_bind(exchange=amqp_exchange, routing_key=amqp_routing_key, queue=amqp_queue) if print_stdout: print ' [*] Example inspired from: http://www.rabbitmq.com/getstarted.html' print ' [*] Waiting for messages on E =', amqp_exchange, ',', amqp_type, 'RK =', amqp_routing_key, 'Q =', amqp_queue, 'H =', amqp_host, '. Edit code to change any parameter. To exit press CTRL+C' sys.stdout.flush() if stats_interval: elem_count = 0 time_count = int(time.time()) channel.basic_consume(callback, queue=amqp_queue, no_ack=True) channel.start_consuming() if __name__ == "__main__": main() pmacct-1.7.8/examples/pcap_interfaces.map.example0000644000175000017500000000153414354105275021112 0ustar paolopaolo! ! pcap_interfaces_map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! pmacctd: mandatory keys: ifname. ! ! list of currently supported keys follows: ! ! 'ifname' MATCH: name of the interface, ie. eth0, ens1, lo, etc. ! 'ifindex' SET: interface index. A positive 32-bit integer value ! is expected. ! 'direction' SET: packet sampling direction. Possible values are ! 'in' and 'out'. It influences whether ifindex should ! be used to populate in_iface or out_iface. Omitting the ! direction enables both ingress and egress collection: ! in this case populating in_iface or out_iface with the ! supplied ifindex does stops (as it would not be possible ! anymore to clearly determine direction). ! ! Examples: ! ifindex=100 ifname=eth0 direction=in ifindex=200 ifname=ens1 direction=in pmacct-1.7.8/examples/ports.lst.example0000644000175000017500000000012714354105275017155 0ustar paolopaolo! ! Sample ports-list; enabled by 'ports_file' key. ! 22 23 25 110 137 139 ! ... 4662 pmacct-1.7.8/examples/pmacctd-multiple-plugins.conf.example0000644000175000017500000000123314354105275023053 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! libpcap daemon configs ! pcap_interface: eth0 ! ! Plugins definitions ! plugins: memory[in], memory[out] ! ! 'in' plugin configuration ! aggregate[in]: src_host aggregate_filter[in]: dst net 192.168.0.0/16 imt_path[in]: /tmp/acct_in.pipe ! ! 'out' plugin configuration ! aggregate[out]: dst_host aggregate_filter[out]: src net 192.168.0.0/16 imt_path[out]: /tmp/acct_out.pipe ! ! shared plugin configuration ! imt_buckets: 65537 imt_mem_pools_size: 65536 imt_mem_pools_number: 0 pmacct-1.7.8/examples/primitives.lst.example0000644000175000017500000001240614354105275020204 0ustar paolopaolo! ! aggregate_primitives: list of custom-defined primitives ! ! File syntax is key-based. Position of keys inside the same row (rule) is not ! relevant; Spaces are not allowed (ie. 'id = 1' is not valid). The first full ! match wins (like in firewall rules). ! ! list of currently supported keys follows: ! ! 'name' SET: Primitive name: it will be used as identifier of ! the primitive itself and hence must be unique. This ! name can be used in 'aggregate' statements to include ! the primitive as part of plugin aggregation methods. ! 'packet_ptr' MATCH: Applies to pmacctd (libpcap), uacctd (NFLOG), ! nfacctd (NetFlow v9/IPFIX dataLinkFrameSection IE #315) ! and sFlow v5 sampled headers section: defines the base ! pointer in the packet where to read the primitive value; ! This is to be used in conjunction with 'len' to define ! the portion of the packet to save (up to the maximum ! captured length; in pmacctd and uacctd, this can be ! adjusted via 'snaplen' config directive). The supported ! syntax is: ":[]+[]". ! Valid 'layer' keys are: 'packet', 'mac', 'vlan', 'mpls', ! 'l3', 'l4' and 'payload'; 'layer' keyword is mandatory. ! 'protocol value' is an optional key and can be supplied ! in either decimal or hex format. 'offset' is an optional ! key and is expected to be a positive decimal number. A ! maximum of 8 'packet_ptr' definitions are allowed per ! entry. ! 'field_type' MATCH: Applies to NetFlow v9/IPFIX collection and export: ! defines which field type (Information Element ID) to ! select. Optionally, a PEN value can be supplied as well ! via the : format. As a reference the IPFIX ! standard IEs definition table can be used: ! http://www.iana.org/assignments/ipfix/ipfix.xhtml ; for ! non-standard IEs, vendor tend to supply equivalent docs: ! should this result unavailable, make a trace of the data, ! ie. "tcpdump -i any -n -w ", ! then analyse it, ie. with Wireshark, isolating templates ! in order to find relevant information. ! 'len' MATCH: Length of the primitive, in bytes. 'vlen' word ! defines a primitive to be variable length. In pmacctd ! and uacctd only strings can be defined vlen; in nfacctd ! string and raw semantics can be defined vlen. ! 'semantics' SET: Specifies semantics of the primitive. Allowed values ! are: 'u_int' (unsigned integer [1,2,4,8 bytes long], ! presented as decimal number), 'hex' (unsigned integer ! [1,2,4,8 bytes long], presented as hexadecimal number), ! 'ip' (IP address), 'mac' (L2 MAC address), 'str' ! (string) and 'raw' (raw data, fixed or variable length ! in hex format). Note: when selecting 'str' as semantics, ! although some effort is put in ensuring null-termination ! in pmacct, it is recommended that the original string is ! null-terminated; alternatively pick 'raw' in order to ! avoid undefined behaviours; 'raw' will require some ! simple post processing in order to be converted back to ! a string. ! ! Examples: ! ! Defines a primitive called 'mtla': it picks NetFlow v9/IPFIX field type #47 ! (mplsTopLabelIPv4Address), reads for 4 bytes (since it's expected to be an ! IPv4 address) and will present it as an IP address. ! In an 'aggregate' statement this primitive would be intuitively recalled by ! its name, 'mtla'. ! name=mtla field_type=47 len=4 semantics=ip ! ! Defines a primitive called 'mtlpl': it picks NetFlow v9/IPFIX field type #91 ! (mplsTopLabelPrefixLength), reads for 1 byte (since it's expected to be a ! prefix length/network mask) and will present it as a decimal unsigned int. ! name=mtlpl field_type=91 len=1 semantics=u_int ! ! Defines a primitive called 'alu_91': it picks NetFlow v9/IPFIX field type ! #91 and PEN #637 (Alcatel-Lucent), reads for 2 bytes and will present it as ! a hexadecimal. ! name=alu_91 field_type=637:91 len=2 semantics=hex ! ! Defines a primitive called 'ttl_pm': if reading an IPv4 header (l3:0x800) ! the base pointer is offset by 8 bytes, if reading an IPv6 header (l3:0x86dd) ! it is offset by 7 bytes; it reads for 1 byte and will present it as unsigned ! int. ! name=ttl_pm packet_ptr=l3:0x800+8 packet_ptr=l3:0x86dd+7 len=1 semantics=u_int ! ! Defines a primitive called 'udp_len': base pointer is set to the UDP header ! (l4:17) plus 4 bytes offset, reads for 2 byte and will present it as unsigned ! int. Correct working of "l4" offset does require setting the configuration key ! [pm|u]acctd_force_frag_handling to true. ! name=udp_len packet_ptr=l4:17+4 len=2 semantics=u_int ! ! Defines a primitive called 'tcp_win': base pointer is set to the TCP header ! (l4:6) plus 14 bytes offset, reads for 2 byte and will present it as unsigned ! int. Correct working of "l4" offset does require setting the configuration key ! [pm|u]acctd_force_frag_handling to true. ! name=tcp_win packet_ptr=l4:6+14 len=2 semantics=u_int ! ! nfprobe example: defines a primitive called 'ttl_nf': if reading an IPv4 ! header (l3:0x800) the base pointer is offset by 8 bytes, if reading an IPv6 ! header (l3:0x86dd) it is offset by 7 bytes; it reads for 1 byte and will ! present it as unsigned int. The info is carried via NetFlow/IPFIX in field ! type #192. ! name=ttl_nf packet_ptr=l3:0x800+8 packet_ptr=l3:0x86dd+7 len=1 semantics=u_int field_type=192 pmacct-1.7.8/examples/networks.lst.example0000644000175000017500000000143514354105275017665 0ustar paolopaolo! ! Sample networks-list; enabled by 'networks_file' key. ! ! Format supported: [<(BGP) next-hop>','][['_']',']'/' ! ! ! '/' examples ! 192.168.95.0/24 192.168.94.0/25 192.168.94.128/25 192.168.92.0/26 192.168.92.64/26 192.168.92.128/26 192.168.92.192/26 ! ! ',''/' examples ! 65500,192.168.1.0/24 65501,192.168.2.0/25 65502,192.168.4.0/23 ! ! '_'',''/' examples ! 64512_65500,192.168.1.0/24 64512_65501,192.168.2.0/25 64512_65502,192.168.4.0/23 ! ! <(BGP) next-hop>','',''/' examples ! 10.0.0.1,65500,192.168.1.0/24 10.0.0.2,65501,192.168.2.0/25 10.0.0.3,65502,192.168.4.0/23 pmacct-1.7.8/examples/nfacctd-print.conf.example0000644000175000017500000000065514354105275020673 0ustar paolopaolo! ! nfacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! NetFlow/IPFIX daemon configs ! ! nfacctd_port: 5678 ! nfacctd_time_secs: true nfacctd_time_new: true ! ! Plugins definitions ! plugins: print[foo] ! ! 'foo' plugin configuration ! aggregate[foo]: src_host, dst_host, src_port, dst_port, proto pmacct-1.7.8/examples/probe_netflow.conf.example0000644000175000017500000000076414354105275021005 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys ! supported by 'nfacctd' and 'pmacctd' ? ! ! debug: true daemonize: true pcap_interface: eth0 aggregate: src_host, dst_host, src_port, dst_port, proto, tos plugins: nfprobe nfprobe_receiver: 192.168.1.1:2100 nfprobe_version: 9 ! nfprobe_engine: 1:1 ! nfprobe_timeouts: tcp=120:maxlife=3600 ! ! networks_file: /path/to/networks.lst ! classifiers: /path/to/classifiers/ ! snaplen: 700 pmacct-1.7.8/examples/peers.map.example0000644000175000017500000000657414354105275017113 0ustar paolopaolo! ! bgp_peer_src_as_map: BGP source peer ASN map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! nfacctd, sfacctd: valid keys: id, ip, in, bgp_nexthop, src_mac, vlan. ! ! pmacctd, uacctd: valid keys: id, ip, filter. ! ! list of currently supported keys follow: ! ! 'id' SET: value to assign to a matching packet or flow. Other ! than hard-coded AS numbers, this field accepts also the ! 'bgp' keyword which triggers a BGP lookup and returns ! its result: useful to handle exceptions. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' MATCH: input interface ! 'bgp_nexthop' MATCH: BGP next-hop of the flow source IP address (RPF- ! like). This value is compared against the corresponding ! BGP RIB of the exporting device. ! 'peer_dst_as' MATCH: first AS hop within the AS-PATH of the source IP ! address (RPF-like). This value is compared against the ! BGP RIB of the exporting device (see 'bgp_daemon' ! configuration directive). ! 'src_mac' MATCH: In NetFlow v9 and IPFIX this is compared against ! IE #56, in sFlow against source MAC address field part ! of the Extended Switch object. ! 'vlan' MATCH: In NetFlow v9 and IPFIX this is compared against ! IE #58, in sFlow against in/out VLAN ID fields part of ! the Extended Switch object. ! 'filter' MATCH: incoming data is compared against the supplied ! filter expression (expected in libpcap syntax); the ! filter needs to be enclosed in quotes ('). ! ! Examples: ! ! Private peering with AS12345 on router with IP address 192.168.2.1, SNMP ifIndex 7 ! id=12345 ip=192.168.2.1 in=7 ! A way to model a public internet exchange - in case MAC addresses are not available, ! ie. NetFlow v5. The catch-all entry at the end can be the AS number of the exchange. ! 'peer_dst_as' can be used instead of the BGP next-hop for the very same purpose, with ! perhaps 'peer_dst_as' being more effective in case of, say, egress NetFlow. Note that ! by using either 'bgp_nexthop' or 'peer_dst_as' for this purpose constitutes only an ! educated guess. ! id=34567 ip=192.168.1.1 in=7 bgp_nexthop=10.10.10.1 id=45678 ip=192.168.1.1 in=7 bgp_nexthop=10.10.10.2 id=56789 ip=192.168.1.1 in=7 ! A way to model a public internet exchange - in case MAC addresses are available. The ! method is exact and hence doesn't require a catch-all entry at the end. ! id=34567 ip=192.168.1.1 in=7 src_mac=00:01:02:03:04:05 id=45678 ip=192.168.1.1 in=7 src_mac=00:01:02:03:04:06 ! Same example as the previous one but with pmacctd / uacctd: id=34567 ip=0.0.0.0/0 filter='ether src 00:01:02:03:04:05' id=45678 ip=0.0.0.0/0 filter='ether src 00:01:02:03:04:06' ! A simple example on how to trigger BGP lookups rather than returning a fixed result. ! This allows to handle exceptions to static mapping id=bgp ip=192.168.2.1 in=7 pmacct-1.7.8/examples/kafka/0000755000175000017500000000000014354105275014705 5ustar paolopaolopmacct-1.7.8/examples/kafka/kafka_consumer.py0000755000175000017500000001445214354105275020260 0ustar paolopaolo#!/usr/bin/env python # # Confluent Kafka Python module is available at: # https://github.com/confluentinc/confluent-kafka-python # # UltraJSON, an ultra fast JSON encoder and decoder, is available at: # https://pypi.python.org/pypi/ujson # # Binding to the topic specified by kafka_topic (by default 'acct') allows to # receive messages published by a 'kafka' plugin, in JSON format. Similarly for # BGP daemon bgp_*_topic and BMP daemon bmp_*_topic. # # Three pipelines are supported in this script: # * Kafka -> Kafka # * Kafka -> REST API # * Kafka -> stdout # # A single data encoding format is supported in this script: # * JSON import sys, os, getopt, StringIO, time, urllib2 import confluent_kafka import ujson as json import uuid def usage(tool): print "" print "Usage: %s [Args]" % tool print "" print "Mandatory Args:" print " -t, --topic".ljust(25) + "Define the topic to consume from" print "" print "Optional Args:" print " -h, --help".ljust(25) + "Print this help" print " -g, --group_id".ljust(25) + "Specify the consumer Group ID" print " -e, --earliest".ljust(25) + "Set consume topic offset to 'earliest' [default: 'latest']" print " -H, --host".ljust(25) + "Define Kafka broker host [default: '127.0.0.1:9092']" print " -p, --print".ljust(25) + "Print data to stdout" print " -n, --num".ljust(25) + "Number of rows to print to stdout [default: 0, ie. forever]" print " -T, --produce-topic".ljust(25) + "Define a topic to produce to" print " -u, --url".ljust(25) + "Define a URL to HTTP POST data to" print " -a, --to-json-array".ljust(25) + "Convert list of newline-separated JSON objects in a JSON array" print " -s, --stats-interval".ljust(25) + "Define a time interval, in secs, to get statistics to stdout" print " -P, --pidfile".ljust(25) + "Set a pidfile to record active processes PID" def post_to_url(http_req, value): try: urllib2.urlopen(http_req, value) except urllib2.HTTPError, err: print "WARN: urlopen() returned HTTP error code:", err.code sys.stdout.flush() except urllib2.URLError, err: print "WARN: urlopen() returned URL error reason:", err.reason sys.stdout.flush() def main(): try: opts, args = getopt.getopt(sys.argv[1:], "ht:T:pin:g:H:d:eu:as:r:P:", ["help", "topic=", "group_id=", "host=", "earliest=", "url=", "produce-topic=", "print=", "num=", "to-json-array=", "stats-interval=", "pidfile="]) except getopt.GetoptError as err: # print help information and exit: print str(err) # will print something like "option -a not recognized" usage(sys.argv[0]) sys.exit(2) mypid = os.getpid() kafka_topic = None kafka_group_id = uuid.uuid1() kafka_host = "127.0.0.1:9092" kafka_produce_topic = None topic_offset = "latest" http_url_post = None print_stdout = 0 print_stdout_num = 0 print_stdout_max = 0 convert_to_json_array = 0 stats_interval = 0 pidfile = None required_cl = 0 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit() elif o in ("-t", "--topic"): required_cl += 1 kafka_topic = a elif o in ("-T", "--produce-topic"): kafka_produce_topic = a elif o in ("-p", "--print"): print_stdout = 1 elif o in ("-n", "--num"): print_stdout_max = int(a) elif o in ("-g", "--group_id"): kafka_group_id = a elif o in ("-H", "--host"): kafka_host = a elif o in ("-e", "--earliest"): topic_offset = "earliest" elif o in ("-u", "--url"): http_url_post = a elif o in ("-a", "--to-json-array"): convert_to_json_array = 1 elif o in ("-s", "--stats-interval"): stats_interval = int(a) if stats_interval < 0: sys.stderr.write("ERROR: `-s`, `--stats-interval` must be positive\n") sys.exit(1) elif o in ("-P", "--pidfile"): pidfile = a else: assert False, "unhandled option" if required_cl < 1: print "ERROR: Missing required arguments" usage(sys.argv[0]) sys.exit(1) if pidfile: pidfile_f = open(pidfile, 'w') pidfile_f.write(str(mypid)) pidfile_f.write("\n") pidfile_f.close() consumer_conf = { 'bootstrap.servers': kafka_host, 'group.id': kafka_group_id, 'default.topic.config': { 'auto.offset.reset': topic_offset } } consumer = confluent_kafka.Consumer(**consumer_conf) consumer.subscribe([kafka_topic]) producer_conf = { 'bootstrap.servers': kafka_host } if kafka_produce_topic: producer = confluent_kafka.Producer(**producer_conf) if stats_interval: elem_count = 0 time_count = int(time.time()) while True: message = consumer.poll() value = message.value().decode('utf-8') if stats_interval: time_now = int(time.time()) if len(value): try: jsonObj = json.loads(value) except ValueError: print("ERROR: json.loads: '%s'. Skipping." % value) continue if 'event_type' in jsonObj: if jsonObj['event_type'] == "purge_init": continue elif jsonObj['event_type'] == "purge_close": continue elif jsonObj['event_type'] == "purge": pass else: print("WARN: json.loads: flow record with unexpected event_type '%s'. Skipping." % jsonObj['event_type']) continue else: print("WARN: json.loads: flow record with no event_type field. Skipping.") continue # # XXX: data enrichments, manipulations, correlations, filtering, etc. go here # if stats_interval: elem_count += 1 if convert_to_json_array: value = "[" + value + "]" value = value.replace('\n', ',\n') value = value.replace(',\n]', ']') if print_stdout: print("%s:%d:%d: pid=%d key=%s value=%s" % (message.topic(), message.partition(), message.offset(), mypid, str(message.key()), value)) sys.stdout.flush() print_stdout_num += 1 if (print_stdout_max == print_stdout_num): sys.exit(0) if http_url_post: http_req = urllib2.Request(http_url_post) http_req.add_header('Content-Type', 'application/json') post_to_url(http_req, value) if kafka_produce_topic: producer.produce(kafka_produce_topic, value) producer.poll(0) if stats_interval: if time_now >= (time_count + stats_interval): print("INFO: stats: [ time=%s interval=%d records=%d pid=%d ]" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time_now)), stats_interval, elem_count), mypid) sys.stdout.flush() time_count = time_now elem_count = 0 if __name__ == "__main__": main() pmacct-1.7.8/examples/nfacctd-sql.conf.example0000644000175000017500000000151514354105275020332 0ustar paolopaolo! ! nfacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! NetFlow/IPFIX daemon configs ! ! nfacctd_port: 5678 ! nfacctd_time_secs: true nfacctd_time_new: true ! ! Plugins definitions ! plugins: mysql[foo] ! plugins: pgsql[foo] ! ! 'foo' plugin configuration ! aggregate[foo]: src_host, dst_host sql_db[foo]: pmacct sql_table[foo]: acct sql_table_version[foo]: 1 ! sql_table_version[foo]: 2 ! sql_table_version[foo]: 3 sql_passwd[foo]: arealsmartpwd sql_user[foo]: pmacct sql_refresh_time[foo]: 60 ! sql_optimize_clauses[foo]: true sql_history[foo]: 1m sql_history_roundoff[foo]: mh ! sql_preprocess[foo]: qnum=1000, minp=5 ! networks_file[foo]: /path/to/networks.example ! ports_file[foo]: /path/to/ports.example pmacct-1.7.8/examples/lg/0000755000175000017500000000000014354105415014226 5ustar paolopaolopmacct-1.7.8/examples/lg/pmbgp.c0000644000175000017500000002431314354105275015506 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define __PMBGP_C /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "addr.h" #ifdef WITH_ZMQ #include "zmq_common.h" #endif #include "bgp/bgp.h" #include "pmbgpd.h" #include "pmbgp.h" /* functions */ #if defined (WITH_ZMQ) && defined (WITH_JANSSON) void usage_pmbgp(char *prog) { printf("%s %s (%s)\n", PMBGP_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [options] [query]\n\n", prog); printf("IP Lookup query options:\n"); printf(" -a\tIP address/prefix to look up\n"); printf(" -d\tRoute Distinguisher to look up\n"); printf(" -r\tBGP peer to look up\n"); printf(" -R\tTCP port of the BGP peer (for BGP through NAT/proxy scenarios)\n"); printf("\n"); printf("Get Peers query options:\n"); printf(" -g\tGet the list of BGP peers at the Looking Glass\n"); printf("\n"); printf("General options:\n"); printf(" -z\tLooking Glass IP address [default: 127.0.0.1]\n"); printf(" -Z\tLooking Glass port [default: 17900]\n"); printf(" -u\tLooking Glass username [default: none]\n"); printf(" -p\tLooking Glass password [default: none]\n"); printf("\n"); printf(" -h\tShow this page\n"); printf(" -V\tPrint version and exit\n"); } void version_pmbgp(char *prog) { printf("%s %s (%s)\n", PMBGP_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); } int main(int argc,char **argv) { char address_str[SRVBUFLEN], peer_str[SRVBUFLEN], rd_str[SRVBUFLEN], port_str[SRVBUFLEN]; char *req_str = NULL, *req_type_str = NULL, *rep_str = NULL, *pfx_delim = NULL; char *zmq_host_str_ptr, zmq_host_str[SRVBUFLEN], default_zmq_host_str[] = "127.0.0.1"; int zmq_port = 0, default_zmq_port = 17900, results = 0, query_type = 0, idx = 0; struct p_zmq_host zmq_host; struct host_addr peer_ha, address_ha; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int cp, ip_lookup_query, get_peers_query; memset(address_str, 0, sizeof(address_str)); memset(rd_str, 0, sizeof(rd_str)); memset(peer_str, 0, sizeof(peer_str)); memset(port_str, 0, sizeof(port_str)); memset(zmq_host_str, 0, sizeof(zmq_host_str)); memset(&zmq_host, 0, sizeof(zmq_host)); memset(&address_ha, 0, sizeof(address_ha)); memset(&peer_ha, 0, sizeof(peer_ha)); ip_lookup_query = FALSE; get_peers_query = FALSE; while ((cp = getopt(argc, argv, ARGS_PMBGP)) != -1) { switch (cp) { case 'h': usage_pmbgp(argv[0]); exit(0); break; case 'V': version_pmbgp(argv[0]); exit(0); break; case 'a': strlcpy(address_str, optarg, sizeof(address_str)); ip_lookup_query = TRUE; break; case 'd': strlcpy(rd_str, optarg, sizeof(rd_str)); ip_lookup_query = TRUE; break; case 'r': strlcpy(peer_str, optarg, sizeof(peer_str)); ip_lookup_query = TRUE; break; case 'R': strlcpy(port_str, optarg, sizeof(port_str)); ip_lookup_query = TRUE; break; case 'g': get_peers_query = TRUE; break; case 'z': strlcpy(zmq_host_str, optarg, sizeof(zmq_host_str)); break; case 'Z': zmq_port = atoi(optarg); break; case 'u': strlcpy(zmq_host.zap.username, optarg, sizeof(zmq_host.zap.username)); break; case 'p': strlcpy(zmq_host.zap.password, optarg, sizeof(zmq_host.zap.password)); break; default: printf("ERROR: parameter %c unknown! \n Exiting...\n\n", cp); usage_pmbgp(argv[0]); exit(1); break; } } if (!ip_lookup_query && !get_peers_query) { printf("ERROR: no query specificed. Exiting ..\n"); usage_pmbgp(argv[0]); exit(1); } if (ip_lookup_query && get_peers_query) { printf("ERROR: IP Lookup and Get Peers queries are mutual exclusive. Please select only one. Exiting ..\n"); exit(1); } if (ip_lookup_query && (!strlen(address_str) || !strlen(peer_str))) { printf("ERROR: mandatory options for IP Lookup query (-a, -r) are not specified. Exiting ..\n"); exit(1); } if (!strlen(zmq_host_str)) zmq_host_str_ptr = default_zmq_host_str; else zmq_host_str_ptr = zmq_host_str; if (!zmq_port) zmq_port = default_zmq_port; /* craft query */ if (ip_lookup_query) { { json_t *req_obj = json_object(); json_object_set_new_nocheck(req_obj, "query_type", json_integer(BGP_LG_QT_IP_LOOKUP)); json_object_set_new_nocheck(req_obj, "queries", json_integer(1)); req_type_str = json_dumps(req_obj, JSON_PRESERVE_ORDER); json_decref(req_obj); } { json_t *req_obj = json_object(); str_to_addr(peer_str, &peer_ha); if (peer_ha.family) json_object_set_new_nocheck(req_obj, "peer_ip_src", json_string(peer_str)); else { printf("ERROR: invalid -r value. Exiting ..\n"); exit(1); } if (strlen(port_str)) { int port_int; port_int = atoi(port_str); if (port_int > 0 && port_int <= 65535) json_object_set_new_nocheck(req_obj, "peer_tcp_port", json_integer(port_int)); else { printf("ERROR: invalid -R value. Exiting ..\n"); exit(1); } } /* Simplified validation: only IP address part */ pfx_delim = strchr(address_str, '/'); if (pfx_delim) (*pfx_delim) = '\0'; str_to_addr(address_str, &address_ha); if (pfx_delim) (*pfx_delim) = '/'; if (address_ha.family) json_object_set_new_nocheck(req_obj, "ip_prefix", json_string(address_str)); else { printf("ERROR: invalid -a value. Exiting ..\n"); exit(1); } /* no specific validation done for the RD */ if (strlen(rd_str)) json_object_set_new_nocheck(req_obj, "rd", json_string(rd_str)); req_str = json_dumps(req_obj, JSON_PRESERVE_ORDER); json_decref(req_obj); } } else if (get_peers_query) { { json_t *req_obj = json_object(); json_object_set_new_nocheck(req_obj, "query_type", json_integer(BGP_LG_QT_GET_PEERS)); json_object_set_new_nocheck(req_obj, "queries", json_integer(1)); req_type_str = json_dumps(req_obj, JSON_PRESERVE_ORDER); json_decref(req_obj); } } pmbgp_zmq_req_setup(&zmq_host, zmq_host_str_ptr, zmq_port); if (req_str) { pmbgp_zmq_sendmore_str(&zmq_host.sock, req_type_str); pmbgp_zmq_send_str(&zmq_host.sock, req_str); } else { pmbgp_zmq_send_str(&zmq_host.sock, req_type_str); } /* query type + results */ rep_str = pmbgp_zmq_recv_str(&zmq_host.sock); if (rep_str) { json_error_t rep_err; json_t *rep_results_obj, *results_json, *query_type_json; rep_results_obj = json_loads(rep_str, 0, &rep_err); if (rep_results_obj) { if (!json_is_object(rep_results_obj)) { printf("WARN: json_is_object() failed for results: %s\n", rep_err.text); exit(1); } else { query_type_json = json_object_get(rep_results_obj, "query_type"); if (query_type_json == NULL) { printf("WARN: no 'query_type' element.\n"); exit(1); } else query_type = json_integer_value(query_type_json); results_json = json_object_get(rep_results_obj, "results"); if (results_json == NULL) { printf("WARN: no 'results' element.\n"); exit(1); } else results = json_integer_value(results_json); } json_decref(rep_results_obj); } printf("%s\n", rep_str); free(rep_str); } /* data */ for (idx = 0; idx < results; idx++) { rep_str = pmbgp_zmq_recv_str(&zmq_host.sock); if (rep_str) { if (query_type == BGP_LG_QT_IP_LOOKUP || query_type == BGP_LG_QT_GET_PEERS) printf("%s\n", rep_str); free(rep_str); } } return 0; } void pmbgp_zmq_req_setup(struct p_zmq_host *zmq_host, char *host, int port) { int ret; if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); zmq_host->sock.obj = zmq_socket(zmq_host->ctx, ZMQ_REQ); if (!zmq_host->sock.obj) { printf("ERROR: zmq_socket() failed for ZMQ_REQ: %s. Exiting.\n", zmq_strerror(errno)); exit(1); } snprintf(zmq_host->sock.str, sizeof(zmq_host->sock.str), "tcp://%s:%u", host, port); if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_USERNAME, zmq_host->zap.username, strlen(zmq_host->zap.username)); if (ret == ERR) { printf("ERROR: zmq_setsockopt() ZMQ_PLAIN_USERNAME failed: %s\nExiting.\n", zmq_strerror(errno)); exit(1); } ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_PASSWORD, zmq_host->zap.password, strlen(zmq_host->zap.password)); if (ret == ERR) { printf("ERROR: zmq_setsockopt() ZMQ_PLAIN_PASSWORD failed: %s\nExiting.\n", zmq_strerror(errno)); exit(1); } } ret = zmq_connect(zmq_host->sock.obj, zmq_host->sock.str); if (ret == ERR) { printf("ERROR: zmq_connect() failed for ZMQ_REQ: %s. Exiting.\n", zmq_strerror(errno)); exit(1); } } char *pmbgp_zmq_recv_str(struct p_zmq_sock *sock) { char buf[LARGEBUFLEN]; int len; memset(buf, 0, sizeof(buf)); len = zmq_recv(sock->obj, buf, (sizeof(buf) - 1), 0); if (len == ERR) return NULL; else return strndup(buf, sizeof(buf)); } int pmbgp_zmq_send_str(struct p_zmq_sock *sock, char *buf) { int len; len = zmq_send(sock->obj, buf, strlen(buf), 0); return len; } int pmbgp_zmq_sendmore_str(struct p_zmq_sock *sock, char *buf) { int len; len = zmq_send(sock->obj, buf, strlen(buf), ZMQ_SNDMORE); return len; } #else int main(int argc,char **argv) { printf("WARN: pmbgp: tool depends on missing --enable-zmq and --enable-jansson. Exiting.\n"); return 1; } #endif pmacct-1.7.8/examples/lg/pmbgp.py0000755000175000017500000001231314354105275015714 0ustar paolopaolo#!/usr/bin/env python3 # # import sys, os, getopt, struct, time import json import zmq def usage(tool): print("") print(f"Usage: {tool} [options] [query]") print("") print("IP Lookup query options:") print(" -a, --prefix".ljust(25) + "IP address/prefix to look up") print(" -d, --rd".ljust(25) + "Route Distinguisher to look up") print(" -r, --peer".ljust(25) + "BGP peer to look up") print(" -R, --peer-port".ljust(25) + "TCP port of the BGP peer (for BGP through NAT/proxy scenarios)") print("") print("Get Peers query options:") print(" -g, --get-peers".ljust(25) + "Get the list of BGP peers at the Looking Glass") print("") print("General options:") print(" -z, --zmq-host".ljust(25) + "Looking Glass IP address [default: 127.0.0.1]") print(" -Z, --zmq-port".ljust(25) + "Looking Glass port [default: 17900]") print(" -u, --zmq-user".ljust(25) + "Looking Glass username [default: none]") print(" -p, --zmq-passwd".ljust(25) + "Looking Glass password [default: none]") print("") print(" -h, --help".ljust(25) + "Print this help") def main(): try: opts, args = getopt.getopt(sys.argv[1:], "ha:d:r:R:z:Z:u:p:g", ["help", "prefix=", "rd=", "peer=", "peer-port=", "zmq-host=", "zmq-port=", "zmq-user=", "zmq-passwd=", "get-peers="]) except getopt.GetoptError as err: print(str(err)) usage(sys.argv[0]) sys.exit(2) # Vars for connecting to the LG lgHost = "127.0.0.1" lgPort = "17900" lgUser = b"" lgPasswd = b"" queryTypeObj = {} queryDataObj = {} queryTypeJsonObj = "" queryDataJsonObj = "" # Vars for IP Lookup query queryIpl = 0 queryIplPrefix = "" queryIplRd = "" queryIplPeer = "" queryIplPeerPort = "" queryIplRequiredCl = 0 # Vars for Get Peers query queryGp = 0 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit() elif o in ("-a", "--prefix"): queryIplRequiredCl += 1 queryIpl = 1 queryIplPrefix = a elif o in ("-d", "--rd"): queryIpl = 1 queryIplRd = a elif o in ("-r", "--peer"): queryIplRequiredCl += 1 queryIpl = 1 queryIplPeer = a elif o in ("-R", "--peer-port"): queryIpl = 1 queryIplPeerPort = a elif o in ("-g", "--get-peers"): queryGp = 1 elif o in ("-z", "--zmq-host"): lgHost = a elif o in ("-Z", "--zmq-port"): lgPort = a elif o in ("-u", "--zmq-user"): lgUser = a.encode() elif o in ("-p", "--zmq-passwd"): lgPasswd = a.encode() else: assert False, "unhandled option" # Validations if not queryGp and not queryIpl: print("ERROR: no query specificed.") usage(sys.argv[0]) sys.exit(1) if queryGp and queryIpl: print("ERROR: IP Lookup and Get Peers queries are mutual exclusive. Please select only one.") sys.exit(1) if queryIpl and queryIplRequiredCl < 2: print("ERROR: Missing required arguments (-a, -r) for IP Lookup query") usage(sys.argv[0]) sys.exit(1) # Craft query if queryIpl: queryTypeObj['query_type'] = 1 queryTypeObj['queries'] = 1 queryDataObj['peer_ip_src'] = queryIplPeer queryDataObj['ip_prefix'] = queryIplPrefix if len(queryIplRd): queryDataObj['rd'] = queryIplRd if len(queryIplPeerPort): queryDataObj['peer_tcp_port'] = queryIplPeerPort queryTypeJsonObj = json.dumps(queryTypeObj).encode() queryDataJsonObj = json.dumps(queryDataObj).encode() if queryGp: queryTypeObj['query_type'] = 2 queryTypeObj['queries'] = 1 queryTypeJsonObj = json.dumps(queryTypeObj).encode() # Connect to LG, send request, read reply lgClientZmqCtx = zmq.Context() lgClientZmqReq = lgClientZmqCtx.socket(zmq.REQ) if len(lgUser): lgClientZmqReq.plain_username = lgUser if len(lgPasswd): lgClientZmqReq.plain_password = lgPasswd lgConnectStr = "tcp://" + lgHost + ":" + lgPort lgClientZmqReq.connect(lgConnectStr) if len(queryDataJsonObj): lgClientZmqReq.send(queryTypeJsonObj, zmq.SNDMORE) lgClientZmqReq.send(queryDataJsonObj) else: lgClientZmqReq.send(queryTypeJsonObj) repResults = lgClientZmqReq.recv(); if len(repResults): repType = 0 repNum = 0 repResultsJsonObj = json.loads(repResults) if not 'query_type' in repResultsJsonObj.keys(): print("WARN: no 'query_type' element.") sys.exit(1) else: repType = repResultsJsonObj['query_type'] if not 'results' in repResultsJsonObj.keys(): print("WARN: no 'results' element.") sys.exit(1) else: repNum = repResultsJsonObj['results'] print(repResults) repIdx = 0 while repIdx < repNum: repData = lgClientZmqReq.recv(); print(repData) repIdx += 1 if __name__ == "__main__": main() pmacct-1.7.8/examples/lg/Makefile.in0000644000175000017500000005174614354105415016310 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @USING_BGP_BINS_TRUE@noinst_PROGRAMS = pmbgp$(EXEEXT) subdir = examples/lg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am__pmbgp_SOURCES_DIST = pmbgp.c pmbgp.h @USING_BGP_BINS_TRUE@am_pmbgp_OBJECTS = pmbgp-pmbgp.$(OBJEXT) pmbgp_OBJECTS = $(am_pmbgp_OBJECTS) @USING_BGP_BINS_TRUE@pmbgp_DEPENDENCIES = \ @USING_BGP_BINS_TRUE@ $(top_builddir)/src/libcommon.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = pmbgp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(pmbgp_CFLAGS) $(CFLAGS) \ $(pmbgp_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/pmbgp-pmbgp.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmbgp_SOURCES) DIST_SOURCES = $(am__pmbgp_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) @USING_BGP_BINS_TRUE@pmbgp_SOURCES = pmbgp.c pmbgp.h @USING_BGP_BINS_TRUE@pmbgp_CFLAGS = -I$(top_srcdir)/src $(AM_CFLAGS) @USING_BGP_BINS_TRUE@pmbgp_LDFLAGS = $(DEFS) @ZMQ_CFLAGS@ @USING_BGP_BINS_TRUE@pmbgp_LDADD = $(top_builddir)/src/libcommon.la @ZMQ_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/lg/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign examples/lg/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list pmbgp$(EXEEXT): $(pmbgp_OBJECTS) $(pmbgp_DEPENDENCIES) $(EXTRA_pmbgp_DEPENDENCIES) @rm -f pmbgp$(EXEEXT) $(AM_V_CCLD)$(pmbgp_LINK) $(pmbgp_OBJECTS) $(pmbgp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmbgp-pmbgp.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmbgp-pmbgp.o: pmbgp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pmbgp_CFLAGS) $(CFLAGS) -MT pmbgp-pmbgp.o -MD -MP -MF $(DEPDIR)/pmbgp-pmbgp.Tpo -c -o pmbgp-pmbgp.o `test -f 'pmbgp.c' || echo '$(srcdir)/'`pmbgp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmbgp-pmbgp.Tpo $(DEPDIR)/pmbgp-pmbgp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmbgp.c' object='pmbgp-pmbgp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pmbgp_CFLAGS) $(CFLAGS) -c -o pmbgp-pmbgp.o `test -f 'pmbgp.c' || echo '$(srcdir)/'`pmbgp.c pmbgp-pmbgp.obj: pmbgp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pmbgp_CFLAGS) $(CFLAGS) -MT pmbgp-pmbgp.obj -MD -MP -MF $(DEPDIR)/pmbgp-pmbgp.Tpo -c -o pmbgp-pmbgp.obj `if test -f 'pmbgp.c'; then $(CYGPATH_W) 'pmbgp.c'; else $(CYGPATH_W) '$(srcdir)/pmbgp.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmbgp-pmbgp.Tpo $(DEPDIR)/pmbgp-pmbgp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmbgp.c' object='pmbgp-pmbgp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pmbgp_CFLAGS) $(CFLAGS) -c -o pmbgp-pmbgp.obj `if test -f 'pmbgp.c'; then $(CYGPATH_W) 'pmbgp.c'; else $(CYGPATH_W) '$(srcdir)/pmbgp.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/pmbgp-pmbgp.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmbgp-pmbgp.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/examples/lg/pmbgp.h0000644000175000017500000000261114354105275015510 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2017 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define __PMBGP_H #ifdef WITH_ZMQ /* defines */ #define ARGS_PMBGP "hVa:d:r:R:z:Z:u:p:g" #define PMBGP_USAGE_HEADER "pmacct BGP Looking Glass client, pmbgp" /* prototypes */ #if !defined(__PMBGP_C) #define EXT extern #else #define EXT EXT void usage_pmbgp(char *); EXT void version_pmbgp(char *); EXT void pmbgp_zmq_req_setup(struct p_zmq_host *, char *, int); EXT char *pmbgp_zmq_recv_str(struct p_zmq_sock *); EXT int pmbgp_zmq_send_str(struct p_zmq_sock *, char *); EXT int pmbgp_zmq_sendmore_str(struct p_zmq_sock *, char *); #endif #undef EXT #endif /* WITH_ZMQ */ pmacct-1.7.8/examples/lg/Makefile.am0000644000175000017500000000037514354105275016273 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) if USING_BGP_BINS noinst_PROGRAMS = pmbgp pmbgp_SOURCES = pmbgp.c pmbgp.h pmbgp_CFLAGS = -I$(top_srcdir)/src $(AM_CFLAGS) pmbgp_LDFLAGS = $(DEFS) @ZMQ_CFLAGS@ pmbgp_LDADD = $(top_builddir)/src/libcommon.la @ZMQ_LIBS@ endif pmacct-1.7.8/examples/pmacctd-imt.conf.example0000644000175000017500000000064114354105275020334 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! libpcap daemon configs ! pcap_interface: eth0 ! ! Plugins definitions ! plugins: memory[foo] ! ! 'foo' plugin configuration ! aggregate[foo]: src_host, dst_host imt_buckets: 65537 imt_mem_pools_size: 65536 ! imt_mem_pools_number: 0 pmacct-1.7.8/examples/med.map.example0000644000175000017500000000315514354105275016532 0ustar paolopaolo! ! bgp_src_med_type: BGP source MED (Multi Exit Discriminator) map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! nfacctd, sfacctd: valid keys: id, ip, in, bgp_nexthop, src_mac. ! ! list of currently supported keys follow: ! ! 'id' ID value to assign to a matching packet or flow. Other ! than hard-coded MED values this field accepts also the ! 'bgp' keyword which triggers a BGP lookup and returns ! its result: useful to handle exceptions. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' Input interface. ! 'bgp_nexthop' BGP next-hop of the flow source IP address (RPF-like). ! This value is compared against the corresponding BGP ! RIB of the exporting device. ! 'peer_dst_as' First AS hop within the AS-PATH of the source IP address ! (RPF-like). This value is compared against the BGP RIB ! of the exporting device (see 'bgp_daemon' configuration ! directive). ! 'src_mac' Source MAC address of the flow. Requires NetFlow v9, ! IPFIX or sFlow. ! ! A few examples follow. ! ! Customer connected to router with IP address 192.168.2.1, SNMP ifIndex 7 ! id=20 ip=192.168.2.1 in=7 pmacct-1.7.8/examples/flow_to_rd.map.example0000644000175000017500000000453114354105275020122 0ustar paolopaolo! ! flow_to_rd_map: Flow to BGP/MPLS VPN RD map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! nfacctd, sfacctd: valid keys: id, ip, in, out, bgp_nexthop, mpls_label_bottom. ! ! list of currently supported keys follow: ! ! 'id' SET: BGP-signalled MPLS L2/L3 VPN Route Distinguisher ! (RD) value. Encoding types #0, #1 and #2 are supported ! as per rfc4364 in asplain notation as per rfc5396. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' MATCH: Input interface. ! 'out' MATCH: Output interface. ! 'bgp_nexthop' MATCH: IPv4/IPv6 address of the next-hop BGP router. In ! MPLS-enabled networks this can be also matched against ! top label address where available (ie. egress NetFlow ! v9/IPFIX exports). ! 'mpls_vpn_id' MATCH: MPLS VPN ID. A positive 32-bit unsigned integer ! is expected as value. In NetFlow/IPFIX this is compared ! against field types #234 and #235. ! 'mpls_label_bottom' MATCH: MPLS bottom label value. ! ! Examples: ! ! Maps input interface 100 of router 192.168.1.1 to RD 0:65512:1 - ie. ! a BGP/MPLS VPN Route Distinguisher encoded as type #0 according to ! to rfc4364: <2-bytes ASN>: . Type #2 is equivalent to type #0 ! except it supports 4-bytes ASN encoding. ! id=0:65512:1 ip=192.168.1.1 in=100 ! ! Maps the router 192.168.1.1, that is, all interfaces belonging to such ! router to RD 0:65512:1 ! id=0:65512:1 ip=192.168.1.1 ! ! Maps input interface 100 of router 192.168.1.1 to RD 1:192.168.1.1:1 ! ie. a BGP/MPLS VPN Route Distinguisher encoded as type #1 according ! to rfc4364: : ! id=1:192.168.1.1:1 ip=192.168.1.1 in=100 ! ! Maps input interface 100 of router 192.168.1.1 to RD 2:4200000000:1 ! ie. a BGP/MPLS VPN Route Distinguisher encoded as type #2 according ! to rfc4364: : ! id=2:4200000000:1 ip=192.168.1.1 in=100 pmacct-1.7.8/examples/pmacctd-sql.conf.example0000644000175000017500000000155214354105275020344 0ustar paolopaolo! ! pmacctd configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false sampling_rate: 10 ! ! libpcap daemon configs ! pcap_interface: eth0 ! ! Plugins definitions ! plugins: mysql[foo] ! plugins: pgsql[foo] ! ! 'foo' plugin configuration ! aggregate[foo]: src_host,dst_host sql_db[foo]: pmacct sql_table[foo]: acct sql_table_version[foo]: 1 ! sql_table_version[foo]: 2 ! sql_table_version[foo]: 3 sql_passwd[foo]: arealsmartpwd sql_user[foo]: pmacct sql_refresh_time[foo]: 60 ! sql_optimize_clauses: true sql_history[foo]: 1m sql_history_roundoff[foo]: mh ! sql_preprocess[foo]: qnum=1000, minp=5 ! sql_trigger_time[foo]: 1h ! sql_trigger_exec[foo]: /path/to/trigger.sh ! networks_file[foo]: /path/to/networks.example ! ports_file[foo]: /path/to/ports.example pmacct-1.7.8/examples/pretag.map.example0000644000175000017500000004114314354105275017246 0ustar paolopaolo! Pre-Tagging map -- upon matching a set of given conditions, pre_tag_map does ! return numerical (set_tag, set_tag2) or string (label) IDs. ! ! File syntax is key-based. Position of keys inside the same row (rule) is not ! relevant; Spaces are not allowed (ie. 'id = 1' is not valid). The first full ! match wins (like in firewall rules). MATCH keys support negations via a ! negative valuee (ie. 'in=-2' for data not entering via interface with ifindex ! 2); negations are intuitively not supported on SET keys (ie. 'set_tag', etc.); ! also 'filter' and 'ip' keys do not support negative values. 'label', 'jeq' and ! 'stack' keys can be used to alter the standard flow of rules evaluation. ! ! nfacctd: valid keys: set_tag, set_tag2, set_label, set_tos, ip, in, out, ! engine_type, engine_id, source_id, flowset_id, nexthop, bgp_nexthop, filter, ! sample_type, is_bi_flow, is_nel, is_nsel, direction, fwd_status, src_mac, ! dst_mac, vlan, cvlan, src_net, dst_net, is_multicast, mpls_pw_id. ! ! sfacctd: valid keys: set_tag, set_tag2, set_label, set_tos, ip, in, out, ! nexthop, bgp_nexthop, filter, agent_id, sample_type, direction, src_mac, ! dst_mac, vlan, src_net, dst_net, is_multicast, mpls_pw_id. ! ! pmacctd: valid keys: set_tag, set_tag2, set_label, direction and filter. ! ! uacctd: valid keys: set_tag, set_tag2 and set_label. ! ! nfacctd when in 'tee' mode: valid keys: set_tag, set_tag2, set_label, ip, ! in, out, src_mac, dst_mac, vlan, src_net, dst_net, bgp_nexthop, engine_type, ! engine_id, source_id. ! ! sfacctd when in 'tee' mode: valid keys: set_tag, set_tag2, set_label, ip, ! in, out, src_mac, dst_mac, vlan, src_net, dst_net, bgp_nexthop, agent_id. ! ! BGP-related keys supported by pre_tag_map are independent of the collection ! method in use, hence apply to all traffic daemons (when BGP thread is ! enabled): src_as, dst_as, src_comms, comms, peer_src_as, peer_dst_as, ! src_local_pref, local_pref, src_roa, dst_roa, mpls_vpn_rd. ! ! Non-traffic daemons, ie. pmbgpd (including bgp_daemon_tag_map), pmbmpd ! (including bmp_daemon_tag_map), pmtelemetryd, valid keys: set_tag, ! set_label, ip. ! ! list of currently supported keys follows: ! ! 'set_tag' SET: tag assigned to a matching packet, flow or sample; ! tag can be also defined auto-increasing, ie. ++; ! its use is mutually exclusive to set_tag2 and set_label ! within the same rule. The resulting value is written to ! the 'tag' field when using memory tables and 'agent_id' ! when using a SQL plugin (unless a schema v9 is used). ! Valid tag values are in the range 1 to (2^64-1). ! 'set_tag2' SET: tag assigned to a matching packet, flow or sample; ! tag can be also defined auto-increasing, ie. ++; ! its use is mutually exclusive to set_tag and set_label ! within the same rule. The resulting value is written to ! the 'tag2' field when using memory tables and 'agent_id2' ! when using a SQL plugin (unless a schema v9 is used). ! If using a SQL plugin, read more about the 'agent_id2' ! field in the 'sql/README.agent_id2' document. Valid tag ! values are in the range 1 to (2^64-1). ! 'set_label' SET: string label assigned to a matching packet, flow ! or sample; its use is mutually exclusive to tags within ! the same rule. The resulting value is written to the ! 'label' field. If pre_tag_label_encode_as_map is set to ! true in the config, the '%' character is used to delimit ! key and value, ie. "set_label=key%value". ! 'set_tos' SET: Matching packets are set their 'tos' primitive to ! the specified value. Currently valid only in nfacctd. If ! collecting ingress NetFlow at both trusted and untrusted ! borders, e.g., this is useful to selectively override ToS ! values read only at untrusted ones. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses; not specifying an 'ip' clause would ! match both all IPv4 and IPv6 addresses, in which case ! two objects per map entry will be allocated (corollary: ! maps_entries should be set to at least twice the amount ! of entries in the map). ! 'in' MATCH: Input interface. In NFv9/IPFIX this is compared ! against IE #10 and, if not existing, against IE #252. ! 'out' MATCH: Output interface. In NFv9/IPFIX this is compared ! against IE #14 and, if not existing, against IE #253. ! 'engine_type' MATCH: in NFv5 this is compared against the engine_type ! header field. Provides uniqueness with respect to the ! routing engine on the exporting device. ! 'engine_id' MATCH: in NFv5 this is compared against the engine_id ! header field; this provides uniqueness with respect to the ! particular line card on the exporting device. In NFv9/IPFIX ! it's compared against the source_id header field. ! 'source_id' MATCH: In NFv9/IPFIX it's compared against the source_id ! header field. This is an alias to engine_id. ! 'flowset_id' MATCH: In NFv9/IPFIX this is compared against the flowset ! ID field of the flowset header. ! 'nexthop' MATCH: IPv4/IPv6 address of the next-hop router. In NFv9/ ! IPFIX this is compared against IE #15. ! 'bgp_nexthop' MATCH: IPv4/IPv6 address of the next-hop BGP router. In ! MPLS-enabled networks this can be also matched against top ! label address where available (ie. egress NFv9/IPFIX ! exports). In NFv9/IPFIX this is compared against IE #18 ! for IPv4 and IE #62 for IPv6. ! 'filter' MATCH: incoming packets are mateched against the supplied ! filter expression (expected in libpcap syntax); the filter ! needs to be enclosed in quotes ('). ! 'agent_id' MATCH: in sFlow v5 it's compared against the subAgentId ! field. sFlow v2/v4 do not carry such field, hence it does ! not apply. ! 'sample_type' MATCH: in sFlow v2/v4/v5 this is compared against the ! sample type field. Expected in : ! notation. In NetFlow/IPIX three keywords are supported: ! "flow" to match any flow traffic data, "flow-ipv4" and ! "flow-ipv6" to match respectively only IPv4 and IPv6 flow ! traffic data, "flow-mpls-ipv4" and "flow-mpls-ipv6" to ! match respectively only MPLS-labelled IPv4 and IPv6 flow ! traffic data, "event" to match templates suitable to flag ! events and "option" to denote NetFlow/IPFIX option records ! data. ! 'is_bi_flow' MATCH: in NetFlow/IPFIX this checks the presence of both ! initiatorOctets and responderOctets in a flow to infer ! that it is a bi-directional flow. If set to 'true' this ! does match bi-flows, if set to 'false' it does match non ! bi-flows. ! 'is_nel' MATCH: in NetFlow/IPFIX this checks the presence of the ! natEvent field (230) to infer that this is NEL kind data. ! If set to 'true' this does match NSEL, if set to 'false' ! it does match non NEL. ! 'is_nsel' MATCH: in NetFlow/IPFIX this checks the presence of the ! firewallEvent field (233) to infer that this is NSEL kind ! of data. If set to 'true' this does match NSEL, if set to ! 'false' it does match non NSEL. ! 'direction' MATCH: expected values are 0 (ingress direction) or 1 ! (egress direction). In NFv9/IPFIX this is compared ! against the direction (61) field; in sFlow v2/v4/v5 this ! returns a positive match if: 1) source_id equals to input ! interface and this 'direction' key is set to '0' or 2) ! source_id equals to output interface and this 'direction' ! key is set to '1'. ! 'src_as' MATCH: source Autonomous System Number. In pmacctd, if ! the BGP daemon is not enabled it works only against a ! Networks map (see 'networks_file' directive); in nfacctd ! and sfacctd it works against a Networks Map, the source ! ASN field in either sFlow or NetFlow datagrams. Since ! 0.12, this can be compared against the corresponding BGP ! RIB of the exporting device ('bgp_daemon' configuration ! directive). ! 'dst_as' MATCH: destination Autonomous System Number. Same 'src_as' ! remarks hold here. Please read them above. ! 'peer_src_as' MATCH: peering source Autonomous System Number. This is ! compared against the source of info configured in ! bgp_peer_src_as_type. ! 'peer_dst_as' MATCH: peering destination Autonomous System Number. Same ! 'peer_src_as' remarks hold here. Please read them above. ! 'src_local_pref' MATCH: source IP prefix BGP Local Preference attribute. ! This is compared against the source of info configured in ! bgp_src_local_pref_type. ! 'local_pref' MATCH: destination IP prefix BGP Local Preference attribute. ! This is compared against the BGP RIB of the exporting ! device. ! 'src_roa' MATCH: source IP prefix RPKI/ROA status. This is compared ! against the BGP RIB of the exporting device. ! 'dst_roa' MATCH: destination IP prefix RPKI/ROA status. This is ! compared against the BGP RIB of the exporting device. ! 'src_comms' MATCH: Destination IP prefix BGP standard communities; ! multiple elements, up to 16, can be supplied, comma- ! separated (no spaces allowed); the check is successful ! if any of the communities is matched. This is compared ! against the source of info configured in ! bgp_src_std_comm_type. ! 'comms' MATCH: Destination IP prefix BGP standard communities; ! multiple elements, up to 16, can be supplied, comma- ! separated (no spaces allowed); the check is successful ! if any of the communities is matched. This is compared ! against the BGP RIB of the exporting device. See examples ! below. ! 'mpls_vpn_rd' MATCH: Destination IP prefix BGP-signalled MPLS L3 VPN ! Route Distinguisher (RD) value. Encoding types #0, #1 ! and #2 are supported as per rfc4364. See example below. ! 'mpls_pw_id' MATCH: Signalled MPLS L2 VPNs Pseudowire ID. In NetFlow ! v9/IPFIX this is compared against IE #249; in sFlow v5 ! this is compared against vll_vc_id field, extended MPLS ! VC object. ! 'src_mac' MATCH: In NFv9/IPFIX this is compared against IE #56, ! in sFlow against source MAC address field part of the ! Extended Switch object. ! 'dst_mac' MATCH: In NFv9/IPFIX this is compared against IE #57, ! in sFlow against destination MAC address field part of ! the Extended Switch object. ! 'vlan' MATCH: In NFv9/IPFIX this is compared against IE #58 and, ! if not existing, against IE #242, in sFlow against in/out ! VLAN ID fields part of the Extended Switch object. ! 'cvlan' MATCH: In NFv9/IPFIX this is compared against IE #245. ! 'src_net' MATCH: Source IP address field in NeFlow v5 and sFlow. ! In NFv9/IPFIX this is compared against IE #27 or #44. ! 'dst_net' MATCH: Destination IP address field in NetFlow v5 and ! sFlow. In NFv9/IPFIX this is compared against IE #28 or ! IE #45. ! 'is_multicast' MATCH: in NFv9/IPFIX this is compared against IE #57, ! in sFlow against destination MAC address field part of ! the Extended Switch object. If set to 'true' this does ! match MAC multicast addresses, if set to 'false' it won't ! match them. To match or exclude IPv4/IPv6 multicast ! addresses please use 'dst_net'. ! 'fwd_status' MATCH: In NFv9/IPFIX this is compared against IE #89; see ! https://www.iana.org/assignments/ipfix/ipfix.xhtml for ! the specific semantics of the field and some examples. ! 'label' SET: Mark the rule with label's value. Labels don't need ! to be unique: when jumping, the first matching label wins. ! Label value 'next' is reserved for internal use and ! hence must not be used in a map. Doing otherwise might ! give unexpected results. ! 'jeq' SET: Jump on EQual. Jumps to the supplied label in case ! of rule match. Jumps are Only forward. Label "next" is ! reserved and causes to go to the next rule, if any. ! 'stack' SET: Currently 'sum' (A + B) and 'or' (A | B) operators ! are supported. This key makes sense only if JEQs are in ! use. When matching, accumulate tags, using the specified ! operator/function. By setting 'stack=sum', the resulting ! tag would be: =. ! ! ! Examples: ! ! Some basic examples applicable to NetFlow, IPFIX and sFlow. ! set_tag=1 ip=192.168.2.1 in=4 set_tag=10 ip=192.168.1.1 in=5 out=3 set_tag=11 ip=192.168.1.1 in=3 out=5 set_tag=12 ip=192.168.1.1 in=3 set_tag=13 ip=192.168.1.1 nexthop=10.0.0.254 set_tag=14 ip=192.168.1.1 engine_type=1 engine_set_tag=0 set_tag=15 ip=192.168.1.1 in=3 filter='src net 192.168.0.0/24' ! ! The following rule instructs to increase the tag value at every pre_tag_map run, ! starting from a given floor value (in the example below, '1'). Since tags are ! part of the aggregate key, this causes no two objects to be further aggregated ! together. ! set_tag=1++ ip=0.0.0.0/0 ! ! The following rule sets labels on matching IP ranges non-aligned with subnets, ! ie. issue 'labelA' for the IP range 192.168.0.1 - 192.168.0.100 and 'labelB' ! for the IP range 192.168.0.101 - 192.168.0.200 (note: ip[12:4] is the source ! IP address and ip[16:4] is the destination one. ! set_label=LabelA filter='((ip[12:4] >= 0xC0A80001) and (ip[12:4] <= 0xC0A80064)) or ((ip[16:4] >= 0xC0A80001) and (ip[16:4] <= 0xC0A80064))' set_label=LabelB filter='((ip[12:4] >= 0xC0A80065) and (ip[12:4] <= 0xC0A800C8)) or ((ip[16:4] >= 0xC0A80065) and (ip[16:4] <= 0xC0A800C8))' ! ! A few examples sFlow-related. The format of the rules is the same of 'nfacctd' ones ! but some keys don't apply to it. ! set_tag=30 ip=192.168.1.1 set_tag=31 ip=192.168.1.1 out=50 set_tag=32 ip=192.168.1.1 out=50 agent_id=100 ! ! === JEQ example #1: ! - 'set_tag' used to store input interface tags ! - 'set_tag2' used to store output interface tags ! set_tag=1000 ip=192.168.1.1 in=1 jeq=eval_out set_tag=1001 ip=192.168.1.1 in=2 jeq=eval_out set_tag=1002 ip=192.168.1.1 in=3 jeq=eval_out ! ... further INs set_tag2=1000 ip=192.168.1.1 out=1 label=eval_out set_tag2=1001 ip=192.168.1.1 out=2 set_tag2=1002 ip=192.168.1.1 out=3 ! ... further OUTs ! ! === ! ! === JEQ example #2: ! - 'id' structured hierarchically to store both input and output interface tags ! set_tag=11000 ip=192.168.1.1 in=1 jeq=eval_out set_tag=12000 ip=192.168.1.1 in=2 jeq=eval_out set_tag=13000 ip=192.168.1.1 in=3 jeq=eval_out ! ... further INs set_tag=100 ip=192.168.1.1 out=1 label=eval_out stack=sum set_tag=101 ip=192.168.1.1 out=2 stack=sum set_tag=102 ip=192.168.1.1 out=3 stack=sum ! ... further OUTs ! ! === ! ! === BGP standard communities example #1 ! - check is successful if matches either 65000:1234 or 65000:2345 ! set_tag=100 ip=192.168.1.1 comms=65000:1234,65000:2345 ! ! === ! ! === BGP standard communities example #2 ! - a series of checks can be piled up in order to mimic match-all ! - underlying logics is: ! > tag=200 is considered a successful check; ! > tag=0 or tag=100 is considered unsuccessful ! set_tag=100 ip=192.168.1.1 comms=65000:1234 label=65000:1234 jeq=65000:2345 set_tag=100 ip=192.168.1.1 comms=65000:2345 label=65000:2345 jeq=65000:3456 ! ... further set_tag=100 set_tag=200 ip=192.168.1.1 comms=65000:3456 label=65000:3456 ! ! === ! ! === BGP/MPLS VPN Route Distinguisher (RD) example ! - check is successful if matches encoding type #0 with value 65512:1 ! set_tag=100 ip=192.168.1.1 mpls_vpn_rd=0:65512:1 ! ! === ! ! === sfprobe/nfprobe: determining semi-dynamically direction and ifindex ! - Two steps approach: ! > determine direction first (1=in, 2=out) ! > then short circuit it to return an ifindex value ! - Configuration would look like the following fragment: ! ... ! nfprobe_direction: tag ! nfprobe_ifindex: tag2 ! ... ! set_tag=1 filter='ether dst 00:11:22:33:44:55' jeq=fivefive set_tag=1 filter='ether dst 00:11:22:33:44:66' jeq=sixsix set_tag=1 filter='ether dst 00:11:22:33:44:77' jeq=sevenseven set_tag=2 filter='ether src 00:11:22:33:44:55' jeq=fivefive set_tag=2 filter='ether src 00:11:22:33:44:66' jeq=sixsix set_tag=2 filter='ether src 00:11:22:33:44:77' jeq=sevenseven ! set_tag2=5 label=fivefive set_tag2=6 label=sixsix set_tag2=7 label=sevenseven ! ! === ! ! === Basic set_label example ! Tag as "blabla,blabla2" NetFlow/sFlow data received from all exporters. ! If, ie. as a result of JEQ's in a pre_tag_map, multiple 'set_label' are ! matched, then labels are appended and separated by a comma (warning: if ! using print plugin with CSV output, the file separator should be changed ! with print_output_separator) ! set_label=blabla ip=0.0.0.0/0 label=blabla jeq=blabla2 set_label=blabla2 ip=0.0.0.0/0 label=blabla2 ! ! ! pre_tag_label_filter[xxx]: -null ! pre_tag_label_filter[yyy]: blabla ! pre_tag_label_filter[zzz]: blabla, blabla2 ! ! === pmacct-1.7.8/examples/avro/0000755000175000017500000000000014354105275014577 5ustar paolopaolopmacct-1.7.8/examples/avro/avro_file_decoder.py0000755000175000017500000000422014354105275020605 0ustar paolopaolo#!/usr/bin/env python # # If missing 'avro' read how to download it at: # https://avro.apache.org/docs/1.8.1/gettingstartedpython.html # # 'avro' package is deemed slow. For production scenarios, do consider # implementing this script using the 'fastavro' Python package that is # documented here: https://fastavro.readthedocs.io/en/latest/ import sys, os, getopt, io from avro.datafile import DataFileReader from avro.io import DatumReader import avro.schema def usage(tool): print "" print "Usage: %s [Args]" % tool print "" print "Mandatory Args:" print " -i, --input-file".ljust(25) + "Input file in Avro format" print " -s, --schema".ljust(25) + "Schema to decode input file (if not included)" print "" print "Optional Args:" print " -h, --help".ljust(25) + "Print this help" def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hi:s:", ["help", "input-file=", "schema="]) except getopt.GetoptError as err: # print help information and exit: print str(err) # will print something like "option -a not recognized" usage(sys.argv[0]) sys.exit(2) avro_file = None avro_schema_file = None required_cl = 0 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) sys.exit() elif o in ("-i", "--input-file"): required_cl += 1 avro_file = a elif o in ("-s", "--schema"): avro_schema_file = a else: assert False, "unhandled option" if (required_cl < 1): print "ERROR: Missing required argument" usage(sys.argv[0]) sys.exit(1) if not avro_schema_file: reader = DataFileReader(open(avro_file, "r"), DatumReader()) for datum in reader: print datum reader.close() else: reader_schema = open(avro_schema_file, "r") avro_schema = reader_schema.read() reader_schema.close() parsed_avro_schema = avro.schema.parse(avro_schema) with open(avro_file, "rb") as reader_data: inputio = io.BytesIO(reader_data.read()) decoder = avro.io.BinaryDecoder(inputio) reader = avro.io.DatumReader(parsed_avro_schema) while inputio.tell() < len(inputio.getvalue()): avro_datum = reader.read(decoder) print avro_datum reader_data.close() if __name__ == "__main__": main() pmacct-1.7.8/examples/lpref.map.example0000644000175000017500000000376614354105275017105 0ustar paolopaolo! ! bgp_src_local_pref_map: BGP source local preferecence map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! nfacctd, sfacctd: valid keys: id, ip, in, bgp_nexthop, src_mac. ! ! list of currently supported keys follow: ! ! 'id' ID value to assign to a matching packet or flow. Other ! than hard-coded local preference values, this field also ! accepts the 'bgp' keyword which triggers a BGP lookup ! and returns its result: useful to handle exceptions. ! 'ip' MATCH: in nfacctd this is compared against the source ! IP address of the device originating NetFlow packets; ! in sfacctd this is compared against the AgentId field ! of received sFlow samples. Expected argument are an IP ! address or prefix (ie. XXX.XXX.XXX.XXX/NN). 0.0.0.0/0 ! would match all IPv4 addresses; ::/0 would match all ! IPv6 addresses. ! 'in' Input interface. ! 'bgp_nexthop' BGP next-hop of the flow source IP address (RPF-like). ! This value is compared against the corresponding BGP ! RIB of the exporting device. ! 'peer_dst_as' First AS hop within the AS-PATH of the source IP address ! (RPF-like). This value is compared against the BGP RIB ! of the exporting device (see 'bgp_daemon' configuration ! directive). ! 'src_mac' Source MAC address of the flow. Requires NetFlow v9, ! IPFIX or sFlow. ! ! A few examples follow. Let's define: LP=100 identifies customers, LP=80 identifies peers ! and LP=50 identifies IP transit. ! ! Customer connected to router with IP address 192.168.2.1, SNMP ifIndex 7 ! id=100 ip=192.168.2.1 in=7 ! A way to model multiple services, ie. IP transit and peering, off the same interface. ! Realistically services should be delivered off different sub-interfaces, but still ... ! id=50 ip=192.168.1.1 in=7 bgp_nexthop=10.10.10.1 id=80 ip=192.168.1.1 in=7 bgp_nexthop=10.10.10.2 pmacct-1.7.8/examples/misc/0000755000175000017500000000000014354105275014563 5ustar paolopaolopmacct-1.7.8/examples/misc/mrtg.conf.example0000644000175000017500000000156314354105275020042 0ustar paolopaolo# This is a trivial and basic config for use pmacct to export statistics # to mrtg. If you need more informations of the few commands shown below # refer to the online referenge guide at the official MRTG web page: # http://people.ee.ethz.ch/~oetiker/webtools/mrtg/reference.html # Some general definition WorkDir: /var/www/html/monitor Options[_]: growright, bits # Target specific definitions Target[ezwf]: `./mrtg-example.sh` SetEnv[ezwf]: MRTG_INT_IP="10.0.0.1" MRTG_INT_DESCR="yourip.yourdomain.com" MaxBytes[ezwf]: 1250000 LegendI[ezwf]: Title[ezwf]: yourip.yourdomain.com PageTop[ezwf]:

yourip.yourdomain.com

System: yourip.yourdomain.com in
Maintainer:
Ip: 10.0.0.1 (yourip.yourdomain.com)
# ... # Put here more targets and their definitions pmacct-1.7.8/examples/misc/rrdtool-example.sh0000755000175000017500000000133614354105275020243 0ustar paolopaolo#!/bin/sh # This file aims to be a trivial example on how to interface pmacctd/nfacctd memory # plugin to RRDtool (people.ee.ethz.ch/~oetiker/webtools/rrdtool/) to make graphs # from data gathered from the network. # # This script has to be invoked timely from crontab: # */5 * * * * /usr/local/bin/rrdtool-example.sh # # The following command feeds a two DS (Data Sources) RRD with incoming and outcoming # traffic (in bytes) between two hosts; the '-r' switch makes counters 'absolute': they # are zeroed after each query. /usr/local/bin/rrdtool update /tmp/test.rrd N:`/usr/local/bin/pmacct -c src_host,dst_host -N 192.168.0.133,192.168.0.100 -r`:`/usr/local/bin/pmacct -c src_host,dst_host -N 192.168.0.100,192.168.0.133 -r` pmacct-1.7.8/examples/misc/gnuplot-example.sh0000755000175000017500000000251014354105275020241 0ustar paolopaolo#!/bin/bash # This file aims to be a trivial example on how to interface pmacctd/nfacctd memory # plugin to GNUPlot (http://www.gnuplot.info) to make graphs from data gathered from # the network. # # The following does the following assumptions (but these could be easily changed): # # - You are using a PostgreSQL database with two tables: 'acct_in' for incoming traffic # and 'acct_out' for outcoming traffic # - You are aggregating traffic for 'src_host' in 'acct_out' and for 'dst_host' in # 'acct_in' # - You have enabled 'sql_history' to generate timestamps in 'stamp_inserted' field; # because the variable $step is 3600, the assumption is: 'sql_history: 1h' # # After having populated the files 'in.txt' and 'out.txt' run gnuplot the following way: # # > gnuplot gnuplot.script.example > plot.png # PGPASSWORD="arealsmartpwd" export PGPASSWORD j=0 step=3600 output_in="in.txt" output_out="out.txt" rm -rf $output_in rm -rf $output_out RESULT_OUT=`psql -U pmacct -t -c "SELECT SUM(bytes) FROM acct_out WHERE ip_src = '192.168.0.133' GROUP BY stamp_inserted;"` RESULT_IN=`psql -U pmacct -t -c "SELECT SUM(bytes) FROM acct_in WHERE ip_dst = '192.168.0.133' GROUP BY stamp_inserted;"` j=0 for i in $RESULT_IN do echo $j $i >> $output_in let j+=$step done j=0 for i in $RESULT_OUT do echo $j $i >> $output_out let j+=$step done pmacct-1.7.8/examples/misc/mrtg-example.sh0000755000175000017500000000130414354105275017522 0ustar paolopaolo#!/bin/sh # This file aims to be a trivial example on how to interface pmacctd/nfacctd memory # plugin to MRTG (people.ee.ethz.ch/~oetiker/webtools/mrtg/) to make graphs from # data gathered from the network. # # This script has to be invoked timely from crontab: # */5 * * * * /usr/local/bin/mrtg-example.sh # # The following command collects incoming and outcoming traffic (in bytes) between # two hosts; the '-r' switch makes counters 'absolute': they are zeroed after each # query. unset IN unset OUT IN=`/usr/local/bin/pmacct -c src_host,dst_host -N 192.168.0.100,192.168.0.133 -r` OUT=`/usr/local/bin/pmacct -c src_host,dst_host -N 192.168.0.133,192.168.0.100 -r` echo $IN echo $OUT echo 0 echo 0 pmacct-1.7.8/examples/misc/gnuplot.script.example0000644000175000017500000000047314354105275021137 0ustar paolopaoloset term png small color set data style lines set grid set yrange [ 0 : ] set title "Traffic in last XX hours" set xlabel "hours" set ylabel "kBytes" set multiplot plot "in.txt" using ($1/3600):($2/1000) title "IN Traffic" with linespoints, "out.txt" using ($1/3600):($2/1000) title "OUT Traffic" with linespoints pmacct-1.7.8/examples/custom/0000755000175000017500000000000014354105415015136 5ustar paolopaolopmacct-1.7.8/examples/custom/libcustom.c0000644000175000017500000000440614354105275017313 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libcustom.h" FILE *global_file = 0; char global_error_buffer[255]; #ifdef __cplusplus extern "C" { #endif /* NOTE: This is just a simple demonstration of writing to a file, you can use this to process data in any way you want to i.e: store it to redis/mongo write it to a socket etc. */ int plugin_init(const char *configFile) { // readconfig file specified by print_output_custom_cfg_file return 0; } int plugin_destroy() { return 0; } int output_init(const char *date, int append) { global_file = fopen("/tmp/outputfile.txt", "wt"); if (!global_file) { strcpy(global_error_buffer, "this is my error string"); return -1; } return 0; } int print(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int32_t tcp_flags, struct timeval *basetime, struct pkt_stitching *stitch) { if (global_file) { u_int8_t proto = pbase->proto; fprintf(global_file, "protocol %d\n", proto); return 0; } return -1; } int output_flush() { return 0; } int output_close() { fclose(global_file); return 0; } char *get_error_text() { return global_error_buffer; } #ifdef __cplusplus } #endif pmacct-1.7.8/examples/custom/Makefile.in0000644000175000017500000005040714354105415017211 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = examples/custom ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcustom_la_LIBADD = am_libcustom_la_OBJECTS = libcustom_la-libcustom.lo libcustom_la_OBJECTS = $(am_libcustom_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libcustom_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcustom_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libcustom_la-libcustom.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcustom_la_SOURCES) DIST_SOURCES = $(libcustom_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) libcustom_la_SOURCES = libcustom.c noinst_LTLIBRARIES = libcustom.la libcustom_la_CFLAGS = -I$(srcdir)/../../src $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/custom/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign examples/custom/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcustom.la: $(libcustom_la_OBJECTS) $(libcustom_la_DEPENDENCIES) $(EXTRA_libcustom_la_DEPENDENCIES) $(AM_V_CCLD)$(libcustom_la_LINK) $(libcustom_la_OBJECTS) $(libcustom_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcustom_la-libcustom.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libcustom_la-libcustom.lo: libcustom.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcustom_la_CFLAGS) $(CFLAGS) -MT libcustom_la-libcustom.lo -MD -MP -MF $(DEPDIR)/libcustom_la-libcustom.Tpo -c -o libcustom_la-libcustom.lo `test -f 'libcustom.c' || echo '$(srcdir)/'`libcustom.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcustom_la-libcustom.Tpo $(DEPDIR)/libcustom_la-libcustom.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcustom.c' object='libcustom_la-libcustom.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcustom_la_CFLAGS) $(CFLAGS) -c -o libcustom_la-libcustom.lo `test -f 'libcustom.c' || echo '$(srcdir)/'`libcustom.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libcustom_la-libcustom.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcustom_la-libcustom.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/examples/custom/libcustom.h0000644000175000017500000000335614354105275017323 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "pmacct.h" #include "addr.h" #include "pmacct-data.h" #include "plugin_cmn_custom.h" #include "plugin_common.h" #include "bgp/bgp.h" #if defined(WITH_NDPI) #include "ndpi/ndpi.h" #endif #ifdef __cplusplus extern "C" { #endif int plugin_init(const char *configFile); int plugin_destroy(); int output_init(const char *date, int append); int print(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int32_t tcp_flags, struct timeval *basetime, struct pkt_stitching *stitch); int output_flush(); int output_close(); char *get_error_text(); #ifdef __cplusplus } #endif pmacct-1.7.8/examples/custom/Makefile.am0000644000175000017500000000023414354105275017175 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) libcustom_la_SOURCES = libcustom.c noinst_LTLIBRARIES=libcustom.la libcustom_la_CFLAGS = -I$(srcdir)/../../src $(AM_CFLAGS) pmacct-1.7.8/examples/custom/nfacctd-custom.conf.example0000644000175000017500000000113314354105275022353 0ustar paolopaolo! ! nfacctd custom print plugin configuration example ! ! Did you know CONFIG-KEYS contains the detailed list of all configuration keys supported ? ! ! General configs ! ! debug: true daemonize: false ! ! NetFlow/IPFIX daemon configs ! ! nfacctd_port: 5678 ! nfacctd_time_secs: true nfacctd_time_new: true ! ! Plugins definitions ! plugins: custom[foo] !print_output_custom_lib: /path/to/your/library/your_backend_library.so !print_output_custom_cfg_file: /path/configuration/your_configuration_file.ini ! ! ! 'foo' plugin configuration ! aggregate[foo]: src_host, dst_host, src_port, dst_port, proto pmacct-1.7.8/examples/bgp_xconnects.map.example0000644000175000017500000000154414354105275020621 0ustar paolopaolo! ! bgp_daemon_xconnect_map: BGP sessions xconnect map ! ! File syntax is key-based. Read full syntax rules in 'pretag.map.example' in ! this same directory. ! ! list of currently supported keys follow: ! ! 'bgp_dst' SET: IPv4/IPv6 address and port of the BGP collector ! to cross-connect incoming (bgp_src) BGP session to. ! 'bgp_src' MATCH: compared against the IPv4/IPv6 address (not BGP ! Router ID) of an incoming BGP session from a BGP peer. ! ! Examples: ! ! Cross-connect the incoming BGP session from 192.168.0.1 to 10.0.0.1:17901 ! and the session from 192.168.0.2 to 10.0.0.1:17902. ! bgp_dst=10.0.0.1:17901 bgp_src=192.168.0.1 bgp_dst=10.0.0.1:17902 bgp_src=192.168.0.2 ! ! Cross-connect incoming BGP sessions from IP addresses belonging to the ! 192.168.10.0/24 subnet to 10.0.0.1:17910. ! bgp_dst=10.0.0.1:17910 bgp_src=192.168.10.0/24 pmacct-1.7.8/INSTALL0000644000175000017500000001673614354105275013060 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI : IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2021 by Paolo Lucente QUICK INSTALLATION: 1) tar xvfz -x.y.z.tar.gz (*) 2) cd -x.y.z 3) ./configure (./configure --help for help) 4) make 5) make install (you must be root if you want to install in default prefix) Read accepted options with " -h" and run with " [options]". (*) x.y.z is the release version. For compiling from GitHub code, please see the README.md file. For more compiling instrutions, examples, command-lines, quickstart guides please see the QUICKSTART guide. BASIC INSTALLATION: These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. COMPILERS AND OPTIONS: Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure COMPILING FOR MULTIPLE ARCHITECTURES: You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. INSTALLATION NAMES: By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. SPECIFYING THE SYSTEM TYPE: There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. SHARING DEFAULTS: If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. OPERATION CONTROLS: `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. pmacct-1.7.8/QUICKSTART0000644000175000017500000040670714354105275013445 0ustar paolopaolopmacct [IP traffic accounting : BGP : BMP : RPKI : IGP : Streaming Telemetry] pmacct is Copyright (C) 2003-2022 by Paolo Lucente TABLE OF CONTENTS: I. Daemons and plugins included with pmacct distribution II. Configuring pmacct for compilation and installing III. Brief SQL (MySQL, PostgreSQL, SQLite 3.x) setup examples IV. Running the libpcap-based daemon (pmacctd) V. Running the NetFlow/IPFIX and sFlow daemons (nfacctd/sfacctd) VI. Running the NFLOG-based daemon (uacctd) VII. Running the pmacct IMT client (pmacct) VIII. Running the RabbitMQ/AMQP plugin IX. Running the Kafka plugin X. Internal buffering and queueing XI. Quickstart guide to packet/flow classification XII. Quickstart guide to setup a NetFlow/IPFIX agent/probe XIII. Quickstart guide to setup a sFlow agent/probe XIV. Quickstart guide to setup the BGP daemon XV. Quickstart guide to setup a NetFlow/IPFIX/sFlow replicator XVI. Quickstart guide to setup the IS-IS daemon XVII. Quickstart guide to setup the BMP daemon XVIII. Quickstart guide to setup Streaming Telemetry collection XIX. Running the print plugin to write to flat-files XX. Quickstart guide to setup GeoIP lookups XXI. Using pmacct as traffic/event logger XXII. Connecting pmacct to a Redis cache XXIII. Miscellaneous notes and troubleshooting tips I. Daemons and plugins included with pmacct distribution All traffic accounting daemons can print statistics to stdout, keep them in memory tables, store persistently to open-source RDBMS (MySQL, PostgreSQL, Sqlite 3) or to noSQL databates (ie. BerkeleyDB) and to flat-files, and publish to AMQP and Kafka brokers (typically to insert in ElasticSearch, InfluxDB, Druid, ClickHouse and, more in general, all backends which are not natively supported by pmacct). BGP, BMP and Streaming Telemetry daemons can publish control and infrastructure planes to AMQP and Kafka brokers. This is a list of the daemons included in the pmacct distribution: pmacctd libpcap-based accounting daemon: it captures packets from one or multiple interfaces it is bound to. Other than acting as a collector, this daemon can also export statistics via NetFlow, IPFIX and sFlow protocols. nfacctd NetFlow/IPFIX accounting daemon: it listens for NetFlow v5/v9 and IPFIX packets on one or more interfaces (IPv4 and IPv6). Other than acting as a collector, this daemon can also replicate to 3rd party collectors. sfacctd sFlow accounting daemon; it listens for sFlow packets v2, v4 and v5 on one or more interfaces (both IPv4 and IPv6). Other than acting as a collector, this daemon can also replicate to 3rd party collectors. uacctd Linux Netlink NFLOG accounting daemon; it captures packets by leveraging a NFLOG multicast group - and works only on Linux. Other than acting as a collector, this daemon can also export statistics via NetFlow, IPFIX and sFlow protocols. pmtelemetryd Standalone Streaming Telemetry collector daemon; listens for telemetry data binding to a TCP or UDP port and logs real-time and/or dumps at regular time-intervals to configured backends. pmbgpd Standalone BGP collector daemon; acts as a passive iBGP or eBGP neighbor and maintains per-peer RIBs; can log real-time and/or dump at regular time-intervals BGP data to configured backends. pmbmpd Standalone BMP collector daemon; can log real-time and/or dump at regular time-intervals BMP/BGP data to configured backends. pmacct commandline pmacct client; it allows to retrieve data from a memory table plugin; it can perform queries over data or do bulk data retrieval. Output is formatted, CSV or JSON format. suitable for data injection in 3rd party tools like RRDtool, Gnuplot or SNMP server among the others. Given its open and pluggable architecture, pmacct is easily extensible with new plugins. Here is a list of traffic accounting plugins included in the official pmacct distribution: memory data is stored in a memory table and can be fetched via the pmacct command-line client tool, 'pmacct'. This plugin also implements a push model and allows easily to inject data into 3rd party tools. The plugin is recommended for prototyping and proof-of-concept (without mass traffic generation) and smaller-scale / home production environments and is compiled in by default. mysql a working MySQL/MariaDB installation can be used for data storage. This plugin can be compiled using the --enable-mysql switch. pgsql a working PostgreSQL installation can be used for data storage. This plugin can be compiled using the --enable-pgsql switch. sqlite3 a working SQLite 3.x or BerkeleyDB 5.x (compiled in with the SQLite API) installation can be used for data storage. This plugin can be compiled using the --enable-sqlite3 switch. print data is printed at regular intervals to flat-files or standard output in tab-spaced, CSV and JSON formats. This plugin is compiled in by default. amqp data is sent to a RabbitMQ broker, running AMQP protocol, for delivery to consumer applications or tools. Popular consumers are ElasticSearch, InfluxDB, Druid and ClickHouse. This plugin can be compiled using the --enable-rabbitmq switch. kafka data is sent to a Kafka broker for delivery to consumer applications or tools. Popular consumers are ElasticSearch, InfluxDB, Druid and ClickHouse. This plugin can be compiled using the --enable-kafka switch. tee applies to nfacctd and sfacctd daemons only. It's a featureful packet replicator for NetFlow/IPFIX/sFlow data. This plugin is compiled in by default. nfprobe applies to pmacctd and uacctd daemons only. Exports collected data via NetFlow v5/v9 or IPFIX. This plugin is compiled in by default. sfprobe applies to pmacctd and uacctd daemons only. Exports collected data via sFlow v5. This plugin is compiled in by default. II. Configuring pmacct for compilation and installing The simplest way to configure the package for compilation is to download the latest stable released tarball from http://www.pmacct.net/ and let the configure script to probe default headers and libraries for you. The only dependency that pmacct brings is libpcap library and headers: libpcap-dev on Debian/Ubuntu, libpcap-devel on CentOS/RHEL (note: this may need enabling extra yum repos!) or (self-compiled) equivalent must be installed on the system. Then, a first round of guessing is done via pkg-config then, for some libraries, "typical" default locations are checked, ie. /usr/local/lib. Switches one likely wants enabled are already set so, ie. 64 bits counters and multi-threading (pre- requisite for the BGP, BMP, and IGP daemon codes); the full list of switches enabled by default are marked as 'default: yes' in the "./configure --help" output. SQL plugins, AMQP and Kafka support are all disabled by default instead. A few examples will follow; to get the list of available switches, you can use the following command-line: shell> ./configure --help Examples on how to enable support for (1) MySQL, (2) PostgreSQL and (3) SQLite: (1) libmysqlclient-dev package or (self-compiled) equivalent being installed: shell> ./configure --enable-mysql (2) libpq-dev package or (self-compiled) equivalent being installed: shell> ./configure --enable-pgsql (3) libsqlite3-dev package or (self-compiled) equivalent being installed: shell> ./configure --enable-sqlite3 If cloning the GitHub repository ( https://github.com/pmacct/pmacct ) instead, the configure script has to be generated, resulting in one extra step than the process just described. Please refer to the Building section of the README.md document for instruction about cloning the repo, generate the configure script along with the required installed packages. Then compile and install simply typing: shell> make; make install Should you want, for example, to compile pmacct with PostgreSQL support and have installed PostgreSQL in /usr/local/postgresql and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export PGSQL_LIBS="-L/usr/local/postgresql/lib -lpq" shell> export PGSQL_CFLAGS="-I/usr/local/postgresql/include" shell> ./configure --enable-pgsql If the library does actually support pkg-config but the .pc pkg-config file is in some non-standard location, this can be supplied as follows: shell> export PKG_CONFIG_PATH=/usr/local/postgresql/pkgconfig/ shell> ./configure --enable-pgsql Special case is to compile pmacct with MySQL support but MySQL is installed in some non-default location. MySQL brings the mysql_config tool that works similarly to pkg-config. Make sure the tool is on the path so that it can be executed by the configure script, ie.: shell> export PATH=$PATH:/usr/local/mysql/bin shell> ./configure --enable-mysql By default all tools - flow, BGP, BMP and Streaming Telemetry - are compiled. Specific tool sets can be disabled. For example, to compile only flow tools (ie. no pmbgpd, pmbmpd, pmtelemetryd) the following command-line can be used: shell> ./configure --disable-bgp-bins --disable-bmp-bins --disable-st-bins Once daemons are installed you can check: * Basic instrumenting of each daemon via its help page, ie.: shell> pmacctd -h * Review daemon version and build details, ie.: shell> sfacctd -V * Check supported traffic aggregation primitives and their description, ie.: shell> nfacctd -a IIa. Compiling pmacct with JSON support JSON encoding is supported via the Jansson library (http://www.digip.org/jansson/ and https://github.com/akheron/jansson); a library version >= 2.5 is required. To compile pmacct with JSON support simply do: shell> ./configure --enable-jansson However should you have installed Jansson in the /usr/local/jansson directory and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export JANSSON_LIBS="-L/usr/local/jansson/lib -ljansson" shell> export JANSSON_CFLAGS="-I/usr/local/jansson/include" shell> ./configure --enable-jansson IIb. Compiling pmacct with Apache Avro support Apache Avro encoding is supported via libavro library (http://avro.apache.org/ and https://avro.apache.org/docs/1.9.1/api/c/index.html); Avro depends on the Jansson JSON parser version 2.3 or higher so please review the previous section "Compiling pmacct with JSON support"; then, to compile pmacct with Apache Avro support simply do: shell> ./configure --enable-jansson --enable-avro However should you have installed libavro in the /usr/local/avro directory and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export AVRO_LIBS="-L/usr/local/avro/lib -lavro" shell> export AVRO_CFLAGS="-I/usr/local/avro/include" shell> ./configure --enable-kafka --enable-jansson --enable-avro IIc. Compiling pmacct against a own libpcap library Compiling against a downloaded libpcap library may be wanted for several reasons including the version packaged with the Operating System is too old, a custom libpcap library needs to be compiled (ie. with support for PF_RING) or static linking is wanted. Once libpcap is downloaded, if static linking is wanted (ideal for example for distributing pmacct without external dependencies), the library can be configured for comipiling: shell> ./configure --disable-so Which passes the compiler the '-static' knob. pmacct should be pointed to the own libpcap library when configuring for compiling: shell> ./configure --with-pcap-libs=/path/to/libpcap-x.y.z --with-pcap-includes=/path/to/libpcap-x.y.z Once pmacct is compiled, it can be confirmed that the right library was picked by doing, for example, a 'pmacctd -V' and seeing the version of libpcap matches with the supplied version. It has to be noted however that static compiling on GNU systems can yeld variable success; the recommendation is to consider containers first (look into the 'docker/' directory). A use-case for a PF_RING-enabled libpcap is that by hashing and balancing collected traffic over multiple NIC queues (ie. if using Intel X520) it is possible to scale pmacctd horizontally, with one pmacctd instance reading from one or multiple queues. The queues can be managed via the 'ethtool' tool (ie. 'ethtool -l enp1s0f0' to list, 'ethtool -L enp1s0f0 combined 16' to access 16 queues, etc.) and pmacctd can be bound to a single queue, ie. 'pmacctd -i enp1s0f0@0', or multiple ones via a pcap_interfaces_map, ie. ifname=enp1s0f0@0 ifindex=100 ifname=enp1s0f0@1 ifindex=101 ifname=enp1s0f0@2 ifindex=102 ifname=enp1s0f0@3 ifindex=103 III. Brief SQL and noSQL setup examples RDBMS require a table schema to store data. pmacct offers two options: use one of the few pre-determined table schemas available (sections IIIa, b and c) or compose a custom schema to fit your needs (section IIId). If you are blind to SQL the former approach is recommended, although it can pose scalability issues in larger deployments; if you know some SQL the latter is definitely the way to go. Scripts for setting up RDBMS are located in the 'sql/' tree of the pmacct distribution tarball. For further guidance read the relevant README files in such directory. One of the crucial concepts to deal with, when using default table schemas, is table versioning: please read more about this topic in the FAQS document (Q17). IIIa. MySQL examples shell> cd sql/ - To create v1 tables: shell> mysql -u root -p < pmacct-create-db_v1.mysql shell> mysql -u root -p < pmacct-grant-db.mysql Data will be available in 'acct' table of 'pmacct' DB. - To create v2 tables: shell> mysql -u root -p < pmacct-create-db_v2.mysql shell> mysql -u root -p < pmacct-grant-db.mysql Data will be available in 'acct_v2' table of 'pmacct' DB. ... And so on for the newer versions. IIIb. PostgreSQL examples Which user has to execute the following two scripts and how to autenticate with the PostgreSQL server depends upon your current configuration. Keep in mind that both scripts need postgres superuser permissions to execute some commands successfully: shell> cp -p *.pgsql /tmp shell> su - postgres To create v1 tables: shell> psql -d template1 -f /tmp/pmacct-create-db.pgsql shell> psql -d pmacct -f /tmp/pmacct-create-table_v1.pgsql To create v2 tables: shell> psql -d template1 -f /tmp/pmacct-create-db.pgsql shell> psql -d pmacct -f /tmp/pmacct-create-table_v2.pgsql ... And so on for the newer versions. A few tables will be created into 'pmacct' DB. 'acct' ('acct_v2' or 'acct_v3') table is the default table where data will be written when in 'typed' mode (see 'sql_data' option in CONFIG-KEYS document; default value is 'typed'); 'acct_uni' ('acct_uni_v2' or 'acct_uni_v3') is the default table where data will be written when in 'unified' mode. Since v6, PostgreSQL tables are greatly simplified: unified mode is no longer supported and an unique table ('acct_v6', for example) is created instead. IIIc. SQLite examples shell> cd sql/ - To create v1 tables: shell> sqlite3 /tmp/pmacct.db < pmacct-create-table.sqlite3 Data will be available in 'acct' table of '/tmp/pmacct.db' DB. Of course, you can change the database filename basing on your preferences. - To create v2 tables: shell> sqlite3 /tmp/pmacct.db < pmacct-create-table_v2.sqlite3 Data will be available in 'acct_v2' table of '/tmp/pmacct.db' DB. ... And so on for the newer versions. IIId. Custom SQL tables Custom tables can be built by creating your own SQL schema and indexes. This allows to mix-and-match the primitives relevant to your accounting scenario. To flag intention to build a custom table the sql_optimize_clauses directive must be set to true, ie.: sql_optimize_clauses: true sql_table: aggregate: How to build the custom schema? Let's say the aggregation method of choice (aggregate directive) is "vlan, in_iface, out_iface, etype" the table name is "acct" and the database of choice is MySQL. The SQL schema is composed of four main parts, explained below: 1) A fixed skeleton needed by pmacct logics: CREATE TABLE ( packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME ); 2) Indexing: primary key (of your choice, this is only an example) plus any additional index you may find relevant. 3) Primitives enabled in pmacct, in this specific example the ones below; should one need more/others, these can be looked up in the sql/README.mysql file in the section named "Aggregation primitives to SQL schema mapping:" : vlan INT(2) UNSIGNED NOT NULL, iface_in INT(4) UNSIGNED NOT NULL, iface_out INT(4) UNSIGNED NOT NULL, etype INT(2) UNSIGNED NOT NULL, 4) Any additional fields, ignored by pmacct, that can be of use, these can be for lookup purposes, auto-increment, etc. and can be of course also part of the indexing you might choose. Putting the pieces together, the resulting SQL schema is below along with the required statements to create the database: DROP DATABASE IF EXISTS pmacct; CREATE DATABASE pmacct; USE pmacct; DROP TABLE IF EXISTS acct; CREATE TABLE acct ( vlan INT(2) UNSIGNED NOT NULL, iface_in INT(4) UNSIGNED NOT NULL, iface_out INT(4) UNSIGNED NOT NULL, etype INT(2) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (vlan, iface_in, iface_out, etype, stamp_inserted) ); To grant default pmacct user permission to write into the database look at the file sql/pmacct-grant-db.mysql IIIe. Historical accounting Enabling historical accounting allows to aggregate data in time-bins (ie. 5 mins, hour, day, etc.) in a flexible and fully configurable way. Two timestamps are available: the 'stamp_inserted' field, representing the basetime of the time-bin, and 'stamp_updated', the last time the time-bin was updated. Following a pretty standard config fragment to slice data into nicely aligned (or rounded-off) 5 minutes time-bins: sql_history: 5m sql_history_roundoff: m IIIf. INSERTs-only UPDATE queries are expensive; this is why, even if they are supported by pmacct, a savy approach would be to cache data for longer times in memory and write them off once per time-bin (sql_history): this results into a much lighter INSERTs-only setup. This is an example based on 5 minutes time-bins: sql_refresh_time: 300 sql_history: 5m sql_history_roundoff: m sql_dont_try_update: true Note that sql_refresh_time is always expressed in seconds. An alternative approach for cases where sql_refresh_time must be kept shorter than sql_history (for example because a) of long sql_history periods, ie. hours or days, and/or because b) near real-time data feed is a requirement) is to set up a synthetic auto-increment 'id' field: it successfully prevents duplicates but comes at the expenses of GROUP BYs when querying data. IV. Running the libpcap-based daemon (pmacctd) All deamons including pmacctd can be run with commandline options, using a config file or a mix of the two. Sample configuration files are in examples/ tree. Note also that most of the new features are available only as config directives. To be aware of the existing configuration directives, please read the CONFIG-KEYS document. Show all available pmacctd commandline switches: shell> pmacctd -h Run pmacctd reading configuration from a specified file (see examples/ tree for a brief list of some commonly useed keys; divert your eyes to CONFIG-KEYS for the full list). This example applies to all daemons: shell> pmacctd -f pmacctd.conf Daemonize the process; listen on eth0; aggregate data by src_host/dst_host; write to a MySQL server; filter in only traffic with source prefix 10.0.0.0/16; note that filters work the same as tcpdump so you can refer to libpcap/tcpdump man pages for examples and further reading about the supported filtering syntax. shell> pmacctd -D -c src_host,dst_host -i eth0 -P mysql src net 10.0.0.0/16 Or written the configuration way: ! daemonize: true plugins: mysql aggregate: src_host, dst_host pcap_interface: eth0 pcap_filter: src net 10.0.0.0/16 ! ... Print collected traffic data aggregated by src_host/dst_host over the screen; refresh data every 30 seconds and listen on eth0. shell> pmacctd -P print -r 30 -i eth0 -c src_host,dst_host Or written the configuration way: ! plugins: print print_refresh_time: 30 aggregate: src_host, dst_host pcap_interface: eth0 ! ... Print collected traffic data aggregated by src_host/dst_host over the screen; refresh data every 30 seconds and listen on eth0 and eth1, listed in the file pointed by pcap_interfaces_map (see 'examples/pcap_interfaces.map.example' for more advanced uses of the map): ! plugins: print print_refresh_time: 30 aggregate: src_host, dst_host pcap_interfaces_map: /path/to/pcap_interfaces.map ! ... Then in /path/to/pcap_interfaces.map: ! ifindex=100 ifname=eth0 ifindex=200 ifname=eth1 ! ... Daemonize the process; let pmacct aggregate traffic in order to show in vs out traffic for network 192.168.0.0/16; send data to a PostgreSQL server. This configuration is not possible via commandline switches; the corresponding configuration follows: ! daemonize: true plugins: pgsql[in], pgsql[out] aggregate[in]: dst_host aggregate[out]: src_host aggregate_filter[in]: dst net 192.168.0.0/16 aggregate_filter[out]: src net 192.168.0.0/16 sql_table[in]: acct_in sql_table[out]: acct_out ! ... And now enabling historical accounting. Split traffic by hour and write to the database every 60 seconds: ! daemonize: true plugins: pgsql[in], pgsql[out] aggregate[in]: dst_host aggregate[out]: src_host aggregate_filter[in]: dst net 192.168.0.0/16 aggregate_filter[out]: src net 192.168.0.0/16 sql_table[in]: acct_in sql_table[out]: acct_out sql_refresh_time: 60 sql_history: 1h sql_history_roundoff: h ! ... Let's now translate the same example in the memory plugin world. One of the use-cases for this plugin is when feeding 3rd party tools with bytes/ packets/flows counters. Examples how to query the memory table with the 'pmacct' client tool will follow later in this document. Now, note that each memory table need its own pipe file in order to get queried by the client: ! daemonize: true plugins: memory[in], memory[out] aggregate[in]: dst_host aggregate[out]: src_host aggregate_filter[in]: dst net 192.168.0.0/16 aggregate_filter[out]: src net 192.168.0.0/16 imt_path[in]: /tmp/pmacct_in.pipe imt_path[out]: /tmp/pmacct_out.pipe ! ... As a further note, check CONFIG-KEYS document about more imt_* directives as they will support in the task of fine tuning the size and boundaries of memory tables, if default values are not ok for your setup. Now, fire multiple instances of pmacctd, each on a different interface; again, because each instance will have its own memory table, it will require its own pipe file for client queries aswell (as explained in the previous examples): shell> pmacctd -D -i eth0 -m 8 -s 65535 -p /tmp/pipe.eth0 shell> pmacctd -D -i ppp0 -m 0 -s 32768 -p /tmp/pipe.ppp0 Run pmacctd logging what happens to syslog and using "local2" facility: shell> pmacctd -c src_host,dst_host -S local2 NOTE: superuser privileges are needed to execute pmacctd correctly. V. Running the NetFlow/IPFIX and sFlow daemons (nfacctd/sfacctd) All examples about pmacctd are also valid for nfacctd and sfacctd with the exception of directives that apply exclusively to libpcap. If you have skipped examples in the previous section, please read them before continuing. All config keys available are in the CONFIG-KEYS document. Some examples: Run nfacctd reading configuration from a specified file: shell> nfacctd -f nfacctd.conf Daemonize the process; aggregate data by sum_host (by host, summing inbound + outbound traffic); write to a local MySQL server. Listen on port 5678 for incoming Netflow datagrams (from one or multiple NetFlow agents): shell> nfacctd -D -c sum_host -P mysql -l 5678 Let's now configure pmacct to insert data in MySQL every two minutes, enable historical accounting with 10 minutes time-bins and make use of a SQL table version 4: ! daemonize: true plugins: mysql aggregate: sum_host nfacctd_port: 5678 sql_refresh_time: 120 sql_history: 10m sql_history_roundoff: mh sql_table_version: 4 ! ... Va. NetFlow daemon & accounting NetFlow v9/IPFIX options NetFlow v9/IPFIX can send option records other than flow ones, typically used to send to a collector mappings among interface SNMP ifIndexes to interface names or VRF ID's to VRF names or extra sampling information. nfacctd_account_options enables accounting of option records then these should be split from regular flow records. Below is a sample config: nfacctd_time_new: true nfacctd_account_options: true ! plugins: print[data], print[option_vrf], print[option_if], print[option_sampling] ! pre_tag_filter[data]: 100 aggregate[data]: peer_src_ip, in_iface, out_iface, tos, vrf_id_ingress, vrf_id_egress print_refresh_time[data]: 300 print_history[data]: 300 print_history_roundoff[data]: m print_output_file_append[data]: true print_output_file[data]: /path/to/flow_%s print_output[data]: csv ! pre_tag_filter[option_vrf]: 200 aggregate[option_vrf]: peer_src_ip, vrf_id_ingress, vrf_name print_refresh_time[option_vrf]: 300 print_history[option_vrf]: 300 print_history_roundoff[option_vrf]: m print_output_file_append[option_vrf]: true print_output_file[option_vrf]: /path/to/option_vrf_%s print_output[option_vrf]: event_csv ! pre_tag_filter[option_if]: 200 aggregate[option_if]: peer_src_ip, in_iface, int_descr print_refresh_time[option_if]: 300 print_history[option_if]: 300 print_history_roundoff[option_if]: m print_output_file_append[option_if]: true print_output_file[option_if]: /path/to/option_if_%s print_output[option_if]: event_csv ! pre_tag_filter[option_sampling]: 200 aggregate[option_sampling]: peer_src_ip, sampler_id, sampler_interval print_refresh_time[option_sampling]: 300 print_history[option_sampling]: 300 print_history_roundoff[option_sampling]: m print_output_file_append[option_sampling]: true print_output_file[option_sampling]: /path/to/option_sampling_%s print_output[option_sampling]: event_csv ! aggregate_primitives: /path/to/primitives.lst pre_tag_map: /path/to/pretag.map maps_refresh: true Below is the referenced pretag.map: set_tag=100 ip=0.0.0.0/0 sample_type=flow set_tag=200 ip=0.0.0.0/0 sample_type=option Below is the referenced primitives.lst: name=vrf_id_ingress field_type=234 len=4 semantics=u_int name=vrf_id_egress field_type=235 len=4 semantics=u_int name=vrf_name field_type=236 len=32 semantics=str ! name=int_descr field_type=83 len=64 semantics=str ! name=sampler_interval field_type=50 len=4 semantics=u_int name=sampler_id field_type=48 len=2 semantics=u_int Vb. Distributing NetFlow v9/IPFIX templates when clustering One of the possible ways to cluster multiple nfacctd daemons running on the same system (ie. to harness all [configured] CPU threads) is to rely on the Linux/BSD SO_REUSEPORT feature (read more in the "Miscellaneous notes and troubleshooting tips" section of this document). NetFlow v9/IPFIX protocols are template-based and templates are emitted in specific Options packets and are indeed needed in order to properly decode actual Data packets. Hence a load-balancing cluster (when not hashing but performing some sort of round-robin) does pose the problem of disseminating the templates across the clustered daemons. For this very purpose there are two config knobs: nfacctd_templates_receiver (to export received templates) and nfacctd_templates_port (to define a port to receive templates from the rest of the cluster). When multiple daemons are clustered a replicator (nfacctd with 'tee' plugin configured is required). Here is an example of the configs needed: nfacctd clustered daemon config (other daemons in the same cluster would be listening on different nfacctd_templates_port ports, ie. 20002, 20003, etc.): ! ! [ .. existing config .. ] ! nfacctd_templates_receiver: 127.0.0.1:10000 nfacctd_templates_port: 20001 The replicator piece needs two bits, a config and a tee_receivers file (in the example receivers.lst). Here is the config: nfacctd_port: 10000 ! plugins: tee[a] ! tee_receivers[a]: /path/to/receivers.lst tee_transparent[a]: true And here is the receivers.lst file: id=1 ip=127.0.0.1:20001,127.0.0.1:20002,127.0.0.1:20003,[..] Vc. Examples configuring NetFlow v9/IPFIX export Example to configure NetFlow v9 export on a Cisco running IOS/IOS-XE: ip flow-cache timeout active 1 ip flow-cache mpls label-positions 1 ! ip flow-export source Loopback0 ip flow-export version 9 bgp-nexthop ip flow-export template timeout-rate 1 ip flow-export template refresh-rate 4 ip flow-export destination X.X.X.X 2100 ! interface GigabitEthernet0/0 ip address Y.Y.Y.Y Z.Z.Z.Z ip flow ingress Example to configure NetFlow v9 export on a Cisco running IOS-XR: sampler-map NFACCTD-SMP random 1 out-of 10 ! flow monitor-map NFACCTD-MON record ipv4 exporter NFACCTD-EXP ! flow exporter-map NFACCTD-EXP version v9 transport udp 2100 destination X.X.X.X ! interface GigabitEthernet0/0/0/1 ipv4 address Y.Y.Y.Y Z.Z.Z.Z flow ipv4 monitor NFACCTD-MON sampler NFACCTD-SMP ingress Example to configure IPFIX export on a Juniper: services { flow-monitoring { version-ipfix { template ipv4 { flow-active-timeout 60; flow-inactive-timeout 70; template-refresh-rate seconds 30; option-refresh-rate seconds 30; ipv4-template; } } } } chassis { fpc 0 { sampling-instance s1; } } forwarding-options { sampling { instance { s1 { input { rate 10; } family inet { output { flow-server X.X.X.X { port 2100; version-ipfix { template { ipv4; } } } inline-jflow { source-address Y.Y.Y.Y; } } } } } } } Example to configure NetFlow v9 export on a Huawei: ip netstream timeout active 1 ip netstream timeout inactive 5 ip netstream mpls-aware label-and-ip ip netstream export version 9 origin-as bgp-nexthop ip netstream export index-switch 32 ip netstream export template timeout-rate 1 ip netstream sampler fix-packets 1000 inbound ip netstream export source Y.Y.Y.Y ip netstream export host X.X.X.X 2100 ipv6 netstream timeout active 1 ipv6 netstream timeout inactive 5 ipv6 netstream mpls-aware label-and-ip ipv6 netstream export version 9 origin-as bgp-nexthop ipv6 netstream export index-switch 32 ipv6 netstream export template timeout-rate 1 ipv6 netstream sampler fix-packets 1000 inbound interface Eth-Trunk1.100 ip netstream inbound ipv6 netstream inbound Contribution of further configuration examples for Cisco and Juniper devices and/or other relevant vendors is more than welcome. VI. Running the NFLOG-based daemon (uacctd) All examples about pmacctd are also valid for uacctd with the exception of directives that apply exclusively to libpcap. If you've skipped examples in the "Running the libpcap-based daemon (pmacctd)" section, please read them before continuing. All configuration keys available are in the CONFIG-KEYS document. The daemon depends on the package libnetfilter-log-dev in Debian/Ubuntu, libnetfilter_log in CentOS/RHEL (or equivalent package in the preferred Linux distribution). The support for NFLOG is disabled by default and should be enabled as follows: shell> ./configure --enable-nflog NFLOG_CFLAGS and NFLOG_LIBS can be used if includes and library are not in default locations. The Linux NFLOG infrastructure requires a couple parameters in order to work properly: the NFLOG multicast group (uacctd_group) to which captured packets have to be sent to and the Netlink buffer size (uacctd_nl_size). The default buffer settings (128KB) typically works OK for small environments. The traffic is captured with an iptables rule. For example in one of the following ways: * iptables -t mangle -I POSTROUTING -j NFLOG --nflog-group 5 * iptables -t raw -I PREROUTING -j NFLOG --nflog-group 5 Apart from determining how and what traffic to capture with iptables, which is topic outside the scope of this document, the most relevant point is the "--nflog-nlgroup" iptables setting has to match with the "uacctd_group" uacctd one. To review the packet flow in iptables: https://commons.wikimedia.org/wiki/File:Netfilter-packet-flow.svg A couple examples follow: Run uacctd reading configuration from a specified file. shell> uacctd -f uacctd.conf Daemonize the process; aggregate data by sum_host (by host, summing inbound + outbound traffic); write to a local MySQL server. Listen on NFLOG multicast group #5. Let's make pmacct divide data into historical time-bins of 5 minutes. Let's disable UPDATE queries and hence align refresh time with the timeslot length. Finally, let's make use of a SQL table, version 4: ! uacctd_group: 5 daemonize: true plugins: mysql aggregate: sum_host sql_refresh_time: 300 sql_history: 5m sql_history_roundoff: mh sql_table_version: 4 sql_dont_try_update: true ! ... VII. Running the pmacct IMT client (pmacct) The 'pmacct' client tool allows to query memory tables. Messaging happens over a UNIX pipe file: authorization is strictly connected to permissions of the pipe file. Note: while writing queries commandline, it may happen to write chars with a special meaning for the shell itself (ie. ; or *). Mind to either escape ( \; or \* ) them or put in quotes ( " ). Show all available pmacct client commandline switches: shell> pmacct -h Fetch data stored in the memory table: shell> pmacct -s Fetch data stored in the memory table using JSON output (and nicely format it with the 'jq' tool): shell> pmacct -s -O json | jq Match data between source IP 192.168.0.10 and destination IP 192.168.0.3 and return a formatted output; display all fields (-a), this way the output is easy to be parsed by tools like awk/sed; each unused field will be zero-filled: shell> pmacct -c src_host,dst_host -M 192.168.0.10,192.168.0.3 -a Similar to the previous example; it is requested to reset data for matched entries; the server will return the actual counters to the client, then will reset them: shell> pmacct -c src_host,dst_host -M 192.168.0.10,192.168.0.3 -r Fetch data for IP address dst_host 10.0.1.200; we also ask for a 'counter only' output ('-N') suitable, this time, for injecting data in tools like MRTG or RRDtool (sample scripts are in the examples/ tree). Bytes counter will be returned (but the '-n' switch allows also select which counter to display). If multiple entries match the request (ie because the query is based on dst_host but the daemon is actually aggregating traffic as "src_host, dst_host") their counters will be summed: shell> pmacct -c dst_host -N 10.0.1.200 Query the memory table available via pipe file /tmp/pipe.eth0: shell> pmacct -c sum_port -N 80 -p /tmp/pipe.eth0 Find all data matching host 192.168.84.133 as either their source or destination address. In particular, this example shows how to use wildcards and how to spawn multiple queries (each separated by the ';' symbol). Take care to follow the same order when specifying the primitive name (-c) and its actual value ('-M' or '-N'): shell> pmacct -c src_host,dst_host -N "192.168.84.133,*;*,192.168.84.133" Find all web and smtp traffic; we are interested in have just the total of such traffic (for example, to split legal network usage from the total); the output will be a unique counter, sum of the partial (coming from each query) values. shell> pmacct -c src_port,dst_port -N "25,*;*,25;80,*;*,80" -S Show traffic between the specified hosts; this aims to be a simple example of a batch query; note that as value of both '-N' and '-M' switches it can be supplied a value like: 'file:/home/paolo/queries.list': actual values will be read from the specified file (and they need to be written into it, one per line) instead of commandline: shell> pmacct -c src_host,dst_host -N "10.0.0.10,10.0.0.1;10.0.0.9,10.0.0.1;10.0.0.8,10.0.0.1" shell> pmacct -c src_host,dst_host -N "file:/home/paolo/queries.list" VIII. Running the RabbitMQ/AMQP plugin The Advanced Message Queuing Protocol (AMQP) is an open standard for passing business messages between applications. RabbitMQ is a messaging broker, an intermediary for messaging, which implementes AMQP. pmacct RabbitMQ/AMQP plugin is designed to send aggregated network traffic data, in JSON or Avro format, through a RabbitMQ server to 3rd party applications (typically, but not limited to, noSQL databases like ElasticSearch, InfluxDB, etc.). Requirements to use the plugin are: * A working RabbitMQ server: http://www.rabbitmq.com/ * RabbitMQ C API, rabbitmq-c: https://github.com/alanxz/rabbitmq-c/ * Libjansson to cook JSON objects: http://www.digip.org/jansson/ Additionally, the Apache Avro C library (http://avro.apache.org/) needs to be installed to be able to send messages packed using Avro (you will also need to pass --enable-avro to the configuration script). Once these elements are installed, pmacct can be configured for compiling. pmacct makes use of pkg-config for finding libraries and headers location and checks some "typical" default locations, ie. /usr/local/lib and /usr/local/include. So all you should do is just: shell> ./configure --enable-rabbitmq --enable-jansson But, for example, should you have installed RabbitMQ in /usr/local/rabbitmq and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export RABBITMQ_LIBS="-L/usr/local/rabbitmq/lib -lrabbitmq" shell> export RABBITMQ_CFLAGS="-I/usr/local/rabbitmq/include" shell> ./configure --enable-rabbitmq --enable-jansson You can check further information on how to compile pmacct with JSON/libjansson support in the section "Compiling pmacct with JSON support" of this document. You can check further information on how to compile pmacct with Avro support in the section "Compiling pmacct with Apache Avro support" of this document. Then "make; make install" as usual. Following a configuration snippet showing a basic RabbitMQ/AMQP plugin configuration (assumes: RabbitMQ server is available at localhost; look all configurable directives up in the CONFIG-KEYS document): ! .. plugins: amqp ! aggregate: src_host, dst_host, src_port, dst_port, proto, tos amqp_output: json amqp_exchange: pmacct amqp_routing_key: acct amqp_refresh_time: 300 amqp_history: 5m amqp_history_roundoff: m ! .. pmacct will only declare a message exchange and provide a routing key, ie. it will not get involved with queues at all. A basic consumer script, in Python, is provided as sample to: declare a queue, bind the queue to the exchange and show consumed data on the screen or post to a REST API. The script is located in the pmacct default distribution tarball in 'examples/amqp/amqp_receiver.py' and requires the 'pika' Python module installed. Should this not be available, installation instructions are available at the following page: http://www.rabbitmq.com/tutorials/tutorial-one-python.html IX. Running the Kafka plugin Apache Kafka is a distributed streaming platform. Its qualities being: fast, scalable, durable and distributed by design. pmacct Kafka plugin is designed to send aggregated network traffic data, in JSON or Avro format, through a Kafka broker to 3rd party applications (typically, but not limited to, noSQL databases like ElasticSearch, InfluxDB, etc.). Requirements to use the plugin are: * A working Kafka broker (and Zookeper server): http://kafka.apache.org/ * Librdkafka: https://github.com/edenhill/librdkafka/ * Libjansson to cook JSON objects: http://www.digip.org/jansson/ Additionally, the Apache Avro C library (http://avro.apache.org/) needs to be installed to be able to send messages packed using Avro (you will also need to pass --enable-avro to the configuration script). Once these elements are installed, pmacct can be configured for compiling. pmacct makes use of pkg-config for finding libraries and headers location and checks some default locations, ie. /usr/local/lib and /usr/local/include. If this is satisfactory, all you should do is just: shell> ./configure --enable-kafka --enable-jansson But, for example, should you have installed Kafka in /usr/local/kafka and pkg- config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export KAFKA_LIBS="-L/usr/local/kafka/lib -lrdkafka" shell> export KAFKA_CFLAGS="-I/usr/local/kafka/include" shell> ./configure --enable-kafka --enable-jansson You can check further information on how to compile pmacct with JSON/libjansson support in the section "Compiling pmacct with JSON support" of this document. As a proof-of-concept once some data is produced in JSON format to a Kafka topic, it can be consumed with the kafka-console-consumer tool, part of standard Kafka distribution, as: kafka-console-consumer --bootstrap-server \ --topic You can check further information on how to compile pmacct with Avro support in the section "Compiling pmacct with Apache Avro support" of this document. Also, if using Confluent Platform, a Schema Registry component is included with it and allows for seamless inter-change of Avro schemas among producers and consumers of a Kafka broker; to make use of this, pmacct should be compiled with libserdes support: shell> ./configure --enable-kafka --enable-jansson --enable-avro --enable-serdes For further info on Confluent Schema Registry and libserdes: https://docs.confluent.io/current/schema-registry/docs/index.html https://github.com/confluentinc/libserdes NOTE: issues have been reported for certain cases when using libserdes on a system with OpenSSL 1.0.x installed due to some interactions with libcurl. Please upgrade to OpenSSL 1.1.x or greater. Then "make; make install" as usual. As a proof-of-concept, when the Schema Registry is in use, once some data is produced in Avro format to a Kafka topic, it can be consumed with the kafka-avro-console-consumer tool, part of standard Confluent Platform distribution, as: kafka-avro-console-consumer --bootstrap-server \ --topic \ --property schema.registry.url= \ --skip-message-on-error Following a configuration snippet showing a basic Kafka plugin configuration (assumes: Kafka broker is available at 127.0.0.1 on port 9092; look all kafka_* configurable directives up in the CONFIG-KEYS document): ! .. plugins: kafka ! aggregate: src_host, dst_host, src_port, dst_port, proto, tos kafka_output: json kafka_topic: pmacct.acct kafka_refresh_time: 300 kafka_history: 5m kafka_history_roundoff: m ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! kafka_config_file: /path/to/librdkafka.conf ! ! [Optional] Schema Registry URL ! kafka_avro_schema_registry: https://localhost ! .. A basic script, in Python, is provided as sample to consume JSON/Avro data from a given topic and perform some simple actions (ie. post data to a new Kafka topic, post to a URL or print to screen). The script is located in the pmacct distribution code in 'examples/kafka/kafka_consumer.py' and requires the confluent-kafka-python Python module installed (among the others, check script header). Should this not be available you can read on the following page how to get it installed: https://github.com/confluentinc/confluent-kafka-python This is a pointer to the quick start guide to Kafka: https://kafka.apache.org/quickstart Some notes: 1) When using Kafka over a dedicated node or VM, you may have to update the default Kafka server configuration. Edit the file named server.properties under the config folder of your kafka installation. Uncomment the following parameters: * listeners, * advertised.listeners, * listener.security.protocol.map and configure it according to your Kafka design. Taking a simple example where there is one single Kafka node used for both Zookeeper and Kafka and this node is using and ip address like 172.16.2.1. Those three parameters will look like this: listeners=PLAINTEXT://172.16.2.1:9092 advertised.listeners=PLAINTEXT://172.16.2.1:9092 listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL 2) When the amount of data published to Kafka is substantial, ie. in the order of thousands of entries per second, batching (MessageSet) is needed in order to avoid every single object being produced singularly to Kafka brokers. Two strategies are available for this a) pmacct batching via the kafka_multi_values feature (legacy) or b) librdkafka batching (recommended) via, as per the lib documentation, "The two most important configuration properties for performance tuning [are]: * batch.num.messages : the minimum number of messages to wait for to accumulate in the local queue before sending off a message set. * queue.buffering.max.ms : how long to wait for batch.num.messages to fill up in the local queue.". Note: up until librdkafka 0.11, the default was kept very low to favour low-latency. A sensible minimum value in high-throughput scenarios is 50ms. Also, intuitively, queue.buffering.max.messages, the "Maximum number of messages allowed on the producer queue", should be kept greater than the batch.num.messages. These knobs can all be supplied to librdkafka through pmacct via a file pointed by kafka_config_file, as global settings, ie.: global, queue.buffering.max.messages, 8000000 global, batch.num.messages, 100000 global, queue.buffering.max.ms, 50 3) Configuring statistics.interval.ms to a positive value in kafka_config_file will make librdkafka log plenty of internal metrics - as documented at the following wiki page: https://github.com/edenhill/librdkafka/wiki/Statistics For example: global, statistics.interval.ms, 60000 4) SSL and SASL supports in librdkafka are totally configuration based, meaning they can be enabled via the kafka_config_file. More info is available at the pages: https://github.com/edenhill/librdkafka/wiki/Using-SSL-with-librdkafka and https://github.com/edenhill/librdkafka/wiki/Using-SASL-with-librdkafka . For example, quoting the librdkafka page for SSL: global, security.protocol, ssl global, ssl.ca.location, ca-cert global, ssl.certificate.location, client_?????_client.pem global, ssl.key.location, client_?????_client.key global, ssl.key.password, abcdefgh Or, for example, trying to connect to Microsoft Azure via their Kafka API using SASL: global, security.protocol, SASL_SSL global, sasl.mechanism, PLAIN global, sasl.username, $ConnectionString global, sasl.password, Endpoint=sb://XXX.windows.net/;SharedAccessKeyName=YYY;SharedAccessKey=ZZZ;EntityPath=JJJ 5) When integrating pmacct with the PNDA framework ( http://www.pnda.io/ ), a guide on how to make the two communicate has been written-up and published at this URL: https://github.com/jbotello7381/pmacct_to_pnda.io . X. Internal buffering and queueing Two options are provided for internal buffering and queueing: 1) a home-grown circular queue implementation available since day one of pmacct (configured via plugin_pipe_size and documented in docs/INTERNALS) and 2) a ZeroMQ queue (configured via plugin_pipe_zmq and plugin_pipe_zmq_* directives). For a quick comparison: while relying on a ZeroMQ queue does introduce an external dependency, ie. libzmq, it reduces the amount of trial and error needed to fine tune plugin_buffer_size and plugin_pipe_size directives needed by the home-grown queue implementation. The home-grown cicular queue has no external dependencies and is configured, for example, as: plugins: print[blabla] plugin_buffer_size[blabla]: 10240 plugin_pipe_size[blabla]: 1024000 For more information about the home-grown circular queue, consult plugin_buffer_size and plugin_pipe_size entries in CONFIG-KEYS and docs/INTERNALS "Communications between core process and plugins" chapter. ZeroMQ, from 0MQ The Guide, "looks like an embeddable networking library but acts like a concurrency framework. It gives you sockets that carry atomic messages across various transports like in-process, inter-process, TCP, and multicast. You can connect sockets N-to-N with patterns like fan-out, pub-sub, task distribution, and request-reply. It's fast enough to be the fabric for clustered products. Its asynchronous I/O model gives you scalable multicore applications, built as asynchronous message-processing tasks. [ .. ]". pmacct integrates ZeroMQ using a pub-sub queue architecture, using ephemeral TCP ports and implementing plain authentication (username and password, auto-generated at runtime). The only requirement to use a ZeroMQ queue is to have the latest available stable release of libzmq installed on the system (http://zeromq.org/intro:get-the-software , https://github.com/zeromq/libzmq/releases). Once this is installed, pmacct can be configured for compiling. pmacct makes use of pkg-config for finding libraries and headers location and checks some "typical" default locations, ie. /usr/local/lib and /usr/local/include. So all you should do is just: shell> ./configure --enable-zmq But, for example, should you have installed ZeroMQ in /usr/local/zeromq and should also pkg-config be unable to help, the non-default location can be supplied as follows (bash shell assumed): shell> export ZMQ_LIBS="-L/usr/local/zeromq/lib -lzmq" shell> export ZMQ_CFLAGS="-I/usr/local/zeromq/include" shell> ./configure --enable-zmq Then "make; make install" as usual. Following a configuration snippet showing how easy is to leverage ZeroMQ for queueing (see CONFIG-KEYS for all ZeroMQ-related options): plugins: print[blabla] plugin_pipe_zmq[blabla]: true plugin_pipe_zmq_profile[blabla]: micro Please review the standard buffer profiles, plugin_pipe_zmq_profile, in CONFIG-KEYS; Q21 of FAQS describes how to estimate the amount of flows/samples per second of your deployment. XI. Quickstart guide to packet/flow classification Packet classification is a feature available for pmacctd (libpcap-based daemon), uacctd (NFLOG-based daemon), nfacctd (NetFlow daemon) via NetFlow v9/IPFIX IE #315 (dataLinkFrameSection) and sfacctd (sFlow daemon) via sFlow v5 raw header sample and the current approach is to leverage the popular free, open-source nDPI library. To enable the feature please follow these steps: 1) Download pmacct from its webpage (http://www.pmacct.net/) or from its GitHub repository (https://github.com/pmacct/pmacct). 2) Download nDPI from its GitHub repository (https://github.com/ntop/nDPI). The nDPI API tends to change frequently in a non-backward compatible fashion. This means that not every version of pmacct will work with any version of nDPI. pmacct 1.7.6 works against nDPI 3.2-stable. pmacct 1.7.7 works against nDPI 3.4-stable. pmacct 1.7.8 works against nDPI 4.0-stable and 4.2-stable. 3) Configure for compiling, compile and install the downloaded nDPI library, ie. inside the nDPI directory: shell> ./autogen.sh; ./configure; make; make install; ldconfig 4) Configure for compiling pmacct with the --enable-ndpi switch. Then compile and install, ie.: If downloading a release from http://www.pmacct.net , from inside the pmacct directory: shell> ./configure --enable-ndpi; make; make install If downloading code from https://github.com/pmacct/pmacct , from inside the pmacct directory: shell> ./autogen.sh; ./configure --enable-ndpi; make; make install If using a nDPI library that is not installed (or not installed in a default location) on the system, then NDPI_LIBS and NDPI_CFLAGS should be set to the location where nDPI headers and dynamic library are lyingi, for example: shell> NDPI_LIBS=-L/path/to/nDPI/src/lib/.libs shell> NDPI_CFLAGS=-I/path/to/nDPI/src/include shell> export NDPI_LIBS NDPI_CFLAGS shell> ./configure --enable-ndpi shell> make; make install If using a nDPI library that does not install libndpi.pc pkg-config file in a standard directory, then PKG_CONFIG_PATH should be set (this seems to be true for both 2.6 and 2.8 releases), for example: shell> PKG_CONFIG_PATH=/usr/local/libdata/pkgconfig shell> export PKG_CONFIG_PATH shell> ./configure --enable-ndpi shell> make; make install 5) Configure pmacct. The following sample configuration is based on pmacctd and the print plugin with formatted output to stdout: daemonize: true pcap_interface: eth0 snaplen: 700 ! plugins: print ! aggregate: src_host, dst_host, src_port, dst_port, proto, tos, class What enables packet classification is the use of the 'class' primitive as part of the supplied aggregation method. Further classification-related options, such as timers, attempts, etc., are documented in the CONFIG-KEYS document (classifier_* directives). 6) Execute pmacct as: shell> pmacctd -f /path/to/pmacctd.conf Flow classification is a feature available for nfacctd (NetFlow daemon) and relies on NetFlow v9/IPFIX IEs #94, #95 and #96. Where IE #95 (applicationId) is part of flow data and can be looked up against Options data where IE #96 (applicationName) and IE #94 (applicationDescription) are supplied - specifically applicationName is the one used for the 'class' primitive value. To enable the feature, if the NetFlow/ IPFIX exporter does follow Cisco NBAR2 / RFC6759 implementation (and pmacct nfprobe plugin does!), simply add the 'class' primitive to the existing 'aggregate' aggregation method. XII. Quickstart guide to setup a NetFlow/IPFIX agent/probe pmacct is able to export traffic data through both NetFlow and sFlow protocols. This section covers NetFlow/IPFIX and next one covers sFlow. While NetFlow v5 is fixed by nature, v9 adds (to v5) flexibility allowing to transport custom information (ie. classification information or custom tags to remote collectors) and IPFIX adds (to v9) the chance to transport private information (PEN) and variable-length elements. Below the configuration guide: a) usual initial steps: download pmacct, unpack it, compile it. b) build NetFlow probe configuration, using pmacctd: ! daemonize: true pcap_interface: eth0 aggregate: src_host, dst_host, src_port, dst_port, proto, tos plugins: nfprobe nfprobe_receiver: 192.168.1.1:2100 ! nfprobe_receiver: [FD00::2]:2100 nfprobe_version: 10 ! nfprobe_engine: 1:1 ! nfprobe_timeouts: tcp=120:maxlife=3600 ! ! networks_file: /path/to/networks.lst !... This is a basic working configuration. Additional probe features include: 1) generate ASNs by using a networks_file pointing to a valid Networks File (see examples/ directory) and adding src_as, dst_as primitives to the 'aggregate' directive; alternatively, it is possible to generate ASNs from the pmacctd BGP thread. The following fragment can be added to the config above: pmacctd_as: bgp bgp_daemon: true bgp_daemon_ip: 127.0.0.1 bgp_agent_map: /path/to/bgp_agent.map bgp_daemon_port: 17917 The bgp_daemon_port can be changed from the standard BGP port (179/TCP) in order to co-exist with other BGP routing software which might be running on the same host. Depending on the BGP implementation used, it is possible to peer each other this way using 127.0.0.1 as bgp_daemon_ip. It may however be necessary to use a different listening IP address for pmacctd BGP and the other BGP software (see below). In pmacctd, bgp_agent_map does the trick of mapping 0.0.0.0 to the IP address of the BGP peer (ie. 127.0.0.1: 'bgp_ip=127.0.0.1 ip=0.0.0.0'); this setup, while generic, was tested working in conjunction with Quagga, FRR and BIRD. Example fragment of the FRR configuration: router bgp Y bgp router-id X.X.X.X bgp ebgp-requires-policy bgp log-neighbor-changes neighbor 127.0.0.1 remote-as Y neighbor 127.0.0.1 port 17917 neighbor 127.0.0.1 update-source 127.0.0.2 ! address-family ipv4 unicast neighbor 127.0.0.1 activate neighbor 127.0.0.1 route-map IMPORT-pmacct-4 in neighbor 127.0.0.1 route-map EXPORT-pmacct-4 out ! address-family ipv6 unicast neighbor 127.0.0.1 activate neighbor 127.0.0.1 route-map IMPORT-pmacct-6 in neighbor 127.0.0.1 route-map EXPORT-pmacct-6 out ! route-map IMPORT-pmacct-4 deny 10 route-map EXPORT-pmacct-4 permit 10 route-map IMPORT-pmacct-6 deny 10 route-map EXPORT-pmacct-6 permit 10 ! NOTE: FRR supports peering with a different implementation on the same system as of February 2022 (> 8.1.0), with the following caveats: * FRR's 'bgpd_options' directive must be configured to listen on a different IP address than pmacctd's bgp_daemon_ip. * FRR cannot initiate BGP sessions with update-source 127.0.0.1 or ::1. Setting up a 127.0.0.2 address on the system and binding FRR's bgpd to it allows the BGP session to come up fine. Example fragment of the BIRD configuration: protocol bgp pmacctd46 { description "pmacctd"; local 127.0.0.1 as YYYYY; neighbor 127.0.0.2 port 179 as YYYYY; rr client; hold time 90; keepalive time 30; graceful restart; ipv4 { next hop self; import filter { reject; }; export filter { accept; }; }; ipv6 { next hop address 127.0.0.1; import filter { reject; }; export filter { accept; }; }; } NOTE: Bird Internet Routing Daemon seems to dislike peerings on the same IP address it is configured on, even though the remote peer listens on a different TCP port; if Bird listens on 127.0.0.1 then setting up a 127.0.0.2 address on the system and binding pmacctd to it allows the BGP session to come up fine in a 127.0.0.1 <-> 127.0.0.2 fashion. 2) encode flow classification information in NetFlow v9 / IPFIX like Cisco does with its NBAR2 implementation / RFC6759. This can be done by introducing the 'class' primitive to the afore mentioned 'aggregate' and add the extra config directive: aggregate: class, src_host, dst_host, src_port, dst_port, proto, tos snaplen: 700 Further information on this topic can be found in the 'Quickstart guide to packet classification' section of this document. 3) add direction (ingress, egress) awareness to measured IP traffic flows. Direction can be defined statically (in, out) or inferred dinamically (tag, tag2) via the use of the nfprobe_direction directive. Let's look at a dynamic example using tag2; first, add the following lines to the daemon configuration: nfprobe_direction[plugin_name]: tag2 pre_tag_map: /path/to/pretag.map then edit the tag map as follows. A return value of '1' means ingress while '2' is translated to egress. It is possible to define L2 and/or L3 addresses to recognize flow directions. The 'set_tag2' primitive (tag2) will be used to carry the return value: set_tag2=1 filter='dst host XXX.XXX.XXX.XXX' set_tag2=2 filter='src host XXX.XXX.XXX.XXX' set_tag2=1 filter='ether src XX:XX:XX:XX:XX:XX' set_tag2=2 filter='ether dst XX:XX:XX:XX:XX:XX' Indeed in such a case, the 'set_tag' primitive (tag) can be leveraged to other uses (ie. filter sub-set of the traffic for flow export); 4) add interface (input, output) awareness to measured IP traffic flows. Interfaces can be defined only in addition to direction. Interface can be either defined statically (<1-4294967295>) or inferred dynamically (tag, tag2) with the use of the nfprobe_ifindex directive. Let's look at a dynamic example using tag; first add the following lines to the daemon config: nfprobe_direction[plugin_name]: tag nfprobe_ifindex[plugin_name]: tag2 pre_tag_map: /path/to/pretag.map then edit the tag map as follows: set_tag=1 filter='dst net XXX.XXX.XXX.XXX/WW' jeq=eval_ifindexes set_tag=2 filter='src net XXX.XXX.XXX.XXX/WW' jeq=eval_ifindexes set_tag=1 filter='dst net YYY.YYY.YYY.YYY/ZZ' jeq=eval_ifindexes set_tag=2 filter='src net YYY.YYY.YYY.YYY/ZZ' jeq=eval_ifindexes set_tag=1 filter='ether src YY:YY:YY:YY:YY:YY' jeq=eval_ifindexes set_tag=2 filter='ether dst YY:YY:YY:YY:YY:YY' jeq=eval_ifindexes set_tag=999 filter='net 0.0.0.0/0' ! set_tag2=100 filter='dst host XXX.XXX.XXX.XXX' label=eval_ifindexes set_tag2=100 filter='src host XXX.XXX.XXX.XXX' set_tag2=200 filter='dst host YYY.YYY.YYY.YYY' set_tag2=200 filter='src host YYY.YYY.YYY.YYY' set_tag2=200 filter='ether src YY:YY:YY:YY:YY:YY' set_tag2=200 filter='ether dst YY:YY:YY:YY:YY:YY' The set_tag=999 works as a catch all for undefined L2/L3 addresses so to prevent searching further in the map. In the example above direction is set first then, if found, interfaces are set, using the jeq/label pre_tag_map construct. c) build NetFlow collector configuration, using nfacctd: ! daemonize: true nfacctd_ip: 192.168.1.1 nfacctd_port: 2100 plugins: memory[display] aggregate[display]: src_host, dst_host, src_port, dst_port, proto ! aggregate[display]: class, src_host, dst_host, src_port, dst_port, proto d) Ok, we are done ! Now fire both daemons: shell a> pmacctd -f /path/to/configuration/pmacctd-nfprobe.conf shell b> nfacctd -f /path/to/configuration/nfacctd-memory.conf XIII. Quickstart guide to setup a sFlow agent/probe pmacct can export traffic data via sFlow; such protocol is different from NetFlow/ IPFIX: in short, it works by sampling individual packets (and exporting portions of them) instead of caching uni-directional flows as it happens for NetFlow; such a statelss approach makes sFlow a light export protocol well-tailored for high-speed networks. Furthermore, sFlow v5 can be extended much like NetFlow v9/IPFIX: meaning classification information (if nDPI is compiled in, see 'Quickstart guide to packet classification' section of this document), tags and/or basic Extended Gateway info (ie. src_as, dst_as) can be easily included in the record structure being exported. For classification info to be included in sFlow packets please make sure to specify the classifier_num_roots directive in the config. Here a quickstarter sFlow probe configuration, using pmacctd: ! daemonize: true pcap_interface: eth0 plugins: sfprobe sampling_rate: 20 sfprobe_agentsubid: 1402 sfprobe_receiver: 192.168.1.1:6343 ! ! sfprobe_agentip: FD00::1 ! sfprobe_source_ip: FD00::1 ! sfprobe_receiver: [FD00::2]:6343 ! ! networks_file: /path/to/networks.lst ! snaplen: 700 ! ! classifier_num_roots: 512 ! !... XIV. Quickstart guide to setup the BGP daemon BGP can be run as a stand-alone collector daemon (pmbgpd) or as a thread within one of the traffic accounting daemons (ie. nfacctd). The stand-alone daemon is suitable for the Looking-Glass use-case, building BGP xconnects and consuming BGP data, real-time or at regular intervals; the thread solution is suitable for correlation of BGP with other data sources, ie. NetFlow, IPFIX, sFlow, etc. The thread implementation idea is to receive data-plane information, ie. via NetFlow, sFlow, etc., and control plane information, ie. full routing tables via BGP, from edge routers. Per-peer BGP RIBs are maintained to ensure local views of the network, a behaviour close to that of a BGP route-server. In case of routers with default-only or partial BGP views, the default route can be followed up (bgp_default_follow); also it might be desirable in certain situations, for example trading-off resources to accuracy, to map one or a set of flow agents to a BGP peer (bgp_agent_map). The following configuration snippet shows how to set up a BGP thread (ie. part of the NetFlow/IPFIX collector, nfacctd) which will bind to an IP address and will support up to a maximum number of 100 peers. Once PE routers start sending flow telemetry data and peer up, it should be possible to see the BGP-related fields, ie. as_path, peer_as_dst, local_pref, med, etc., correctly populated while querying the memory table: bgp_daemon: true bgp_daemon_ip: X.X.X.X bgp_daemon_max_peers: 100 ! bgp_daemon_as: 65555 nfacctd_as: bgp [ ... ] plugins: memory aggregate: src_as, dst_as, local_pref, med, as_path, peer_dst_as Setting up the stand-alone BGP collector daemon, pmbgpd, is not very different at all from the configuration above: bgp_daemon_ip: X.X.X.X bgp_daemon_max_peers: 100 ! bgp_daemon_as: 65555 bgp_table_dump_file: /path/to/spool/bgp-$peer_src_ip-%H%M.log bgp_table_dump_refresh_time: 300 Essentially: the 'bgp_daemon: true' line is not required and there is no need to instantiate plugins. On the other hand, the BGP daemon is instructed to dump BGP tables to disk every 300 secs with file names embedding the BGP peer info ($peer_src_ip) and time reference (%H%M). The BGP implementation, by default, reads the remote ASN upon receipt of a BGP OPEN message and dynamically presents itself as part of the same ASN - this is to ensure an iBGP relationship is established, even in multi ASN scenarios. It is possible to put pmacct in a specific ASN of choice by using the bgp_daemon_as configuration directive, for example, to establish an eBGP kind of relationship. Also, the daemon acts as a passive BGP neighbor and hence will never try to re-establish a fallen peering session. For debugging purposes related to the BGP feed(s), bgp_daemon_msglog_* configuration directives can be enabled in order to log BGP messaging. NOTE: especially when connecting large amounts of BGP peers, say hundreds or more, the almost synchronized attempt to connect from all of them may lead the kernel into a suspicion of TCP SYN Flood. While not recommending to disable TCP SYN flood protection, if slugginess is observed when taking up the BGP sessions and kernel logs indicate a possible SYN flooding, maybe it is good idea to tune and customize default kernel parameters. NOTE: currently if a BGP session is abruptly terminated by the remote peer, pmacct does rely on the underlying operating system to detect the condition (TCP keepalives) and close the socket. While this is going to change by detecting the condition inside the BGP daemon as a workaround TCP keepalive timers can be tuned to react in a reasonable amount of time. The example below is based on Linux and will disconnect a hung session in about two minutes: shell> sysctl -w net.ipv4.tcp_keepalive_time=60 shell> sysctl -w net.ipv4.tcp_keepalive_intvl=10 shell> sysctl -w net.ipv4.tcp_keepalive_probes=2 XIVa. Limiting AS-PATH and BGP community attributes length AS-PATH and BGP communities can get easily long when represented as strings. Sometimes only a small portion of their content is of interest and hence a simple filtering layer was developed in order to take special care of these BGP attributes. bgp_aspath_radius cuts the AS-PATH down after a specified amount of AS hops; whereas the bgp_stdcomm_pattern does a simple sub-string matching against standard BGP communities, filtering in only those that match (optionally, for better precision, a pre-defined number of characters can be wildcarded by employing the '.' symbol, like in regular expressions). See an example below: bgp_aspath_radius: 3 bgp_stdcomm_pattern: 12345: A detailed description of these configuration directives is, as usual, included in the CONFIG-KEYS document. XIVb. The source peer AS case The peer_src_as primitive adds useful insight in understanding where traffic enters the observed routing domain; but asymmetric routing impacts accuracy delivered by devices configured with either NetFlow or sFlow and the peer-as feature (as it only performs a reverse lookup, ie. a lookup on the source IP address, in the BGP table hence saying where it would route such traffic). pmacct offers a few ways to perform some mapping to tackle this issue and easily model both private and public peerings, both bi-lateral or multi-lateral. Find below how to use a map, reloadable at runtime, and its contents (for full syntax guide lines, please see the 'peers.map.example' file within the examples section): bgp_peer_src_as_type: map bgp_peer_src_as_map: /path/to/peers.map [/path/to/peers.map] set_tag=12345 ip=A.A.A.A in=10 bgp_nexthop=X.X.X.X set_tag=34567 ip=A.A.A.A in=10 set_tag=45678 ip=B.B.B.B in=20 src_mac=00:11:22:33:44:55 set_tag=56789 ip=B.B.B.B in=20 src_mac=00:22:33:44:55:66 Even though all this mapping is static, it can be auto-provisioned to a good degree by means of external scripts running at regular intervals and, for example, querying relevant routers via SNMP. In this sense, the bgpPeerTable MIB is a good starting point. Alternatively pmacct also offers the option to perform reverse BGP lookups. NOTES: * When using maps, the peer_src_as primitive should be used with care if egress NetFlow/IPFIX/sFlow is in use as it mainly relies on either the input interface index (ifIndex), the source MAC address, a reverse BGP next-hop lookup or a combination of these. For example, egress NetFlow enabled on edge devices on core interfaces may work as the input ifIndex would still be visible; egress NetFlow enabled on edge devices on edge interfaces may not work as, unless traffic is locally switched, it may be sampled upon exiting the observed netowrk. * "Source" MED, local preference, communities and AS-PATH have all been allocated aggregation primitives. Each carries its own peculiarities but the general concepts highlighed in this chapter apply to these aswell. Check CONFIG-KEYS out for the src_[med|local_pref|as_path|std_comm|ext_comm|lrg_comm]_[type|map] configuration directives. XIVc. Tracking entities on the own IP address space It might happen that not all entities connected to the observed network are running BGP but rather they get assigned provider IP prefixes redistributed into iBGP (different routing protocols, statics, directly connected, etc.). These can be private IP addresses or segments of the SP public address space. The common factor to all of them is that while being present in iBGP, these prefixes can't be distinguished any further due to the lack of attributes like AS-PATH or an ASN. One simple solution, although costly, could be to account on IP prefixes (other than BGP attributes). Another simple solution, especially if the enity is dominated by outbound traffic (ingress in the observed network) could be to use a bgp_peer_src_as_map directive, described previously (ie. make use of interface descriptions as a possible way to automate the process). Alternatively, bgp_stdcomm_pattern_to_asn and bgp_lrgcomm_pattern_to_asn config directives were developed to fit in this scenario: assuming procedures of a SP are (or can be changed) to label every relevant non-BGP speaking entity IP prefixes uniquely with BGP standard communities, this directive then allows to map the community to a peer AS/ origin AS couple as per the following example: XXXXX:YYYYY => Peer-AS=XXXXX, Origin-AS=YYYYY. XIVd. Preparing the router to BGP peer Once the collector is configured and started up the remaining step is to let routers export traffic samples to the collector and BGP peer with it. By configuring the same source IP address across both NetFlow and BGP features allows the collector to perform the required correlations without further configuration. Also, setting the BGP Router ID accordingly allows for more clear log messages. On the routers it is adviceable to configure the BGP session with the collector as a Route-Reflector (RR) client. A relevant configuration example for a Cisco IOS follows: router bgp 12345 neighbor X.X.X.X remote-as 12345 neighbor X.X.X.X update-source Loopback12345 neighbor X.X.X.X version 4 neighbor X.X.X.X send-community neighbor X.X.X.X route-reflector-client neighbor X.X.X.X description nfacctd A relevant configuration example for a Juniper router follows: protocols bgp { group rr-netflow { type internal; local-address Y.Y.Y.Y; family inet { any; } cluster Y.Y.Y.Y; neighbor X.X.X.X { description "nfacctd"; } } } A relevant configuration example for a IOS XR (Version 5.1.1) router follows: router bgp 12345 address-family ipv4 unicast additional-paths receive additional-paths send maximum-paths ibgp 6 additional-paths selection route-policy add_path ! af-group af-group-example address-family ipv4 unicast route-reflector-client ! session-group ibgp remote-as 12345 update-source Loopback0 ! neighbor-group ibgp-rr-client use session-group ibgp address-family ipv4 unicast use af-group af-group-example ! ! neighbor X.X.X.X use neighbor-group ibgp-rr-client ! ! Contribution of further configuration examples for Cisco and Juniper devices and/or other relevant vendors is more than welcome. In case ipv4 and ipv6 address-families are delivered over two distinct BGP sessions, typically one with ipv4 transport and one with ipv6 transport, then, since both ipv4 and ipv6 flows (NetFlow, IPFIX, sFlow) are typically delivered over a single ipv4 transport, a bgp_agent_map is needed in order to make the right correlation (see the 'filter' keyword in the example below). The map is defined in the daemon configuration ie. 'bgp_agent_map: /path/to/bgp_agent.map' then in the map itself for every router exporting flows and BGP peering the following lines should be defined: bgp_ip= ip= filter='ip or (vlan and ip)' bgp_ip= ip= filter='ip6 or (vlan and ip6)' XIVe. Example: writing flows augmented by BGP to a MySQL database The following setup is a realistic example for collecting an external traffic matrix to the ASN level (ie. no IP prefixes collected) for a MPLS-enabled IP carrier network. Samples are aggregated in a way which is suitable to get an overview of traffic trajectories, collecting much information where these enter the AS and where they get out. daemonize: true nfacctd_port: 2100 nfacctd_time_new: true plugins: mysql[5mins], mysql[hourly] sql_optimize_clauses: true sql_dont_try_update: true sql_multi_values: 1024000 sql_history_roundoff[5mins]: m sql_history[5mins]: 5m sql_refresh_time[5mins]: 300 sql_table[5mins]: acct_bgp_5mins sql_history_roundoff[hourly]: h sql_history[hourly]: 1h sql_refresh_time[hourly]: 3600 sql_table[hourly]: acct_bgp_1hr bgp_daemon: true bgp_daemon_ip: X.X.X.X bgp_daemon_max_peers: 100 bgp_aspath_radius: 3 bgp_follow_default: 1 nfacctd_as: bgp bgp_peer_src_as_type: map bgp_peer_src_as_map: /path/to/peers.map plugin_buffer_size: 10240 plugin_pipe_size: 1024000 aggregate: tag, src_as, dst_as, peer_src_as, peer_dst_as, peer_src_ip, peer_dst_ip, local_pref, as_path pre_tag_map: /path/to/pretag.map maps_refresh: true maps_entries: 3840 The content of the maps (bgp_peer_src_as_map, pre_tag_map) is meant to be pretty standard and will not be shown. As it can be grasped from the above configuration, the SQL schema was customized. Below a suggestion on how this can be modified for more efficiency - with additional INDEXes, to speed up specific queries response time, remaining to be worked out: create table acct_bgp_5mins ( id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT, agent_id INT(4) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, peer_as_src INT(4) UNSIGNED NOT NULL, peer_as_dst INT(4) UNSIGNED NOT NULL, peer_ip_src CHAR(15) NOT NULL, peer_ip_dst CHAR(15) NOT NULL, as_path CHAR(21) NOT NULL, local_pref INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (id), INDEX ... ) TYPE=MyISAM AUTO_INCREMENT=1; create table acct_bgp_1hr ( id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT, agent_id INT(4) UNSIGNED NOT NULL, as_src INT(4) UNSIGNED NOT NULL, as_dst INT(4) UNSIGNED NOT NULL, peer_as_src INT(4) UNSIGNED NOT NULL, peer_as_dst INT(4) UNSIGNED NOT NULL, peer_ip_src CHAR(15) NOT NULL, peer_ip_dst CHAR(15) NOT NULL, as_path CHAR(21) NOT NULL, local_pref INT(4) UNSIGNED NOT NULL, packets INT UNSIGNED NOT NULL, bytes BIGINT UNSIGNED NOT NULL, stamp_inserted DATETIME NOT NULL, stamp_updated DATETIME, PRIMARY KEY (id), INDEX ... ) TYPE=MyISAM AUTO_INCREMENT=1; Although table names are fixed in this example, ie. acct_bgp_5mins, it can be highly adviceable in real-life to run dynamic SQL tables, ie. table names that include time-related variables (see sql_table, sql_table_schema in CONFIG-KEYS). XIVf. Example: exporting BGP tables or messaging to files or AMQP/Kafka brokers. Both the stand-alone BGP collector daemon (pmbgpd) and the BGP thread within one of the traffic accounting daemons can: a) export/dump routing tables for all BGP peers at regular time intervals and b) log BGP messaging, real-time, with each of the BGP peers. Both features are useful for producing data useful for analytics, for troubleshooting and debugging. The former is beneficial to gain visibility in extra BGP data while providing event compression; the latter enables BGP analytics and BGP event management, for example spot unstable routes, trigger alarms on route hijacks, etc. Both features export data formatted as JSON or Avro messages. Please review the section "Compiling pmacct with JSON support" and, if planning to use Avro encoding, also the section "Compiling pmacct with Avro support". If writing to AMQP or Kafka brokers, compiling against RabbitMQ or Kafka libraries is required; read more in respectively the "Running the RabbitMQ/AMQP plugin" or "Running the Kafka plugin" sections of this document. If making use of the Schema Registry component of the Confluent Platform please also review the "Running the Kafka plugin" section. A basic dump of BGP tables at regular intervals (60 secs) to plain-text files, split by BGP peer and time of the day, is configured as follows: bgp_table_dump_file: /path/to/spool/bgp/bgp-$peer_src_ip-%H%M.txt bgp_table_dump_refresh_time: 60 A basic log of BGP messaging in near real-time to a plain-text file (which can be rotated by an external tool/script) is configured as follows: bgp_daemon_msglog_file: /path/to/spool/bgp/bgp-$peer_src_ip.log A basic dump of BGP tables at regular intervals (60 secs) to a Kafka broker, listening on the localost and default port, is configured as follows: bgp_table_dump_kafka_topic: pmacct.bgp bgp_table_dump_refresh_time: 60 ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! bgp_table_dump_kafka_config_file: /path/to/librdkafka.conf The equivalent bgp_table_dump_amqp_routing_key config directive can be used to make the above example work against a RabbitMQ broker. A basic log of BGP messaging in near real-time to a Kafka broker, listening on the localhost and default port, is configured as follows: bgp_daemon_msglog_kafka_topic: pmacct.bgp ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! bgp_daemon_msglog_kafka_config_file: /path/to/librdkafka.conf The equivalent bgp_daemon_msglog_amqp_routing_key config directive can be used to make the above example work against a RabbitMQ broker. A sample of both the BGP msglog and dump formats are captured in the following document: docs/MSGLOG_DUMP_FORMATS XIVg. Example: querying the BGP daemon via the Looking Glass server. The Looking Glass server allows to query RIBs stored in the BGP daemon. The server is asyncronous and uses ZeroMQ as transport layer to serve incoming queries. The LG server can be configured as follows: bgp_daemon_lg: true ! bgp_daemon_lg_user: pmacct ! bgp_daemon_lg_passwd: arealsmartpwd This configuration will enable plain authentication and will make the server listen on all interfaces on port 17900/TCP. Following an example of querying with the Python client available in 'examples/lg': Get the list of available BGP peers: shell> examples/lg/pmbgp.py -g {"results": 1, "query_type": 2} {"peer_ip_src": "192.168.1.1", "peer_id": "192.168.1.1", "peer_tcp_port": 47248, "peer_as": 65500} Lookup IP prefix 192.168.2.0/24 for BGP peer 192.168.1.1: shell> examples/lg/pmbgp.py -a 192.168.2.0/24 -r 192.168.1.1 {"peer_ip_src": "192.168.1.1", "event_type": "lglass", "afi": 1, "safi": 1, "ip_prefix": "192.168.2.0/24", "bgp_nexthop": "192.168.1.254", "as_path": "65500 65501 65502", "comms": "65500:1 65500:100 65500:65500", "origin": 0, "local_pref": 100} Request/Reply Looking Glass formats are documented in 'docs/LOOKING_GLASS_FORMAT'. XIVh. Example: BGP Xconnects pmbgpd, the pmacct BGP standalone daemon, includes a BGP xconnect feature to map BGP peers (ie. routers) to BGP collectors (ie. nfacctd, sfacctd), acting essentially as a BGP proxy. While the proxying is non-transparent, BGP peers can be still identified by rheir BGP Router-ID. The aim of this feature is to facilitate operations, ie. point all BGP Peers to a single (or a couple) IP address(es) and facilitate re-sizing/re-balancing of the collection infrastructure without impacting (ie. re-configuring) BGP peers. A few caveats apply: 1) mapping works only against the IP source address and not the BGP Router ID, 2) only 1:1 relationships can be formed (ie. this is about cross-connecting sessions, not replication) and 3) only one session per BGP peer is supported (ie. multiple BGP agents are running on the same IP address or NAT traversal scenarios are not supported [yet]). The feature can be configured as follows: bgp_daemon_xconnect_map: /path/to/bgp_xconnects.map And the content of the map can be defined as follows: bgp_dst=10.0.0.1:17901 bgp_src=192.168.0.1 bgp_dst=10.0.0.1:17902 bgp_src=192.168.0.2 bgp_dst=10.0.0.1:17910 bgp_src=192.168.10.0/24 Where bgp_dst is the IPv4/IPv6 address and port of the BGP collector to cross- connect incoming (bgp_src) BGP session to and bgp_src is compared against the IPv4/IPv6 address (not BGP Router ID) of an incoming BGP session from a BGP peer. At the collector end one should set tmp_bgp_lookup_compare_ports (read more about this knob in CONFIG-KEYS) to true. In future BMP may be added as a transport for BGP data between pmbgpd and the collector (please get in touch if interested). An alternative to the use of pmbgpd is NAT/masquerading; in this context, pmbgpd brings the advantage of running fully in user-space. SO_REUSEPORT feature (read more about it in the section "Miscellaneous notes and troubleshooting tips" of this document) can be used in alternative to BGP xconnects, ie. to simplify the deployment on a single node, or in conjunction with BGP xconnects, ie. for massive multi-node scale-out. Leveraging SO_REUSEPORT, when used in alternative to BGP xconnects, may be best combined with a list of allowed IP addresses, ie. bgp_daemon_allow_file, to explicitely wire peers to collectors. When SO_REUSEPORT is used in conjunction with BGP xconnects there is virtually no config change to make (except perhaps the sensible decision to use different 'logfile' per pmbgpd daemon); below instead an example for SO_REUSEPORT in alternative to BGP xconnects where a few nfacctd daemons are deployed each running the BGP thread (indeed this is applicable to sfacctd as well): Daemon #1: allow-1.map: 10.0.0.0/25 nfacctd-1.conf: ... ! nfacctd_port: 2100 ! nfacctd_allow_file: /path/to/allow-1.map ! bgp_daemon: true bgp_daemon_port: 179 bgp_daemon_allow_file: /path/to/allow-1.map ! ... Daemon #2: allow-2.map: 10.0.0.128/25 nfacctd-2.conf: ... ! nfacctd_port: 2101 ! nfacctd_allow_file: /path/to/allow-2.map ! bgp_daemon: true bgp_daemon_port: 179 bgp_daemon_allow_file: /path/to/allow-2.map ! ... NOTE: when leveraging SO_REUSEPORT for TCP sessions in conjunction with allow files the kernel will try to naively balance the sessions over the listening daemons; this may take a few connection attempts before wiring the session to the right daemon; having an excessive numbers of daemons in the pool may slow down the convergence process. NOTE: each xconnect requires two file descriptors, one for the inbound TCP session, another for the outbound one. Popular default on Linux is 1024 descriptor per process, effectively limiting the amunt of sessions that can be xconnected to approx 500. Such default can be adjusted via 'ulimit -n'. For flow protocols, which are transported in UDP, a replication layer is needed in front, note the daemon listen on different nfacctd_port in the example above (read more on how to set up a replicator in the "Quickstart guide to setup a NetFlow/IPFIX/sFlow replicator" section of the document). nfacctd_allow_file is optional config key and, if created accordingly to bgp_daemon_allow_file, may ensure only flows from router for which a BGP sessions accepted should be processed. XIVi. Example: adding RPKI/ROA information Resource Public Key Infrastructure (RPKI) is a specialized public key infrastructure (PKI) framework designed to secure the Internet routing. RPKI uses certificates to allow Local Internet Registries (LIRs) to list the Internet number resources they hold. These attestations are called Route Origination Authorizations (ROAs). ROA information can be currently acquired in one of the two following ways: 1) it can be imported using the rpki_roas_file config directive from a file in the RIPE Validator or OpenBSD Validator formats, ie.: { "roas" : [ { "asn" : "AS2914", "prefix" : "128.121.0.0/16", "maxLength" : 16, "ta" : "ARIN" }, { "asn" : "AS2914", "prefix" : "128.121.0.0/19", "maxLength" : 24, "ta" : "ARIN" }, { "asn" : "AS2914", "prefix" : "128.121.4.32/29", "maxLength" : 29, "ta" : "ARIN" } ] } RPKI data in such format can be obtained for example at the following URL: https://rpki.gin.ntt.net/api/export.json . 2) Connecting to a RPKI RTR Cache for live ROA updates. Its IP address and port being defined by the rpki_rtr_cache config directive (a few more optional rpki_rtr_* directives are available and can be reviwed in the CONFIG-KEYS document). Once rpki_roas_file or rpki_rtr_cache are defined, traffic daemons (ie. nfacctd) and pmbgpd can be configured to correlate traffic, BGP and RPKI information. This is an example of how to configure nfacctd, the NetFlow/ IPFIX collector daemon: nfacctd_as: longest nfacctd_net: longest ! < .. > ! ! rpki_roas_file: /path/to/roas.json ! rpki_rtr_cache: 127.0.0.1:8323 ! rpki_rtr_cache_version: 1 ! bgp_daemon: true bgp_src_roa_type: bgp ! < .. > ! plugins: print[foo] ! aggregate[foo]: peer_src_ip, peer_dst_ip, src_host, dst_host, src_roa, dst_roa ! < .. > The ROA fields will be populated with one of these five values: 'u' Unknown, 'v' Valid, 'i' Invalid no overlaps, 'V' Invalid with a covering Valid prefix and 'U' Invalid with a covering Unknown prefix. XIVl. BGP daemon implementation concluding notes The implementation supports 4-bytes ASN, IPv4, IPv6, VPNv4 and VPNv6 (MP-BGP) address families and several IETF drafts and RFCs, ie. ADD-PATH, Shutdown Message and Large BGP Communities among the others; IPv4, IPv6 transports for BGP sessions are supported. When storing data via SQL, BGP primitives can be freely mix-and-matched with other primitives (ie. L2/L3/L4) when customizing the SQL table (sql_optimize_clauses: true). Environments making use of BGP Multi-Path should leverage ADD-PATH to advertise the multiple known paths; when correlating traffic flows to BGP, the correct BGP info is picked among the ones available using BGP next-hop (or for certain cases where traffic is sampled egress, IP next-hop if use_ip_next_hop is set to true) as selector; this does imply that BGP next-hop must be available in traffic data (ie. ADD-PATH selection is not compatible with NetFlow v5 which does not carry it) and BGP next-hop-self should not be set (otherwise all or multiple next-hops will just look like the same, hindering the decision process). TCP MD5 signature for BGP messages is also supported. For a review of all knobs and features see the CONFIG-KEYS document. XV. Quickstart guide to setup a NetFlow/IPFIX/sFlow replicator The 'tee' plugin is meant to replicate NetFlow/sFlow data to remote collectors. The plugin can act transparently, by preserving the original IP address of the datagrams, or as a proxy. The basic configuration of a replicator is very easy: all is needed is to define where to listen to for incoming packets, where to replicate them to and optionally a filtering layer, if required. Filtering bases on the standard pre_tag_map infrastructure; here will be presented only coarse-grained filtering against the NetFlow/sFlow source IP address (see next section for finer-grained filtering). nfacctd_port: 2100 nfacctd_ip: X.X.X.X ! plugins: tee[a], tee[b] tee_receivers[a]: /path/to/tee_receivers_a.lst tee_receivers[b]: /path/to/tee_receivers_b.lst ! tee_transparent: true ! ! pre_tag_map: /path/to/pretag.map ! plugin_buffer_size: 10240 plugin_pipe_size: 1024000 nfacctd_pipe_size: 1024000 An example of content of a tee_receivers map, ie. /path/to/tee_receivers_a.lst, is as follows ('id' is the pool ID and 'ip' a comma-separated list of receivers for that pool): id=1 ip=W.W.W.W:2100 id=2 ip=Y.Y.Y.Y:2100,Z.Z.Z.Z:2100 id=3 ip=[::1]:2100 ! id=1 ip=W.W.W.W:2100 tag=0 ! id=2 ip=Y.Y.Y.Y:2100,Z.Z.Z.Z:2100 tag=100 Number of tee_receivers map entries (by default 384) can be modified via maps_entries. Content can be reloaded at runtime by sending the daemon a SIGUSR2 signal (ie. "killall -USR2 nfacctd"). Selective teeing allows to filter which pool of receivers has to receive which datagrams. Tags are applied via a pre_tag_map, the one illustrated below applies tag 100 to packets exported from agents A.A.A.A, B.B.B.B and C.C.C.C; in case there was also an agent D.D.D.D exporting towards the replicator, its packets would intuitively remain untagged. Tags are matched by a tee_receivers map, see above the two pool definitions commented out containing the 'tag' keyword: the definition would cause untagged packets (tag=0) to be replicated only to pool #1 whereas packets tagged as 100 (tag=100) to be replicated only to pool #2. More examples in the pretag.map.example and tee_receivers.lst.example files in the examples/ sub-tree: set_tag=100 ip=A.A.A.A set_tag=100 ip=B.B.B.B set_tag=100 ip=C.C.C.C To enable the transparent mode, the tee_transparent should be commented out. It preserves the original IP address of the NetFlow/sFlow sender while replicating by essentially spoofing it. This feature is not global and can be freely enabled only on a subset of the active replicators. It requires super-user permissions in order to run. Concluding note: 'tee' plugin is not compatible with different plugins - within the same daemon instance. So if in the need of using pmacct for both collecting and replicating data, two separate instances must be used (intuitively with the replicator instance feeding the collector one). XVa. Splitting and dissecting data while replicating When replicating, it is possible to perform finer-grained filtering, ie. against flow-specific primitives. For example: replicate flows from or to MAC address X1, X2 .. Xn to receiver Y or replicate flows in VLAN W to receiver Z. The feature works by inspecting the original packet and dissecting it as needed, one of the most popular use-cases being IXPs replicating flows back to the members originating and/or receiving them. The feature is available for sFlow and NetFlow/IPFIX. Some of the supported primitives are: source/ destination MAC addresses and input/output interfaces ifindex; the full list of primitives is available in examples/pretag.map.example (look for "sfacctd when in 'tee' mode" or "nfacctd when in 'tee' mode"). The feature is configured just like selective teeing shown in the previous section. Incoming packets are tagged with a pre_tag_map and then matched to a receiver in tee_receivers. For example: replicate flows from/to MAC address XX:XX:XX:XX:XX:XX to receiver Y, flows from/to MAC address WW:WW:WW:WW:WW:WW to receiver Z and replicate any remaining (untagged) flows to receiver J. This is the pre_tag_map map: set_tag=100 ip=0.0.0.0/0 src_mac=XX:XX:XX:XX:XX:XX set_tag=100 ip=0.0.0.0/0 dst_mac=XX:XX:XX:XX:XX:XX set_tag=200 ip=0.0.0.0/0 src_mac=WW:WW:WW:WW:WW:WW set_tag=200 ip=0.0.0.0/0 dst_mac=WW:WW:WW:WW:WW:WW set_tag=999 ip=0.0.0.0/0 This is the tee_receivers map: id=100 ip=Y.Y.Y.Y:2100 tag=100 id=200 ip=Z.Z.Z.Z:2100 tag=200 id=999 ip=J.J.J.J:2100 tag=999 This is the relevant section from nfacctd/sfacctd configuration: [ .. ] ! tee_transparent: true maps_index: true ! plugins: tee[a] ! tee_receivers[a]: /path/to/tee_receivers.lst pre_tag_map[a]: /path/to/pretag.map Along with dissected flows, it is possible to replicate also the original packet as-is. This can be done in a separate 'tee' plugin with no or a simple pre_tag_map defined. Extending the example above, we instantiate two plugins; 'a' is as per the previous example, 'b' is to replicate full packets (as in plain, non-dissected replication): [ .. ] ! tee_transparent: true maps_index: true ! plugins: tee[a], tee[b] ! tee_receivers[a]: /path/to/tee_receivers_a.lst pre_tag_map[a]: /path/to/pretag_a.map ! tee_receivers[a]: /path/to/tee_receivers_b.lst pre_tag_map[a]: /path/to/pretag_b.map tee_receivers_a.lst and pretag_a.map are precisely as in the previous example. This is the pretag_b.map map: set_tag=100 ip=0.0.0.0/0 This is the tee_receivers_b.map map: id=100 ip=H.H.H.H:2100 tag=100 Defining a simple pre_tag_map as one where no entries require dissecting flows (ie. tagging on source_id, agent_id, ip, etc. keys) and a complex pre_tag_map as one that requires dissecting flows (ie. tagging on vlan, src_mac, dst_net, etc. keys) this is the table of truth for stopping or passing replicated data: no pre_tag_map | simple pre_tag_map | complex pre_tag_map | | dissected no | no | yes | | full yes | yes | no There are a few restrictions to the feature: 1) for sFlow, only sFlow v5 flow samples are supported, ie. no sFlow v2/v4 nor counter samples; 2) for NetFlow/ IPFIX, templates and option data is broadcasted to configured tee receivers (regardless of tags); 3) once split, flows are not muxed back together, ie. in case multiple samples part of the same packet are to be replicated to the same receiver; 4) sequence numbers are untouched: the most obvious cases being receivers may detect non-increasing sequencing or false duplicates. If you are negatively affected by any of these restrictions or limitations or you need other primitives to be supported by this feature, please get in touch. XVI. Quickstart guide to setup the IS-IS daemon pmacct integrates an IS-IS daemon as part of the IP accounting collectors. Such daemon is run as a thread within the collector core process. The idea is to receive data-plane information, ie. via NetFlow, sFlow, etc., and control-plane information via IS-IS. Currently a single L2 P2P neighborship, ie. over a GRE tunnel, is supported. The daemon is currently used for the purpose of route resolution. A sample scenario could be that more specific internal routes might be configured to get summarized in BGP while crossing cluster boundaries. Pre-requisite for the use of the IS-IS daemon is that the pmacct package has to be configured for compilation with threads, this line will do it: shell> ./configure XVIa. Preparing the collector for the L2 P2P IS-IS neighborship It's assumed the collector sits on an Ethernet segment and has not direct link (L2) connectivity to an IS-IS speaker, hence the need to establish a GRE tunnel. While extensive literature and OS specific examples exist on the topic, a brief example for Linux, consistent with rest of the chapter, is provided below: ip tunnel add gre2 mode gre remote 10.0.1.2 local 10.0.1.1 ttl 255 ip link set gre2 up The following configuration fragment is sufficient to set up an IS-IS daemon which will bind to a network interface gre2 configured with IP address 10.0.1.1 in an IS-IS area 49.0001 and a CLNS MTU set to 1400: isis_daemon: true isis_daemon_ip: 10.0.1.1 isis_daemon_net: 49.0001.0100.0000.1001.00 isis_daemon_iface: gre2 isis_daemon_mtu: 1400 ! isis_daemon_msglog: true XVIb. Preparing the router for the L2 P2P IS-IS neighborship Once the collector is ready, the remaining step is to configure a remote router for the L2 P2P IS-IS neighborship. The following bit of configuration (based on Cisco IOS) will match the above fragment of configuration for the IS-IS daemon: interface Tunnel0 ip address 10.0.1.2 255.255.255.252 ip router isis tunnel source FastEthernet0 tunnel destination XXX.XXX.XXX.XXX clns mtu 1400 isis metric 1000 ! router isis net 49.0001.0100.0000.1002.00 is-type level-2-only metric-style wide log-adjacency-changes passive-interface Loopback0 ! XVII. Quickstart guide to setup the BMP daemon BMP can be run as a stand-alone collector daemon (pmbmpd) or as a thread within one of the traffic accounting daemons (ie. nfacctd). The stand-alone daemon is suitable for consuming BMP data only, real-time or at regular intervals; the thread solution is suitable for correlation of BMP with other data sources, ie. NetFlow, IPFIX, sFlow, etc.. The implementation bases on rfc7854 and is in-sync with most recent RFCs and draft-ietf-grow-bmp-* IETF documents (ie. rfc8671, ietf-grow-bmp-local-rib, ietf-grow-bmp-tlv, etc.). If unfamiliar with BMP, to quote rfc7854: "BMP is intended to provide a more convenient interface for obtaining route views for research purpose than the screen-scraping approach in common use today. The design goals are to keep BMP simple, useful, easily implemented, and minimally service-affecting.". The BMP daemon currently supports BMP data, events and stats, ie. initiation, termination, peer up, peer down, stats and route monitoring messages (that is no route mirroring messages; please get in touch if an implementation is wanted in this sense). The daemon enables to write BMP messages to files, AMQP and Kafka brokers, real-time (msglog) or at regular time intervals (dump). Also, route monitoring messages are saved in a RIB structure for IP prefix lookup. All features export data formatted as JSON or Avro messages. Please review the section "Compiling pmacct with JSON support" and, if planning to use Avro encoding, also the section "Compiling pmacct with Avro support". If writing to AMQP or Kafka brokers, compiling against RabbitMQ or Kafka libraries is required; read more in respectively the "Running the RabbitMQ/AMQP plugin" or "Running the Kafka plugin" sections of this document. If making use of the Schema Registry component of the Confluent Platform please also review the "Running the Kafka plugin" section. Following a simple example on how to configure nfacctd to enable the BMP thread to a) log, in real-time, BGP stats, events and routes received via BMP to a text-file (bmp_daemon_msglog_file) and b) dump the same (ie. BGP stats and events received via BMP) to a text-file and at regular time intervals (bmp_dump_refresh_time, bmp_dump_file): bmp_daemon: true ! bmp_daemon_msglog_file: /path/to/bmp-$peer_src_ip.log ! bmp_dump_file: /path/to/bmp-$peer_src_ip-%H%M.dump bmp_dump_refresh_time: 60 Following a simple example on how to configure nfacctd to enable the BMP thread to a) log, in real-time, BGP stats, events and routes received via BMP to a Kafka broker (bmp_daemon_msglog_kafka_topic) and b) dump the same (ie. BGP stats and events received via BMP) to a text-file and at regular time intervals (bmp_dump_refresh_time, bmp_dump_kafka_topic): bmp_daemon: true ! bmp_daemon_msglog_kafka_topic: pmacct.bmp-msglog ! bmp_dump_kafka_topic: pmacct.bmp-dump bmp_dump_refresh_time: 60 ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! bmp_dump_config_file: /path/to/librdkafka.conf The equivalent bmp_daemon_msglog_amqp_routing_key and bmp_dump_amqp_routing_key config directives can be used to make the above example work against a RabbitMQ broker. A sample of both the BMP msglog and dump formats are captured in the following document: docs/MSGLOG_DUMP_FORMATS Setting up the stand-alone BMP collector daemon, pmbmpd, is the exact same as the configuration above except the 'bmp_daemon: true' line can be skipped. Following is an example of how a Cisco router running IOS/IOS-XE (15.4(2)T) should be configured in order to export BMP data to a collector: router bgp 64512 bmp server 1 address X.X.X.X port-number 1790 initial-delay 60 failure-retry-delay 60 flapping-delay 60 stats-reporting-period 300 activate exit-bmp-server-mode ! neighbor Y.Y.Y.Y remote-as 64513 neighbor Y.Y.Y.Y bmp-activate all neighbor Z.Z.Z.Z remote-as 64514 neighbor Z.Z.Z.Z bmp-activate all Following is an example how a Cisco router running IOS-XR (6.2.1) should be configured in order to export BMP data to a collector: router bgp 64512 neighbor Y.Y.Y.Y bmp-activate server 1 neighbor Z.Z.Z.Z bmp-activate server 1 ! ! bmp server 1 host X.X.X.X port 1790 description -- fretta -- update-source GigabitEthernet0/0/0/10 initial-delay 60 initial-refresh delay 60 stats-reporting-period 300 initial-refresh delay 10 ! Following is an example how a Juniper router should be configured in order to export BMP data to a collector: routing-options { bmp { station FQDN { connection-mode active; monitor enable; route-monitoring { pre-policy; post-policy; } station-address X.X.X.X; station-port 1790; } } } Following is an example how a Huawei router should be configured in order to export BMP data to a collector: bmp statistics-timer 3600 # bmp-session 192.0.2.1 tcp connect port 1790 connect-interface GigabitEthernet0/3/6 # monitor peer 198.51.100.19 route-mode ipv4-family vpnv4 adj-rib-in pre-policy route-mode ipv4-family vpnv4 adj-rib-in post-policy route-mode ipv4-family vpnv4 adj-rib-out pre-policy route-mode ipv4-family vpnv4 adj-rib-out post-policy # monitor peer 198.51.100.25 route-mode ipv4-family vpnv4 adj-rib-in pre-policy route-mode ipv4-family vpnv4 adj-rib-in post-policy route-mode ipv4-family vpnv4 adj-rib-out pre-policy route-mode ipv4-family vpnv4 adj-rib-out post-policy # monitor vpn-instance A route-mode ipv4-family unicast local-rib Contribution of further configuration examples for Cisco and Juniper devices and/or other relevant vendors is more than welcome. XVIII. Quickstart guide to setup Streaming Telemetry collection Quoting Cisco IOS-XR Telemetry Configuration Guide at the time of this writing: "Streaming telemetry lets users direct data to a configured receiver. This data can be used for analysis and troubleshooting purposes to maintain the health of the network. This is achieved by leveraging the capabilities of machine-to- machine communication. The data is used by development and operations (DevOps) personnel who plan to optimize networks by collecting analytics of the network in real-time, locate where problems occur, and investigate issues in a collaborative manner.". Streaming telemetry support comes in pmacct in two flavours: 1) a telemetry thread can be started in existing daemons, ie. sFlow, NetFlow/IPFIX, etc. for the purpose of data correlation and 2) a new daemon pmtelemetryd for standalone consumpton of data. Streaming telemetry data can be logged real-time and/or dumped at regular time intervals to flat-files, RabbitMQ or Kafka brokers. All features export data formatted as JSON messages, hence compiling pmacct against libjansson is a requirement. See how to compile pmacct with JSON/ libjansson support in the section "Compiling pmacct with JSON support" of this document. If writing to AMQP or Kafka brokers compiling against RabbitMQ or Kafka libraries is required; read more in respectively the "Running the RabbitMQ/AMQP plugin" or "Running the Kafka plugin" sections of this document. Data can be optionally consumed from a ZeroMQ queue, for example to have a pre-processor taking care of the GPB (Protobuf or Google Protocol Buffers) de-marshalling and conversion to JSON; read more about (compiling) ZeroMQ in the "Internal buffering and queueing" section of this document; also read more about gRPC support and GPB de-marshalling in telemetry/README.telemetry . From a configuration standpoint both the thread (ie. telemetry configured part of nfacctd) and the daemon (pmtelemetryd) are configured the same way except the thread must be explicitely enabled with a 'telemetry_daemon: true' config line. Hence the following examples hold for both the thread and the daemon setups. Following is a config example to receive telemetry data in JSON format over UDP port 1620 and log it real-time to flat-files: ! Telemetry thread configuration ! telemetry_daemon: true ! telemetry_daemon_port_udp: 1620 telemetry_daemon_decoder: json ! telemetry_daemon_msglog_file: /path/to/spool/telemetry-msglog-$peer_src_ip.txt ! telemetry_daemon_msglog_amqp_routing_key: telemetry-msglog ! telemetry_daemon_msglog_kafka_topic: telemetry-msglog Following is a config example to receive telemetry data with Cisco proprietary header, in GPB format over TCP port 1620 and dump it at 60 secs time intervals to flat-files: ! Telemetry thread configuration ! telemetry_daemon: true ! telemetry_daemon_port_tcp: 1620 telemetry_daemon_decoder: cisco_v1 ! telemetry_dump_file: /path/to/spool/telemetry-dump-$peer_src_ip-%Y%m%d-%H%M.txt telemetry_dump_latest_file: /path/to/spool/telemetry-dump-$peer_src_ip.latest ! telemetry_dump_amqp_routing_key: telemetry-dump ! telemetry_dump_kafka_topic: telemetry-dump ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! telemetry_dump_kafka_config_file: /path/to/librdkafka.conf ! telemetry_dump_refresh_time: 60 Following is a config example to receive JSON-formatted telemetry data from a pre-processor over a ZeroMQ queue (see telemetry/README.telemetry for further info, ie. gRPC support and GPB de-marshalling): ! Telemetry thread configuration ! telemetry_daemon: true ! telemetry_daemon_zmq_address: 127.0.0.1:50000 telemetry_daemon_decoder: json ! telemetry_daemon_msglog_file: /path/to/spool/telemetry-msglog-$peer_src_ip.txt ! telemetry_daemon_msglog_amqp_routing_key: telemetry-msglog ! telemetry_daemon_msglog_kafka_topic: telemetry-msglog ! ! [Optional] librdkafka config for buffer tuning, ssl config, etc. ! telemetry_daemon_msglog_kafka_config_file: /path/to/librdkafka.conf A sample of both the Streaming Telemetry msglog and dump formats are captured in the following document: docs/MSGLOG_DUMP_FORMATS XIX. Running the print plugin to write to regular files and named pipes pmacct can also output to regular files and named pipes via the 'print' plugin. Dynamic filenames are supported. Output encoding is either text-based using JSON or CSV or binary schema-based using Apache Avro; encoding can be set via the 'print_output' config directive. Interval between writes can be configured via the 'print_refresh_time' config directive. An example follows on how to write to regular files in CSV format, every 15 minutes and aggregate data in 15 minutes time-bins (print_history): print_refresh_time: 900 print_history: 15m print_output: csv print_output_file: /path/to/file-%Y%m%d-%H%M.txt print_history_roundoff: m Which, over time, would produce a series of files as follows: -rw------- 1 paolo paolo 2067 Nov 21 00:15 blabla-20111121-0000.txt -rw------- 1 paolo paolo 2772 Nov 21 00:30 blabla-20111121-0015.txt -rw------- 1 paolo paolo 1916 Nov 21 00:45 blabla-20111121-0030.txt -rw------- 1 paolo paolo 2940 Nov 21 01:00 blabla-20111121-0045.txt JSON output requires compiling pmacct against Jansson library. See how to compile pmacct with JSON/libjansson support in the section "Compiling pmacct with JSON support" of this document. Avro output requires compiling pmacct against libavro library. See how to compile pmacct with Avro support in the section "Compiling pmacct with Apache Avro support" of this document. Splitting data into time-bins is supported via print_history directive. When enabled, time-related variable substitutions of dynamic print_output_file names are determined using this value. It is supported to define print_refresh_time values shorter than print_history ones by setting print_output_file_append to true (which is generally also recommended to prevent that unscheduled writes to disk, ie. due to caching issues, overwrite existing file content). A sample config follows: print_refresh_time: 300 print_output: csv print_output_file: /path/to/%Y/%Y-%m/%Y-%m-%d/file-%Y%m%d-%H%M.txt print_history: 15m print_history_roundoff: m print_output_file_append: true Writing to named pipes is an easy way to stream data into 3rd party tools without adding external dependencies (ie. RabbitMQ, Kafka). The named pipe must be manually created before starting the pmacct daemon. From a config standpoint using a named pipe is transparent and hence all the examples provided so far in this section do apply to named pipes as well. Writing to regular files is a suitable method to batch ingest data into 3rd party tools (typically, but not limited to, modern noSQL databases like ElasticSearch, InfluxDB, etc.). An example is the pmacct-to-elasticsearch project https://github.com/pierky/pmacct-to-elasticsearch . XX. Quickstart guide to setup GeoIP lookups pmacct can perform GeoIP country lookups against a Maxmind DB v1 (--enable-geoip) and against a Maxmind DB v2 (--enable-geoipv2). A v1 database enables resolution of src_host_country and dst_host_country primitives only. A v2 database enables resolution of presently supported GeoIP-related primitives, ie. src_host_country, src_host_pocode, src_host_coords, dst_host_country, dst_host_pocode and dst_host_coords. Pre-requisite for the feature to work are: a) a working installed Maxmind GeoIP library and headers and b) a Maxmind GeoIP database (freely available). Two steps to quickly start with GeoIP lookups in pmacct: GeoIP v1 (libGeoIP): * Have libGeoIP library and headers available to compile against; have a GeoIP database also available: http://dev.maxmind.com/geoip/legacy/install/country/ * To compile the pmacct package with support for GeoIP lookups, the code must be configured for compilation as follows: shell> ./configure --enable-geoip [ ... ] But, for example, should you have installed libGeoIP in /usr/local/geoip and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export GEOIP_LIBS="-L/usr/local/geoip/lib -lgeoip" shell> export GEOIP_CFLAGS="-I/usr/local/geoip/include" shell> ./configure --enable-geoip [ ... ] * Include as part of the pmacct configuration the following fragment: ... geoip_ipv4_file: /path/to/GeoIP/GeoIP.dat aggregate: src_host_country, dst_host_country, ... ... GeoIP v2 (libmaxminddb): * Have libmaxminddb library and headers to compile against, available at: https://github.com/maxmind/libmaxminddb/releases ; have also a database available: https://dev.maxmind.com/geoip/geoip2/geolite2/ . Only the database binary format is supported. * To compile the pmacct package with support for GeoIP lookups, the code must be configured for compilation as follows: shell> ./configure --enable-geoipv2 [ ... ] But, for example, should you have installed libmaxminddb in /usr/local/geoipv2 and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export GEOIPV2_LIBS="-L/usr/local/geoipv2/lib -lmaxminddb" shell> export GEOIPV2_CFLAGS="-I/usr/local/geoipv2/include" shell> ./configure --enable-geoipv2 [ ... ] * Include as part of the pmacct configuration the following fragment: ... geoipv2_file: /path/to/GeoIP/GeoLite2-Country.mmdb aggregate: src_host_country, dst_host_country, ... ... Concluding notes: 1) The use of --enable-geoip is mutually exclusive with --enable-geoipv2; 2) more fine-grained GeoIP lookup primitives (ie. cities, states, counties, metro areas, zip codes, etc.) are not yet supported: should you be interested into any of these, please get in touch. XXI. Using pmacct as traffic/event logger This use-case has been fostered particularly by the use of NetFlow/IPFIX as generic transport, see for example Cisco NEL and Cisco NSEL. Key to logging are time-stamping primitives, timestamp_start and timestamp_end: the former records the likes of libpcap packet timestamp, sFlow sample arrival time, NetFlow observation time and flow first switched time; timestamp_end does currently only makes sense for logging flow data via NetFlow/IPFIX. Still, the exact boundary between aggregation and logging can be defined via the aggregation method, ie. no assumptions are made. An example to log traffic flows follows: ! ... ! plugins: print[traffic] ! aggregate[traffic]: src_host, dst_host, peer_src_ip, peer_dst_ip, in_iface, out_iface, timestamp_start, timestamp_end, src_port, dst_port, proto, tos, src_mask, dst_mask, src_as, dst_as, tcpflags print_output_file[traffic]: /path/to/traffic-%Y%m%d_%H%M.txt print_output[traffic]: csv print_history[traffic]: 5m print_history_roundoff[traffic]: m print_refresh_time[traffic]: 300 ! print_cache_entries[traffic]: 9999991 print_output_file_append[traffic]: true ! ! ... An example to log specifically CGNAT (Carrier Grade NAT) events from a Cisco ASR1K box follows: ! ... ! plugins: print[nat] ! aggregate[nat]: src_host, post_nat_src_host, src_port, post_nat_src_port, proto, nat_event, timestamp_start print_output_file[nat]: /path/to/nat-%Y%m%d_%H%M.txt print_output[nat]: json print_history[nat]: 5m print_history_roundoff[nat]: m print_refresh_time[nat]: 300 ! print_cache_entries[nat]: 9999991 print_output_file_append[nat]: true ! ! ... The two examples above can intuitively be merged in a single configuration so to log down in parallel both traffic flows and events. To split flows accounting from events, ie. to different files, a pre_tag_map and two print plugins can be used as follows: ! ... ! pre_tag_map: /path/to/pretag.map ! plugins: print[traffic], print[nat] ! pre_tag_filter[traffic]: 10 aggregate[traffic]: src_host, dst_host, peer_src_ip, peer_dst_ip, in_iface, out_iface, timestamp_start, timestamp_end, src_port, dst_port, proto, tos, src_mask, dst_mask, src_as, dst_as, tcpflags print_output_file[traffic]: /path/to/traffic-%Y%m%d_%H%M.txt print_output[traffic]: csv print_history[traffic]: 5m print_history_roundoff[traffic]: m print_refresh_time[traffic]: 300 ! print_cache_entries[traffic]: 9999991 print_output_file_append[traffic]: true ! pre_tag_filter[nat]: 20 aggregate[nat]: src_host, post_nat_src_host, src_port, post_nat_src_port, proto, nat_event, timestamp_start print_output_file[nat]: /path/to/nat-%Y%m%d_%H%M.txt print_output[nat]: json print_history[nat]: 5m print_history_roundoff[nat]: m print_refresh_time[nat]: 300 ! print_cache_entries[nat]: 9999991 print_output_file_append[nat]: true ! ! ... In the above configuration both plugins will log their data in 5 mins files basing on the 'print_history[]: 5m' configuration directive, ie. traffic-20130802-1345.txt traffic-20130802-1350.txt traffic-20130802-1355.txt etc. Granted appending to output file is set to true, data can be refreshed at shorter intervals than 300 secs. This is a snippet from /path/to/pretag.map referred above: set_tag=10 ip=A.A.A.A sample_type=flow set_tag=20 ip=A.A.A.A sample_type=event set_tag=10 ip=B.B.B.B sample_type=flow set_tag=20 ip=B.B.B.B sample_type=event ! ! ... XXII. Connecting pmacct to a Redis cache Since version 1.7.5, pmacct daemons can connect to a Redis cache. The main use-case currenly covered is: registering every stable daemon component (ie. plugins, threads, etc. but not writers for example) in a table so to have, when running a cluster comprising several daemons / components, an olistic view of what is currently running and where; shall a component stop running or crash it will disappear from the inventory. Over time it is expected that the amount of use-cases will increase to include specific features where one daemon can obtain relevant information about other daemons running in the cluster. Requirement to use the Redis feature plugin is the Hiredis library available here: https://github.com/redis/hiredis . Once this is installed, pmacct can be configured for compiling. pmacct makes use of pkg-config for finding libraries and headers location and checks some default locations, ie. /usr/local/lib and /usr/local/include. If this is satisfactory, all you should do is just: shell> ./configure --enable-redis But, for example, should you have installed Hiedis in /usr/local/redis and pkg-config is unable to help, you can supply this non-default location as follows (assuming you are running the bash shell): shell> export REDIS_LIBS="-L/usr/local/redis/lib -lhiredis" shell> export EDIS_CFLAGS="-I/usr/local/redis/include" shell> ./configure --enable-redis Following a configuration snippet showing a basic configuration for the Redis feature. redis_host points to the Redis cache whereas cluster_* directives essentially form a pmacct cluster (cluster_name, every cluster should have a different name string, and cluster_id, an unique id inside a certain cluster): cluster_name: prod cluster_id: 1 ! redis_host: 127.0.0.1:6379 XXIII. Miscellaneous notes and troubleshooting tips This chapter will hopefully build up to the point of providing a taxonomy of popular cases to troubleshoot by daemon and what to do. Although that is the plan, the current format is sparse notes. When reporting a bug: please report in all cases the pmacct version that you are experiencing your issue against; the CLI option -V of the daemon you are using returns all the info needed (daemon, version, specific release and options compiled in). Do realise that if using a pre-packaged version from your OS and/or old code (ie. not master code on GitHub or latest official release), you may be very possibly asked to try one of these first. Finally, please refrain to open issues on GitHub if not using master code (use the pmacct-discussion mailing list or unicast email instead). a) In cases of errors at configure script time (ie. library not found, headers not found, etc.), additional info can be found in config.log at the end of the 'Core tests' section. Also if reporting an issue related to configure time, it is good idea to supply the config.log file as well. Here are recap some popular issues when compiling pmacct or linking it at runtime against shared libraries: 1) /usr/local/sbin/pmacctd: error while loading shared libraries: librabbitmq.so.4: cannot open shared object file: No such file or directory This can happen at runtime and, especially in case of freshly downloaded and compiled libraries, it is a symptom that after installing the shared library, ldconfig was not called. Or alternatively that the directory where the library is located is not inserted in /etc/ld.so.conf or in any files included it includes. When not having super-user privileges, this can be fixed in the own environment setting the LD_LIBRARY_PATH variable. 2) json_array_foreach(json_list, key, value) { ^ nfv9_template.c: In function ‘nfacctd_offline_read_json_template’: nfv9_template.c:572:53: error: expected ‘;’ before ‘{’ token This can happen at compile time and and is a bit tricky to hint. In this example the function json_array_foreach() is not being recognized, in other words while the library could be located, it does not contain the specific function. This is a symptom that the library version in use is too old. Typical situation is when using a packaged library rather than a freshly downloaded and compiled latest stable release. 3) /usr/local/lib/libpcap.so: undefined reference to `pcap_lex' collect2: error: ld returned 1 exit status make[2]: *** [pmacctd] Error 1 This can happen at compile time and it is a symptom that the needed library could not be located by the linker. This is a symptom that the library could be in some non-standard location and the linked need an hint. For libpcap --with-pcap-libs knob is available at configure time; for all other libraries the library_LIBS and library_CFLAGS environment variables are available. See examples in the "Configuring pmacct for compilation and installing" section of this document. b) In case of crashes of an any process, regardless if predictable or not, the advice is to run the daemon with "ulimit -c unlimited" so to generate a core dump. The core dump file location, on Linux, is determined by the following file: /proc/sys/kernel/core_pattern : if the value is "core", then the file is placed in the directory where the daemon is started so it is good to take care of that. pmacct developers will then ask for one or both of the following: 1) the core file along with the crashing executable and its configuration be made available for further inspection and/or 2) a backtrace in GDB obtained via the following two steps: shell> gdb /path/to/executable /path/to/core Then once in the gdb console the backtrace output can be obtained with the following command: gdb> bt As an alternative to gdb, the valgrind tool can be used which, upon crashing, will simply print out the backtrace: shell> valgrind /path/to/executable If the dmesg command or system logs reveal a line like the following one: Jan 01 00:00:00 xxxx kernel: [4075819.569587] nfacctd[51817]: segfault at 10 ip 00007f77f448ad44 sp 00007ffc6974ed70 error 4 .. In certain cases, ie. if the crash is not inside a shared library, this can return useful information for debugging when examined with addr2line; using the example above: shell> addr2line /path/to/nfacctd 00007f77f448ad44 Optionally, especially if the issue can be easily reproduced, the daemon can be re-configured for compiling with the --enable-debug flag so to produce extra info suitable for troubleshooting. There is a whole range of cases where the crash could be caused by corrupting the heap and these are evidenced when a 'bt' in gdb highlights a malloc() call as point of crash; while these issues often times boil down to erroneous coding, they are subtle, hard to reproduce and platform / OS dependant. When facing such issues, launching the daemon with the MALLOC_CHECK_ environment variable set to 2, ie.: shell> MALLOC_CHECK_=2 shell> export MALLOC_CHECK_ Would return additional useful information for the troubleshooting process. At times this action - that elicits the use of an alternate malloc() call - may even work as a work-around (if falling in this condition it is recommended to not use this 'mask' as long-term solution, that is, please report the issue). The use of Docker containers is getting increasingly popular. The valgrind tool can be used when a crash is experienced in a container. The following example applies to any of the official pmacct containers (running on top of Debian): shell> docker run -it --entrypoint bash # apt-get update && apt-get install -y valgrind # valgrind /path/to/executable c) In case of (suspected) memory leaks, the advice is to: 1) re-compile pmacct with "./configure --enable-debug "; --enable-debug sets as CFLAGS -O0 -g -Wall where especially -O0 is capital since it disables any code optimizations the compiler may introduce; 2) run the resulting daemon under valgrind, "valgrind --leak-check=yes /path/to/executable ". A memory leak is confirmed if the amount of "definitely lost" bytes keeps increasing over time. d) In the two cases of nfacctd/sfacctd or nfprobe/sfprobe not showing signs of input/output data: 1) check with tcpdump, ie. "tcpdump -i -n " (for uacctd use -i nflog:), that packets are emitted/received. Optionally Wireshark (or its cli tool tshark) can be used, in conjunction with decoders ('cflow' for NetFlow/IPFIX and 'sflow' for sFlow), to validate packets are consistent; this proofs there is no filtering taking place in between exporters and collector; 2) check firewall settings on the collector box, ie. "iptables -L -n" on Linux (disable or do appropriate holes): tcpdump may see packets hitting the listening port as, in normal kernel operations, the filtering happens after the raw socket (the one used by tcpdump) is served; you can also check with 3rd party equivalent tools or netcat, "nc -l -u -p ", that the same behaviour is obtained as with pmacct; finally, if running on a SELinux enabled system, consider that it could be interfering too; 3) check the process list to confirm whether there is some stuck / forgotten running process which may be consuming data in place of a newly started one; 4) when not using ZeroMQ for internal buffering (plugin_pipe_zmq set to true) and especially in case of copy/paste of configs or if using a config from a production system in lab, disable/double-check values for internal buffering: if set too high they will likely retain data internally to the daemon; 5) if multiple interfaces are configured on a system, try to disable rp_filter. See http://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.kernel.rpf.html for more info on RP filtering. The value of rp_filter files in /proc must be set to zero (ie. "echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter") in order to disable RP filtering. Also, if working on a cloud instance, consider often times these are not configured by default to pass traffic through. These appear popular issues when replicating flow data with tee_transparent feature enabled (that is, packet spoofing); 6) in case aggregate_filter is in use: the feature expects a libpcap-style filter as value. BPF filters are sensible to both VLAN tags and MPLS labels: if, for example, the traffic is VLAN tagged and the value of aggregate_filter is 'src net X.X.X.X/Y', there will be no match for VLAN-tagged traffic from src net X.X.X.X/Y; the filter should be re-written as 'vlan and src net X.X.X.X/Y'; 7) in case of NetFlow v9/IPFIX collection, two protocols that are template-based, the issue may be with templates not being received by nfacctd (in which case by enabling debug you may see "Discarded NetFlow v9/IPFIX packet (R: unknown template [ .. ]" messages in your logs); you can confirm whether templates are being exported/replicated/received with a touch of "tshark -d udp.port==,cflow -R cflow.template_id -2"; it may also happen the opposite: templates are received but no data packets are being sent (ie. because sampling is not configured on the actual interfaces on the exporting device): in this case tshark would only show periodic data being received (ie. every 30 secs, 60 secs, etc.) rather than a more constant stream of data. e) In the case of inconsistent output - inconsistent defined as replaying the same set of data, output produced by the daemon differs - of nfacctd/sfacctd: 1) check the basics: whether another nfacctd/sfacctd is listening on the very same port; this is legit behaviour due to behaviour of SO_REUSEPORT, in brief: share load among multiple sockets listening on the same port, and SO_REUSEADDR, in brief: don't wait for a closing socket to be closed in order to bind a new one to the same port, options used on the listening socket; 2) check all tips about buffering provided slightly later in this document. f) Replay packets can be needed, for example, to troubleshoot the behaviour of one of the pmacct daemons. A capture in libpcap format, suitable for replay, can be produced with tcpdump. For example to produce a trace for NetFlow/IPFIX/sFlow this is the command-line: "tcpdump -i -n -s 0 -w port "; for ULOG/NFLOG on Linux the interface should be in the format "-i nflog:" instead. For traces over extended periods of time, ie. to troubleshoot specific bogus packets triggering crashes or capture NetFlow v9/IPFIX templates, optionally the -G tcpdump option can be specified to rotate the -w output_file each specified seconds interval (read more on tcpdump man page). Once the trace has been created, trace file(s) can be replayed by pmacct daemons using the pcap_savefile (-I) and, optionally, the pcap_savefile_wait (-W) directives, ie.: "nfacctd -I <..>". For more advanced use-cases, ie. loop indefinitely through the pcap file and run it with a speed multiplicator in order to stress test the daemon, the tcpreplay tool can be used. In this case, before replaying NetFlow/IPFIX/sFlow, L2/L3 of captured packets may need to be adjusted in order to reflect the lab/ replay environment; this can be done with the tcprewrite tool of the tcpreplay package, ie.: "tcprewrite --enet-smac= --enet-dmac= -S -D --fixcsum --infile= --outfile=". Then the output file from tcprewrite can be supplied to tcpreplay for the actual replay to the pmacct daemon, ie.: "tcpreplay -x -i ". g) Buffering is often an element to tune in order to make sure that output is complete (packet loss may lead to incomplete results but also configuring too large buffers). While buffering internal to pmacct (configured with plugin_buffer_size / plugin_pipe_size or plugin_pipe_zmq) returns warning messages in case of data loss, buffering between pmacct and the kernel (configured with nfacctd_pipe_size and its equivalents) may be more tricky to detect and sometimes issues can only be inferred by symptoms (like sequence number checks for NetFlow v9/IPFIX). For nfacctd and sfacctd daemons, two commands useful to check this kind of buffering on Linux systems are: 1) "cat /proc/net/udp" or "cat /proc/net/udp6" ensuring that "drops" value is not increasing and 2) "netstat -s" ensuring, under the section UDP, that errors are not increasing (since this command returns system-wide counters, the counter-check would be: stop the pmacct daemon running and, granted the counter was increasing, verify it does not increase anymore). For pmacctd, an UNIX signal can be sent to the daemon so that the amount of dropped packets is reported in the log output (ie. kill -USR1 ). Finally, if troubleshooting incomplete output, please review tips about inconsistent output slightly earlier in this document. h) BMP, the BGP Monitoring Protocol, has got drafting traction at IETF. New protocol features drive the need for inter-op testing. The BMP play tool ( https://github.com/paololucente/bmp_play ) is a simple script to record and replay raw BMP packets in order to reproduce issues. An example of how this can be done, here: Step 1: export BMP data from an exporter to a host/port where a bmp_play script is listening to. bmp_play will then save raw BMP data to a file: shell> bmp_play.py -m record -p 1791 -f bmp.dump Step 2: the file containing raw BMP data can be replayed at will with the same bmp_play script to a pmbmpd daemon: shell 1> bmp_play.py -m play -p 1790 -f bmp.dump -d 127.0.0.1 shell 2> pmbmpd -l 1790 -d -o bmp.log Additionally, since version 1.7.5, pmbmpd supports pcap_savefile (-I) to replay a pcap trace that includes BMP packets; packets functional to the house-keeping of the TCP session are safely ignored and pcap_filter helps on replay to trash unrelevant (non BMP) packets; yet this method is less preferred to the capture of raw data via bmp_play. i) packet classification using the nDPI library is among the new features of pmacct 1.7. Following are some tips on how to help by providing meaningful report of issues you may be experiencing in this area. 1) Please follow guidelines in the section "Quickstart guide to packet classification" of this document; 2) please avoid generic reporting; remember that the most effective way troubleshoot any issue related to packet classification is by the authors being able to reproduce the issue or for them to verify first-hand the issue: whenever possible please share a traffic capture in pcap format or grant remote-access to your testbed; 3) it is OK to compare classification results achieved with a 3rd party tool also using nDPI for classification; in case of different results, please show the actual results when reporting the issue and please elaborate as much as possible how the comparison was done (ie. say how it is being ensured that the two data-sets are the same or as much as possible similar); 4) excluded from these guidelines are problems related to nDPI but unrelated to classification, ie. memory leaks, performance issues, crashes, etc. for which you can follow the other guide lines in this document in the "Miscellaneous notes and troubleshooting tips" section. j) if supported and if enabled on the system, the SO_REUSEPORT feature can be leveraged on Linux and most BSDs where it is part of the standard kernel: it allows multiple daemons to bind to the same local address and port in order to load-balance processing of incoming packets. Here a reference to a presentation of this feature for Linux: https://domsch.com/linux/lpc2010/Scaling_techniques_for_servers_with_high_connection%20rates.pdf To enable SO_REUSEPORT on a Linux system 'sysctl net.core.allow_reuseport=1'. Also the processes must be launched by the same user. pmacct-1.7.8/Makefile.am0000644000175000017500000000674014354105275014055 0ustar paolopaoloSUBDIRS = src examples/custom if USING_BGP_BINS SUBDIRS += examples/lg endif ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = include sql examples docs CONFIG-KEYS FAQS QUICKSTART UPGRADE if USING_SQL EXTRA_DIST += src/sql_common_m.c endif pmacct_data_dir = $(datarootdir)/pmacct pmacct_libs_dir = $(libdir)/pmacct pmacct_docs_dir = $(pmacct_data_dir)/docs pmacct_examples_dir = $(pmacct_data_dir)/examples pmacct_examples_arch_dir = $(pmacct_libs_dir)/examples pmacct_examples_kafka_dir = $(pmacct_examples_dir)/kafka pmacct_examples_amqp_dir = $(pmacct_examples_dir)/amqp pmacct_examples_avro_dir = $(pmacct_examples_dir)/avro if USING_BGP_BINS pmacct_examples_lg_dir = $(pmacct_examples_dir)/lg pmacct_examples_lg_arch_dir = $(pmacct_examples_arch_dir)/lg endif pmacct_examples_custom_dir = $(pmacct_examples_arch_dir)/custom if USING_SQL pmacct_sql_dir = $(pmacct_data_dir)/sql endif pmacct_data__DATA = CONFIG-KEYS FAQS QUICKSTART UPGRADE pmacct_docs__DATA = docs/IPFIX docs/LOOKING_GLASS_FORMAT docs/SIGNALS \ docs/MSGLOG_DUMP_FORMATS docs/TRIGGER_VARS pmacct_examples__DATA = examples/allow.lst.example examples/bgp_agent.map.example \ examples/bgp_md5.lst.example examples/bgp_xconnects.map.example \ examples/flow_to_rd.map.example examples/networks.lst.example \ examples/peers.map.example examples/pcap_interfaces.map.example \ examples/pmacctd-imt.conf.example examples/pmacctd-multiple-plugins.conf.example \ examples/ports.lst.example examples/pretag.map.example \ examples/primitives.lst.example examples/probe_netflow.conf.example \ examples/probe_sflow.conf.example examples/sampling.map.example \ examples/tee_receivers.lst.example examples/nfacctd-sql.conf.example \ examples/pmacctd-sql.conf.example examples/pmacctd-sqlite3.conf.example pmacct_examples_kafka__DATA = examples/kafka/kafka_consumer.py pmacct_examples_amqp__DATA = examples/amqp/amqp_receiver.py pmacct_examples_avro__DATA = examples/avro/avro_file_decoder.py if USING_BGP_BINS pmacct_examples_lg__DATA = examples/lg/pmbgp.py pmacct_examples_lg_arch__DATA = examples/lg/pmbgp endif pmacct_examples_custom__DATA = examples/custom/libcustom.la if USING_SQL pmacct_sql__DATA = sql/pmacct-create-db_bgp_v1.mysql sql/pmacct-create-db.pgsql \ sql/pmacct-create-db_v1.mysql sql/pmacct-create-db_v2.mysql \ sql/pmacct-create-db_v3.mysql sql/pmacct-create-db_v4.mysql \ sql/pmacct-create-db_v5.mysql sql/pmacct-create-db_v6.mysql \ sql/pmacct-create-db_v7.mysql sql/pmacct-create-db_v8.mysql \ sql/pmacct-create-db_v9.mysql sql/pmacct-create-table_bgp_v1.pgsql \ sql/pmacct-create-table_bgp_v1.sqlite3 sql/pmacct-grant-db.mysql \ sql/pmacct-create-table_v1.pgsql sql/pmacct-create-table_v1.sqlite3 \ sql/pmacct-create-table_v2.pgsql sql/pmacct-create-table_v2.sqlite3 \ sql/pmacct-create-table_v3.pgsql sql/pmacct-create-table_v3.sqlite3 \ sql/pmacct-create-table_v4.pgsql sql/pmacct-create-table_v4.sqlite3 \ sql/pmacct-create-table_v5.pgsql sql/pmacct-create-table_v5.sqlite3 \ sql/pmacct-create-table_v6.pgsql sql/pmacct-create-table_v6.sqlite3 \ sql/pmacct-create-table_v7_v8.pgsql sql/pmacct-create-table_v7.sqlite3 \ sql/pmacct-create-table_v8.sqlite3 sql/pmacct-create-table_v9.pgsql \ sql/pmacct-create-table_v9.sqlite3 sql/README.cos \ sql/README.custom_primitives sql/README.etype sql/README.export_proto \ sql/README.GeoIP sql/README.iface sql/README.label sql/README.mask \ sql/README.mpls sql/README.mysql sql/README.nat sql/README.pgsql \ sql/README.sampling sql/README.sqlite3 sql/README.tag2 sql/README.tunnel \ sql/README.timestamp endif pmacct-1.7.8/missing0000755000175000017500000001533614354105415013415 0ustar paolopaolo#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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 2, 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. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/src/0000755000175000017500000000000014354105415012575 5ustar paolopaolopmacct-1.7.8/src/net_aggr.h0000644000175000017500000001773314354105275014553 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NET_AGGR_H #define NET_AGGR_H /* defines */ #define NETWORKS_CACHE_ENTRIES 99991 #define NETWORKS6_CACHE_ENTRIES 32771 #define NETWORKS_CACHE_DEPTH 128 #define RETURN_NET 0 #define RETURN_AS 1 #define NET_FUNCS_N 32 /* structures */ struct networks_cache_entry { u_int32_t key; struct networks_table_entry *result; }; struct networks_cache { struct networks_cache_entry *cache; unsigned int num; struct networks6_cache_entry *cache6; unsigned int num6; }; struct networks_table { struct networks_table_entry *table; unsigned int num; struct networks6_table_entry *table6; unsigned int num6; u_int32_t maskbits[4]; time_t timestamp; }; struct networks_table_entry { u_int32_t net; u_int32_t mask; u_int8_t masknum; as_t peer_as; as_t as; struct host_addr nh; struct networks_table childs_table; }; struct networks6_cache_entry { u_int32_t key[4]; struct networks6_table_entry *result; }; struct networks6_table_entry { u_int32_t net[4]; u_int32_t mask[4]; u_int8_t masknum; as_t peer_as; as_t as; struct host_addr nh; struct networks_table childs_table; }; struct networks_table_metadata { u_int8_t level; u_int32_t childs; }; struct networks_file_data { u_int8_t zero_src_nmask; u_int8_t zero_dst_nmask; u_int8_t family; u_char *entry; }; typedef void (*net_func) (struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); /* prototypes */ extern void set_net_funcs(); extern void init_net_funcs(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void mask_src_ipaddr(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void mask_dst_ipaddr(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void mask_static_src_ipaddr(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void mask_static_dst_ipaddr(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void copy_src_mask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void copy_dst_mask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_src_ip(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_dst_ip(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_src_host(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_dst_host(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_src_nmask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_dst_nmask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_src_as(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_dst_as(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_peer_src_as(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_peer_dst_as(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void search_peer_dst_ip(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_src_host(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_dst_host(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_src_net(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_dst_net(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_src_nmask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern void clear_dst_nmask(struct networks_table *, struct networks_cache *, struct pkt_primitives *, struct pkt_bgp_primitives *, struct networks_file_data *); extern as_t search_pretag_src_as(struct networks_table *, struct networks_cache *, struct packet_ptrs *); extern as_t search_pretag_dst_as(struct networks_table *, struct networks_cache *, struct packet_ptrs *); extern void load_networks(char *, struct networks_table *, struct networks_cache *); /* wrapper */ extern void load_networks4(char *, struct networks_table *, struct networks_cache *); extern void merge_sort(char *, struct networks_table_entry *, int, int); extern void merge(char *, struct networks_table_entry *, int, int, int); extern struct networks_table_entry *binsearch(struct networks_table *, struct networks_cache *, struct host_addr *); extern void remove_dupes(char *, struct networks_table *, int); extern void networks_cache_insert(struct networks_cache *, u_int32_t *, struct networks_table_entry *); extern struct networks_table_entry *networks_cache_search(struct networks_cache *, u_int32_t *); extern void load_networks6(char *, struct networks_table *, struct networks_cache *); extern void merge_sort6(char *, struct networks6_table_entry *, int, int); extern void merge6(char *, struct networks6_table_entry *, int, int, int); extern struct networks6_table_entry *binsearch6(struct networks_table *, struct networks_cache *, struct host_addr *); extern void networks_cache_insert6(struct networks_cache *, void *, struct networks6_table_entry *); extern struct networks6_table_entry *networks_cache_search6(struct networks_cache *, void *); extern unsigned int networks_cache_hash6(void *); /* global vars */ extern net_func net_funcs[NET_FUNCS_N]; extern struct networks_table nt; extern struct networks_cache nc; extern struct networks_table_entry dummy_entry; extern int default_route_in_networks4_table; extern struct networks6_table_entry dummy_entry6; extern int default_route_in_networks6_table; #endif //NET_AGGR_H pmacct-1.7.8/src/plugin_hooks.h0000644000175000017500000001371214354105275015457 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLUGIN_HOOKS_H #define PLUGIN_HOOKS_H #include "plugin_common.h" #define DEFAULT_CHBUFLEN 4096 #define DEFAULT_PIPE_SIZE 65535 #define DEFAULT_SFPROBE_PLOAD_SIZE DEFAULT_SNAPLEN #define WARNING_PIPE_SIZE 16384000 /* 16 Mb */ #define MAX_FAILS 5 #define MAX_SEQNUM 65536 #define MAX_RG_COUNT_ERR 3 struct channels_list_entry; typedef void (*pkt_handler) (struct channels_list_entry *, struct packet_ptrs *, char **); typedef int (*ring_cleaner) (void *, int); typedef pm_counter_t (*skip_func) (pm_counter_t); struct ring { char *base; char *ptr; char *end; }; struct ch_buf_hdr { u_int64_t len; u_int32_t seq; u_int32_t num; }; struct ch_status { u_int8_t wakeup; /* plugin is polling */ u_int64_t last_buf_off; /* offset of last committed buffer */ }; struct sampling { pm_counter_t rate; pm_counter_t counter; pm_counter_t sample_pool; pm_counter_t sampled_pkts; skip_func sf; }; struct aggregate_filter { int *num; struct bpf_program **table; }; struct plugin_type_entry { u_int8_t id; char string[16]; void (*func)(int, struct configuration *, void *); }; struct plugins_list_entry { u_int8_t id; pid_t pid; char name[SRVBUFLEN]; struct configuration cfg; int pipe[2]; struct plugin_type_entry type; struct plugins_list_entry *next; }; #ifdef WITH_ZMQ #include "zmq_common.h" #endif struct channels_list_entry { pm_cfgreg_t aggregation; pm_cfgreg_t aggregation_2; u_int64_t buf; /* buffer base */ u_int64_t bufptr; /* buffer current */ u_int64_t bufend; /* buffer end */ struct ring rg; struct ch_buf_hdr hdr; struct ch_status *status; ring_cleaner clean_func; u_int8_t request; /* does the plugin support on-request wakeup ? */ u_int8_t reprocess; /* do we need to jump back for packet reprocessing ? */ u_int8_t already_reprocessed; /* loop avoidance for packet reprocessing */ int datasize; u_int64_t bufsize; int var_size; int buffer_immediate; int same_aggregate; pkt_handler phandler[N_PRIMITIVES]; int pipe; pid_t core_pid; pm_id_t tag; /* post-tagging tag */ pm_id_t tag2; /* post-tagging tag2 */ struct pretag_filter tag_filter; /* filter aggregates basing on their tag */ struct pretag_filter tag2_filter; /* filter aggregates basing on their tag2 */ struct pretag_label_filter label_filter; /* filter aggregates basing on their label */ struct aggregate_filter agg_filter; /* filter aggregates basing on L2-L4 primitives */ struct sampling s; struct plugins_list_entry *plugin; /* backpointer to the plugin the actual channel belongs to */ struct extra_primitives extras; /* offset for non-standard aggregation primitives structures */ #ifdef WITH_ZMQ struct p_zmq_host zmq_host; #endif }; #if (defined __PLUGIN_HOOKS_C) extern struct channels_list_entry channels_list[MAX_N_PLUGINS]; #endif /* Function prototypes */ extern void load_plugins(struct plugin_requests *); extern void exec_plugins(struct packet_ptrs *, struct plugin_requests *); extern void load_plugin_filters(int); extern struct channels_list_entry *insert_pipe_channel(int, struct configuration *, int); extern void delete_pipe_channel(int); extern void sort_pipe_channels(); extern void init_pipe_channels(); extern int evaluate_filters(struct aggregate_filter *, u_char *, struct pcap_pkthdr *); extern void recollect_pipe_memory(struct channels_list_entry *); extern void init_random_seed(); extern void fill_pipe_buffer(); extern int check_pipe_buffer_space(struct channels_list_entry *, struct pkt_vlen_hdr_primitives *, int); extern void return_pipe_buffer_space(struct channels_list_entry *, int); extern int check_shadow_status(struct packet_ptrs *, struct channels_list_entry *); extern int pkt_data_clean(void *, int); extern int pkt_payload_clean(void *, int); extern int pkt_msg_clean(void *, int); extern int pkt_extras_clean(void *, int); extern void evaluate_sampling(struct sampling *, pm_counter_t *, pm_counter_t *, pm_counter_t *); extern pm_counter_t take_simple_random_skip(pm_counter_t); extern pm_counter_t take_simple_systematic_skip(pm_counter_t); extern void plugin_pipe_zmq_compile_check(); extern void plugin_pipe_check(struct configuration *); extern void P_zmq_pipe_init(void *, int *, u_int32_t *); extern void imt_plugin(int, struct configuration *, void *); extern void print_plugin(int, struct configuration *, void *); extern void nfprobe_plugin(int, struct configuration *, void *); extern void sfprobe_plugin(int, struct configuration *, void *); extern void tee_plugin(int, struct configuration *, void *); #ifdef WITH_MYSQL extern void mysql_plugin(int, struct configuration *, void *); #endif #ifdef WITH_PGSQL extern void pgsql_plugin(int, struct configuration *, void *); #endif #ifdef WITH_SQLITE3 extern void sqlite3_plugin(int, struct configuration *, void *); #endif #ifdef WITH_MONGODB extern void mongodb_plugin(int, struct configuration *, void *); extern void mongodb_legacy_warning(int, struct configuration *, void *); #endif #ifdef WITH_RABBITMQ extern void amqp_plugin(int, struct configuration *, void *); #endif #ifdef WITH_KAFKA extern void kafka_plugin(int, struct configuration *, void *); #endif #endif //PLUGIN_HOOKS_H pmacct-1.7.8/src/pgsql_plugin.c0000644000175000017500000011344014354105275015454 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "sql_common.h" #include "sql_common_m.h" #include "pgsql_plugin.h" int typed = TRUE; char pgsql_user[] = "pmacct"; char pgsql_pwd[] = "arealsmartpwd"; char pgsql_db[] = "pmacct"; char pgsql_table[] = "acct"; char pgsql_table_v2[] = "acct_v2"; char pgsql_table_v3[] = "acct_v3"; char pgsql_table_v4[] = "acct_v4"; char pgsql_table_v5[] = "acct_v5"; char pgsql_table_v6[] = "acct_v6"; char pgsql_table_v7[] = "acct_v7"; char pgsql_table_v8[] = "acct_v8"; char pgsql_table_bgp[] = "acct_bgp"; char pgsql_table_uni[] = "acct_uni"; char pgsql_table_uni_v2[] = "acct_uni_v2"; char pgsql_table_uni_v3[] = "acct_uni_v3"; char pgsql_table_uni_v4[] = "acct_uni_v4"; char pgsql_table_uni_v5[] = "acct_uni_v5"; char pgsql_table_as[] = "acct_as"; char pgsql_table_as_v2[] = "acct_as_v2"; char pgsql_table_as_v3[] = "acct_as_v3"; char pgsql_table_as_v4[] = "acct_as_v4"; char pgsql_table_as_v5[] = "acct_as_v5"; char typed_str[] = "typed"; char unified_str[] = "unified"; /* Functions */ void pgsql_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; struct pollfd pfd; struct insert_data idata; time_t refresh_deadline; int refresh_timeout; int ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *dataptr; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "PostgreSQL Plugin", config.name); memset(&idata, 0, sizeof(idata)); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } sql_set_signals(); sql_init_default_values(&extras); PG_init_default_values(&idata); PG_set_callbacks(&sqlfunc_cbr); sql_set_insert_func(); /* some LOCAL initialization AFTER setting some default values */ reload_map = FALSE; idata.now = time(NULL); refresh_deadline = idata.now; idata.cfg = &config; sql_init_maps(&extras, &prim_ptrs, &nt, &nc, &pt, &prt, &tost); sql_init_global_buffers(); sql_init_historical_acct(idata.now, &idata); sql_init_triggers(idata.now, &idata); sql_init_refresh_deadline(&refresh_deadline); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); /* building up static SQL clauses */ idata.num_primitives = PG_compose_static_queries(); glob_num_primitives = idata.num_primitives; /* setting up environment variables */ SQL_SetENV(); sql_link_backend_descriptors(&bed, &p, &b); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: sql_update_time_reference(&idata); now = idata.now; if (idata.now > refresh_deadline) { if (sql_qq_ptr) sql_cache_flush(sql_queries_queue, sql_qq_ptr, &idata, FALSE); sql_cache_handle_flush_event(&idata, &refresh_deadline, &pt, &prt, &tost); } else { if (config.sql_trigger_exec) { while (idata.now > idata.triggertime && idata.t_timeslot > 0) { sql_trigger_exec(config.sql_trigger_exec); idata.triggertime += idata.t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata.t_timeslot = calc_monthly_timeslot(idata.triggertime, config.sql_trigger_time_howmany, ADD); } } } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* poll(): timeout */ break; default: /* poll(): received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; idata.now = time(NULL); now = idata.now; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*sql_insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } goto read_data; } } } int PG_cache_dbop_copy(struct DBdesc *db, struct db_cache *cache_elem, struct insert_data *idata) { char *ptr_values, *ptr_where; char default_delim[] = ",", delim_buf[SRVBUFLEN]; int num=0, have_flows=0; if (config.what_to_count & COUNT_FLOWS) have_flows = TRUE; if (!config.sql_delimiter) snprintf(delim_buf, SRVBUFLEN, "%s", default_delim); else snprintf(delim_buf, SRVBUFLEN, "%s", config.sql_delimiter); /* constructing SQL query */ ptr_where = where_clause; ptr_values = values_clause; memset(where_clause, 0, sizeof(where_clause)); memset(values_clause, 0, sizeof(values_clause)); memcpy(&values, ©_values, sizeof(values)); while (num < idata->num_primitives) { (*where[num].handler)(cache_elem, idata, num, &ptr_values, &ptr_where); num++; } if (have_flows) snprintf(ptr_values, SPACELEFT(values_clause), "%s%" PRIu64 "%s%" PRIu64 "%s%" PRIu64 "\n", delim_buf, cache_elem->packet_counter, delim_buf, cache_elem->bytes_counter, delim_buf, cache_elem->flows_counter); else snprintf(ptr_values, SPACELEFT(values_clause), "%s%" PRIu64 "%s%" PRIu64 "\n", delim_buf, cache_elem->packet_counter, delim_buf, cache_elem->bytes_counter); strncpy(sql_data, values_clause, SPACELEFT(sql_data)); if (PQputCopyData(db->desc, sql_data, strlen(sql_data)) < 0) { // avoid strlen() db->errmsg = PQerrorMessage(db->desc); Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, sql_data); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): %s\n", config.name, config.type, db->errmsg); sql_db_fail(db); return TRUE; } idata->iqn++; idata->een++; Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n", config.name, config.type, sql_data); return FALSE; } int PG_cache_dbop(struct DBdesc *db, struct db_cache *cache_elem, struct insert_data *idata) { PGresult *ret = NULL; char *ptr_values, *ptr_where, *ptr_set; int num=0, num_set=0, have_flows=0; if (config.what_to_count & COUNT_FLOWS) have_flows = TRUE; /* constructing SQL query */ ptr_where = where_clause; ptr_values = values_clause; ptr_set = set_clause; memset(where_clause, 0, sizeof(where_clause)); memset(values_clause, 0, sizeof(values_clause)); memset(set_clause, 0, sizeof(set_clause)); memset(insert_full_clause, 0, sizeof(insert_full_clause)); for (num = 0; num < idata->num_primitives; num++) (*where[num].handler)(cache_elem, idata, num, &ptr_values, &ptr_where); if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { for (num_set = 0; set_event[num_set].type; num_set++) (*set_event[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } else { for (num_set = 0; set[num_set].type; num_set++) (*set[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } /* sending UPDATE query a) if not switched off and b) if we actually have something to update */ if (!config.sql_dont_try_update && num_set) { strncpy(sql_data, update_clause, SPACELEFT(sql_data)); strncat(sql_data, set_clause, SPACELEFT(sql_data)); strncat(sql_data, where_clause, SPACELEFT(sql_data)); ret = PQexec(db->desc, sql_data); if (PQresultStatus(ret) != PGRES_COMMAND_OK) { db->errmsg = PQresultErrorMessage(ret); PQclear(ret); Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, sql_data); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): %s\n\n", config.name, config.type, db->errmsg); sql_db_fail(db); return TRUE; } PQclear(ret); } if (config.sql_dont_try_update || !num_set || (!PG_affected_rows(ret))) { /* UPDATE failed, trying with an INSERT query */ if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_nocounters_clause, SPACELEFT(insert_full_clause)); strncat(ptr_values, ")", SPACELEFT(values_clause)); } else { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_counters_clause, SPACELEFT(insert_full_clause)); if (have_flows) snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter, cache_elem->flows_counter); else snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter); } strncpy(sql_data, insert_full_clause, sizeof(sql_data)); strncat(sql_data, values_clause, SPACELEFT(sql_data)); ret = PQexec(db->desc, sql_data); if (PQresultStatus(ret) != PGRES_COMMAND_OK) { db->errmsg = PQresultErrorMessage(ret); PQclear(ret); Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, sql_data); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): %s\n\n", config.name, config.type, db->errmsg); sql_db_fail(db); return TRUE; } PQclear(ret); idata->iqn++; } else idata->uqn++; idata->een++; Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, sql_data); return FALSE; } void PG_cache_purge(struct db_cache *queue[], int index, struct insert_data *idata) { PGresult *ret; struct db_cache **reprocess_queries_queue, **bulk_reprocess_queries_queue; char orig_insert_clause[LONGSRVBUFLEN], orig_update_clause[LONGSRVBUFLEN], orig_lock_clause[LONGSRVBUFLEN]; char orig_copy_clause[LONGSRVBUFLEN], tmpbuf[LONGLONGSRVBUFLEN], tmptable[SRVBUFLEN]; time_t start; int j, r, reprocess = 0, stop, go_to_pending, reprocess_idx, bulk_reprocess_idx, saved_index = index; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); if (!index) { Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: 0/0, ET: X) ***\n", config.name, config.type, writer_pid); return; } memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); reprocess_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *)); bulk_reprocess_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *)); if (!reprocess_queries_queue || !bulk_reprocess_queries_queue) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (reprocess_queries_queue). Exiting ..\n", config.name, config.type); exit_gracefully(1); } for (j = 0, stop = 0; (!stop) && sql_preprocess_funcs[j]; j++) stop = sql_preprocess_funcs[j](queue, &index, j); if ((config.what_to_count & COUNT_CLASS) || (config.what_to_count_2 & COUNT_NDPI_CLASS)) sql_invalidate_shadow_entries(queue, &index); idata->ten = index; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); /* re-using pending queries queue stuff from parent and saving clauses */ memcpy(sql_pending_queries_queue, queue, index*sizeof(struct db_cache *)); sql_pqq_ptr = index; strlcpy(orig_copy_clause, copy_clause, LONGSRVBUFLEN); strlcpy(orig_insert_clause, insert_clause, LONGSRVBUFLEN); strlcpy(orig_update_clause, update_clause, LONGSRVBUFLEN); strlcpy(orig_lock_clause, lock_clause, LONGSRVBUFLEN); start: memcpy(queue, sql_pending_queries_queue, sql_pqq_ptr*sizeof(struct db_cache *)); memset(sql_pending_queries_queue, 0, sql_pqq_ptr*sizeof(struct db_cache *)); index = sql_pqq_ptr; sql_pqq_ptr = 0; /* We check for variable substitution in SQL table */ if (idata->dyn_table) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); stamp = queue[0]->basetime; prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[0]); strlcpy(idata->dyn_table_name, config.sql_table, SRVBUFLEN); strlcpy(insert_clause, orig_insert_clause, LONGSRVBUFLEN); strlcpy(update_clause, orig_update_clause, LONGSRVBUFLEN); strlcpy(lock_clause, orig_lock_clause, LONGSRVBUFLEN); handle_dynname_internal_strings_same(copy_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(update_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(copy_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(update_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); } if (config.sql_table_schema) sql_create_table(bed.p, &queue[0]->basetime, &prim_ptrs); /* beginning DB transaction */ (*sqlfunc_cbr.lock)(bed.p); /* for each element of the queue to be processed we execute sql_query(); the function returns a non-zero value if DB has failed; then we use reprocess_queries_queue and bulk_reprocess_queries_queue to handle reprocessing of specific elements or bulk queue (of elements not being held in a pending_queries_queue) due to final COMMIT failure */ memset(reprocess_queries_queue, 0, qq_size*sizeof(struct db_cache *)); memset(bulk_reprocess_queries_queue, 0, qq_size*sizeof(struct db_cache *)); reprocess_idx = 0; bulk_reprocess_idx = 0; for (j = 0; j < index; j++) { go_to_pending = FALSE; if (idata->dyn_table && (!idata->dyn_table_time_only || !config.nfacctd_time_new || (config.sql_refresh_time != idata->timeslot))) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); // XXX: pedantic? stamp = queue[idata->current_queue_elem]->basetime; strlcpy(tmptable, config.sql_table, SRVBUFLEN); prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[idata->current_queue_elem]); handle_dynname_internal_strings_same(tmptable, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(tmptable, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (strncmp(idata->dyn_table_name, tmptable, SRVBUFLEN)) { sql_pending_queries_queue[sql_pqq_ptr] = queue[idata->current_queue_elem]; sql_pqq_ptr++; go_to_pending = TRUE; } } if (!go_to_pending) { if (queue[j]->valid == SQL_CACHE_COMMITTED) { r = sql_query(&bed, queue[j], idata); /* note down all elements in case of a reprocess due to COMMIT failure */ bulk_reprocess_queries_queue[bulk_reprocess_idx] = queue[j]; bulk_reprocess_idx++; } else r = FALSE; /* not valid elements are marked as not to be reprocessed */ if (r) { reprocess_queries_queue[reprocess_idx] = queue[j]; reprocess_idx++; if (!reprocess) sql_db_fail(&p); reprocess = REPROCESS_SPECIFIC; } } } /* Finalizing DB transaction */ if (!p.fail) { if (config.sql_use_copy) { if (PQputCopyEnd(p.desc, NULL) < 0) Log(LOG_ERR, "ERROR ( %s/%s ): COPY failed!\n\n", config.name, config.type); } ret = PQexec(p.desc, "COMMIT"); if (PQresultStatus(ret) != PGRES_COMMAND_OK) { if (!reprocess) sql_db_fail(&p); reprocess = REPROCESS_BULK; } PQclear(ret); } /* don't reprocess free (SQL_CACHE_FREE) and already recovered (SQL_CACHE_ERROR) elements */ if (p.fail) { if (reprocess == REPROCESS_SPECIFIC) { for (j = 0; j < reprocess_idx; j++) { if (reprocess_queries_queue[j]->valid == SQL_CACHE_COMMITTED) sql_query(&bed, reprocess_queries_queue[j], idata); } } else if (reprocess == REPROCESS_BULK) { for (j = 0; j < bulk_reprocess_idx; j++) { if (bulk_reprocess_queries_queue[j]->valid == SQL_CACHE_COMMITTED) sql_query(&bed, bulk_reprocess_queries_queue[j], idata); } } } if (b.connected) { if (config.sql_use_copy) { if (PQputCopyEnd(b.desc, NULL) < 0) Log(LOG_ERR, "ERROR ( %s/%s ): COPY failed!\n\n", config.name, config.type); } ret = PQexec(b.desc, "COMMIT"); if (PQresultStatus(ret) != PGRES_COMMAND_OK) sql_db_fail(&b); PQclear(ret); } /* If we have pending queries then start again */ if (sql_pqq_ptr) goto start; idata->elap_time = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, idata->qn, saved_index, idata->elap_time); if (config.sql_trigger_exec) { if (queue && queue[0]) idata->basetime = queue[0]->basetime; idata->elap_time = time(NULL)-start; SQL_SetENV_child(idata); } } int PG_evaluate_history(int primitive) { if (config.sql_history) { if (primitive) { strncat(copy_clause, ", ", SPACELEFT(copy_clause)); strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, ", ", sizeof(values[primitive].string)); strncat(where[primitive].string, " AND ", sizeof(where[primitive].string)); } if (!config.timestamps_since_epoch) strncat(where[primitive].string, "to_timestamp(%u)::Timestamp without time zone = ", SPACELEFT(where[primitive].string)); else strncat(where[primitive].string, "%u = ", SPACELEFT(where[primitive].string)); strncat(where[primitive].string, "stamp_inserted", SPACELEFT(where[primitive].string)); strncat(copy_clause, "stamp_updated, stamp_inserted", SPACELEFT(copy_clause)); strncat(insert_clause, "stamp_updated, stamp_inserted", SPACELEFT(insert_clause)); if (config.sql_use_copy) { char default_delim[] = ",", delim_buf[SRVBUFLEN]; if (!config.sql_delimiter || !config.sql_use_copy) snprintf(delim_buf, SRVBUFLEN, "%s ", default_delim); else snprintf(delim_buf, SRVBUFLEN, "%s ", config.sql_delimiter); if (!config.timestamps_since_epoch) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_copy_timestamp_handler; } else { strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_timestamp_handler; } } else { if (!config.timestamps_since_epoch) strncat(values[primitive].string, "to_timestamp(%u), to_timestamp(%u)", SPACELEFT(values[primitive].string)); else strncat(values[primitive].string, "%u, %u", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_timestamp_handler; } where[primitive].type = values[primitive].type = TIMESTAMP; primitive++; } return primitive; } int PG_compose_static_queries() { int primitives=0, set_primitives=0, set_event_primitives=0, have_flows=0, lock=0; char default_delim[] = ",", delim_buf[SRVBUFLEN]; if (config.what_to_count & COUNT_FLOWS || (config.sql_table_version >= 4 && config.sql_table_version < SQL_TABLE_VERSION_BGP && !config.sql_optimize_clauses)) { config.what_to_count |= COUNT_FLOWS; have_flows = TRUE; if ((config.sql_table_version < 4 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !config.sql_optimize_clauses) { Log(LOG_ERR, "ERROR ( %s/%s ): The accounting of flows requires SQL table v4. Exiting.\n", config.name, config.type); exit_gracefully(1); } } /* "INSERT INTO ... VALUES ... ", "COPY ... ", "... WHERE ..." stuff */ strncpy(where[primitives].string, " WHERE ", sizeof(where[primitives].string)); snprintf(copy_clause, sizeof(copy_clause), "COPY %s (", config.sql_table); snprintf(insert_clause, sizeof(insert_clause), "INSERT INTO %s (", config.sql_table); strncpy(values[primitives].string, " VALUES (", sizeof(values[primitives].string)); primitives = PG_evaluate_history(primitives); primitives = sql_evaluate_primitives(primitives); strncat(copy_clause, ", packets, bytes", SPACELEFT(copy_clause)); if (have_flows) strncat(copy_clause, ", flows", SPACELEFT(copy_clause)); if (!config.sql_delimiter || !config.sql_use_copy) snprintf(delim_buf, SRVBUFLEN, ") FROM STDIN DELIMITER \'%s\'", default_delim); else snprintf(delim_buf, SRVBUFLEN, ") FROM STDIN DELIMITER \'%s\'", config.sql_delimiter); strncat(copy_clause, delim_buf, SPACELEFT(copy_clause)); strncpy(insert_counters_clause, ", packets, bytes", SPACELEFT(insert_counters_clause)); if (have_flows) strncat(insert_counters_clause, ", flows", SPACELEFT(insert_counters_clause)); strncat(insert_counters_clause, ")", SPACELEFT(insert_counters_clause)); strncpy(insert_nocounters_clause, ")", SPACELEFT(insert_nocounters_clause)); /* "LOCK ..." stuff */ if (config.sql_dont_try_update) snprintf(lock_clause, sizeof(lock_clause), "BEGIN;"); else { if (config.sql_locking_style) lock = sql_select_locking_style(config.sql_locking_style); switch (lock) { case PM_LOCK_NONE: snprintf(lock_clause, sizeof(lock_clause), "BEGIN;"); break; case PM_LOCK_ROW_EXCLUSIVE: snprintf(lock_clause, sizeof(lock_clause), "BEGIN; LOCK %s IN ROW EXCLUSIVE MODE;", config.sql_table); break; case PM_LOCK_EXCLUSIVE: default: snprintf(lock_clause, sizeof(lock_clause), "BEGIN; LOCK %s IN EXCLUSIVE MODE;", config.sql_table); break; } } /* "UPDATE ... SET ..." stuff */ snprintf(update_clause, sizeof(update_clause), "UPDATE %s ", config.sql_table); set_primitives = sql_compose_static_set(have_flows); set_event_primitives = sql_compose_static_set_event(); if (config.sql_history) { if (!config.timestamps_since_epoch) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "stamp_updated=CURRENT_TIMESTAMP(0)", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); strncat(set_event[set_event_primitives].string, "stamp_updated=CURRENT_TIMESTAMP(0)", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_handler; set_event_primitives++; } else { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "stamp_updated=DATE_PART('epoch',NOW())::BIGINT", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); strncat(set_event[set_event_primitives].string, "stamp_updated=DATE_PART('epoch',NOW())::BIGINT", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_handler; set_primitives++; } } /* values for COPY */ memcpy(©_values, &values, sizeof(copy_values)); { int num, x, y; char *ptr; ptr = strchr(copy_values[0].string, '('); ptr++; strcpy(copy_values[0].string, ptr); for (num = 0; num < primitives; num++) { for (x = 0; copy_values[num].string[x] != '\0'; x++) { if (copy_values[num].string[x] == ' ' || copy_values[num].string[x] == '\'') { for (y = x + 1; copy_values[num].string[y] != '\0'; y++) copy_values[num].string[y-1] = copy_values[num].string[y]; copy_values[num].string[y-1] = '\0'; x--; } } copy_values[num].string[x] = '\0'; } } return primitives; } void PG_compose_conn_string(struct DBdesc *db, char *host, int port, char *ca_file) { char *string; int slen = LONGLONGSRVBUFLEN; if (!db->conn_string) { db->conn_string = (char *) malloc(slen); if (!db->conn_string) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (PG_compose_conn_string). Exiting ..\n", config.name, config.type); exit_gracefully(1); } string = db->conn_string; snprintf(string, slen, "dbname=%s user=%s password=%s", config.sql_db, config.sql_user, config.sql_passwd); slen -= strlen(string); string += strlen(string); if (host) { snprintf(string, slen, " host=%s", host); slen -= strlen(string); string += strlen(string); } if (port) { snprintf(string, slen, " port=%u", port); slen -= strlen(string); string += strlen(string); } if (ca_file) { snprintf(string, slen, " sslmode=verify-full sslrootcert=%s", ca_file); slen -= strlen(string); string += strlen(string); } } } void PG_Lock(struct DBdesc *db) { PGresult *PGret; if (!db->fail) { PGret = PQexec(db->desc, lock_clause); if (PQresultStatus(PGret) != PGRES_COMMAND_OK) { db->errmsg = PQresultErrorMessage(PGret); sql_db_errmsg(db); sql_db_fail(db); } PQclear(PGret); /* If using COPY, let's initialize it */ if (config.sql_use_copy) { PGret = PQexec(db->desc, copy_clause); if (PQresultStatus(PGret) != PGRES_COPY_IN) { db->errmsg = PQresultErrorMessage(PGret); sql_db_errmsg(db); sql_db_fail(db); } else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n", config.name, config.type, copy_clause); PQclear(PGret); } } } void PG_DB_Connect(struct DBdesc *db, char *host) { if (!db->fail) { db->desc = PQconnectdb(db->conn_string); if (PQstatus(db->desc) == CONNECTION_BAD) { char errmsg[64+SRVBUFLEN]; sql_db_fail(db); strcpy(errmsg, "Failed connecting to "); strcat(errmsg, db->conn_string); db->errmsg = errmsg; sql_db_errmsg(db); } else sql_db_ok(db); } } void PG_DB_Close(struct BE_descs *bed) { if (bed->p->connected) PQfinish(bed->p->desc); if (bed->b->connected) PQfinish(bed->b->desc); } void PG_create_dyn_table(struct DBdesc *db, char *buf) { char *err_string; PGresult *PGret; if (!db->fail) { PGret = PQexec(db->desc, buf); if ((PQresultStatus(PGret) != PGRES_COMMAND_OK) && (PQresultStatus(PGret) != PGRES_TUPLES_OK)) { err_string = PQresultErrorMessage(PGret); Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, buf); Log(LOG_ERR, "ERROR ( %s/%s ): %s\n\n", config.name, config.type, err_string); } PQclear(PGret); } } int PG_affected_rows(PGresult *result) { return atoi(PQcmdTuples(result)); } void PG_create_backend(struct DBdesc *db) { if (db->type == BE_TYPE_PRIMARY) { PG_compose_conn_string(db, config.sql_host, config.sql_port, config.sql_conn_ca_file); } else if (db->type == BE_TYPE_BACKUP) { if (!config.sql_backup_host) return; else PG_compose_conn_string(db, config.sql_backup_host, config.sql_port, config.sql_conn_ca_file); } } void PG_set_callbacks(struct sqlfunc_cb_registry *cbr) { memset(cbr, 0, sizeof(struct sqlfunc_cb_registry)); cbr->connect = PG_DB_Connect; cbr->close = PG_DB_Close; cbr->lock = PG_Lock; /* cbr->unlock */ if (!config.sql_use_copy) cbr->op = PG_cache_dbop; else cbr->op = PG_cache_dbop_copy; cbr->create_table = PG_create_dyn_table; cbr->purge = PG_cache_purge; cbr->create_backend = PG_create_backend; } void PG_init_default_values(struct insert_data *idata) { /* Linking database parameters */ if (!config.sql_data) config.sql_data = typed_str; if (!config.sql_user) config.sql_user = pgsql_user; if (!config.sql_db) config.sql_db = pgsql_db; if (!config.sql_passwd) config.sql_passwd = pgsql_pwd; if (!config.sql_table) { /* checking 'typed' table constraints */ if (!strcmp(config.sql_data, "typed")) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS|COUNT_DST_AS) && config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST|COUNT_DST_HOST|COUNT_SRC_NET|COUNT_SUM_NET|COUNT_DST_NET) && config.sql_table_version < 6) { Log(LOG_ERR, "ERROR ( %s/%s ): 'typed' PostgreSQL table in use: unable to mix HOST/NET and AS aggregations.\n", config.name, config.type); exit_gracefully(1); } typed = TRUE; } else if (!strcmp(config.sql_data, "unified")) typed = FALSE; else { Log(LOG_ERR, "ERROR ( %s/%s ): Ignoring unknown 'sql_data' value '%s'.\n", config.name, config.type, config.sql_data); exit_gracefully(1); } if (typed) { if (config.sql_table_version == (SQL_TABLE_VERSION_BGP+1)) config.sql_table = pgsql_table_bgp; else if (config.sql_table_version == 8) config.sql_table = pgsql_table_v8; else if (config.sql_table_version == 7) config.sql_table = pgsql_table_v7; else if (config.sql_table_version == 6) config.sql_table = pgsql_table_v6; else if (config.sql_table_version == 5) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) config.sql_table = pgsql_table_as_v5; else config.sql_table = pgsql_table_v5; } else if (config.sql_table_version == 4) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) config.sql_table = pgsql_table_as_v4; else config.sql_table = pgsql_table_v4; } else if (config.sql_table_version == 3) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) config.sql_table = pgsql_table_as_v3; else config.sql_table = pgsql_table_v3; } else if (config.sql_table_version == 2) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) config.sql_table = pgsql_table_as_v2; else config.sql_table = pgsql_table_v2; } else { if (config.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) config.sql_table = pgsql_table_as; else config.sql_table = pgsql_table; } } else { if (config.sql_table_version == 8) { Log(LOG_WARNING, "WARN ( %s/%s ): Unified data are no longer supported. Switching to typed data.\n", config.name, config.type); config.sql_table = pgsql_table_v8; } if (config.sql_table_version == 7) { Log(LOG_WARNING, "WARN ( %s/%s ): Unified data are no longer supported. Switching to typed data.\n", config.name, config.type); config.sql_table = pgsql_table_v7; } else if (config.sql_table_version == 6) { Log(LOG_WARNING, "WARN ( %s/%s ): Unified data are no longer supported. Switching to typed data.\n", config.name, config.type); config.sql_table = pgsql_table_v6; } else if (config.sql_table_version == 5) config.sql_table = pgsql_table_uni_v5; else if (config.sql_table_version == 4) config.sql_table = pgsql_table_uni_v4; else if (config.sql_table_version == 3) config.sql_table = pgsql_table_uni_v3; else if (config.sql_table_version == 2) config.sql_table = pgsql_table_uni_v2; else config.sql_table = pgsql_table_uni; } } if (strchr(config.sql_table, '%') || strchr(config.sql_table, '$')) { idata->dyn_table = TRUE; if (!strchr(config.sql_table, '$')) idata->dyn_table_time_only = TRUE; } glob_dyn_table = idata->dyn_table; glob_dyn_table_time_only = idata->dyn_table_time_only; if (config.sql_backup_host) idata->recover = TRUE; if (!config.sql_dont_try_update && config.sql_use_copy) config.sql_use_copy = FALSE; if (config.sql_locking_style) idata->locks = sql_select_locking_style(config.sql_locking_style); } void PG_postgresql_get_version() { #if defined HAVE_PQLIBVERSION printf("PostgreSQL %u\n", PQlibVersion()); #else printf("PostgreSQL\n"); #endif } pmacct-1.7.8/src/rpki/0000755000175000017500000000000014354105416013543 5ustar paolopaolopmacct-1.7.8/src/rpki/rpki_util.c0000644000175000017500000000771014354105275015721 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp/bgp.h" #include "rpki.h" /* Functions */ void rpki_init_dummy_peer(struct bgp_peer *peer) { memset(peer, 0, sizeof(struct bgp_peer)); peer->type = FUNC_TYPE_RPKI; } int rpki_attrhash_cmp(const void *p1, const void *p2) { const struct bgp_attr *attr1 = (const struct bgp_attr *)p1; const struct bgp_attr *attr2 = (const struct bgp_attr *)p2; if (attr1->aspath == attr2->aspath) return TRUE; return FALSE; } const char *rpki_roa_print(u_int8_t roa) { if (roa <= ROA_STATUS_MAX) return rpki_roa[roa]; else return rpki_roa[ROA_STATUS_UNKNOWN]; } u_int8_t rpki_str2roa(char *roa_str) { if (!strcmp(roa_str, "u")) return ROA_STATUS_UNKNOWN; else if (!strcmp(roa_str, "i")) return ROA_STATUS_INVALID; else if (!strcmp(roa_str, "v")) return ROA_STATUS_VALID; return ROA_STATUS_UNKNOWN; } void rpki_ribs_free(struct bgp_peer *peer, struct bgp_table *rib_v4, struct bgp_table *rib_v6) { bgp_table_info_delete(peer, rib_v4, AFI_IP, SAFI_UNICAST); bgp_table_info_delete(peer, rib_v6, AFI_IP6, SAFI_UNICAST); bgp_table_free(rib_v4); bgp_table_free(rib_v6); } void rpki_ribs_reset(struct bgp_peer *peer, struct bgp_table **rib_v4, struct bgp_table **rib_v6) { rpki_ribs_free(peer, (*rib_v4), (*rib_v6)); (*rib_v4) = bgp_table_init(AFI_IP, SAFI_UNICAST); (*rib_v6) = bgp_table_init(AFI_IP6, SAFI_UNICAST); } void rpki_rtr_set_dont_reconnect(struct rpki_rtr_handle *cache) { cache->dont_reconnect = TRUE; } time_t rpki_rtr_eval_timeout(struct rpki_rtr_handle *cache) { time_t retry_timeout = 0, refresh_timeout = 0, expire_timeout = 0; time_t ret = 1; if (cache->now >= (cache->expire.tstamp + cache->expire.ivl)) expire_timeout = 0; else expire_timeout = ((cache->expire.tstamp + cache->expire.ivl) - cache->now); if (cache->fd < 0) { if (cache->now >= (cache->retry.tstamp + cache->retry.ivl)) retry_timeout = 0; else retry_timeout = ((cache->retry.tstamp + cache->retry.ivl) - cache->now); ret = MIN(retry_timeout, expire_timeout); } else { if (cache->now >= (cache->refresh.tstamp + cache->refresh.ivl)) refresh_timeout = 0; else refresh_timeout = ((cache->refresh.tstamp + cache->refresh.ivl) - cache->now); ret = MIN(refresh_timeout, expire_timeout); } /* 1 is our minimum as zero would block select() indefinitely */ if (!ret) ret = 1; return ret; } void rpki_rtr_eval_expire(struct rpki_rtr_handle *cache) { if (cache->now >= (cache->expire.tstamp + cache->expire.ivl)) { cache->expire.tstamp = cache->now; } else return; cache->session_id = 0; cache->serial = 0; rpki_ribs_reset(&rpki_peer, &rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], &rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); } void rpki_link_misc_structs(struct bgp_misc_structs *m_data) { m_data->table_peer_buckets = 1; /* saving on DEFAULT_BGP_INFO_HASH for now */ m_data->table_per_peer_buckets = DEFAULT_BGP_INFO_PER_PEER_HASH; m_data->table_attr_hash_buckets = HASHTABSIZE; m_data->table_per_peer_hash = BGP_ASPATH_HASH_PATHID; m_data->route_info_modulo = NULL; m_data->bgp_lookup_node_match_cmp = rpki_prefix_lookup_node_match_cmp; } pmacct-1.7.8/src/rpki/rpki_lookup.c0000644000175000017500000000574014354105275016256 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp/bgp.h" #include "rpki.h" /* Functions */ u_int8_t rpki_prefix_lookup(struct prefix *p, as_t last_as) { struct bgp_misc_structs *m_data = rpki_misc_db; struct node_match_cmp_term2 nmct2; struct bgp_node *result = NULL; struct bgp_info *info = NULL; struct bgp_peer peer; safi_t safi; afi_t afi; if (!rpki_roa_db || !m_data || !p) return ROA_STATUS_UNKNOWN; memset(&peer, 0, sizeof(struct bgp_peer)); peer.type = FUNC_TYPE_RPKI; afi = family2afi(p->family); safi = SAFI_UNICAST; memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.ret_code = ROA_STATUS_UNKNOWN; nmct2.safi = safi; nmct2.p = p; nmct2.last_as = last_as; bgp_node_match(rpki_roa_db->rib[afi][safi], p, &peer, m_data->route_info_modulo, m_data->bgp_lookup_node_match_cmp, &nmct2, NULL, &result, &info); return nmct2.ret_code; } u_int8_t rpki_vector_prefix_lookup(struct bgp_node_vector *bnv) { int idx, level; u_int8_t roa = ROA_STATUS_UNKNOWN; as_t last_as; if (!bnv || !bnv->entries) return roa; for (level = 0, idx = bnv->entries; idx; idx--) { level++; last_as = evaluate_last_asn(bnv->v[(idx - 1)].info->attr->aspath); if (!last_as) last_as = bnv->v[(idx - 1)].info->peer->myas; roa = rpki_prefix_lookup(bnv->v[(idx - 1)].p, last_as); if (roa == ROA_STATUS_UNKNOWN || roa == ROA_STATUS_VALID) break; } if (level > 1) { if (roa == ROA_STATUS_UNKNOWN) { roa = ROA_STATUS_OVERLAP_UNKNOWN; } else if (roa == ROA_STATUS_VALID) { roa = ROA_STATUS_OVERLAP_VALID; } } return roa; } int rpki_prefix_lookup_node_match_cmp(struct bgp_info *info, struct node_match_cmp_term2 *nmct2) { if (!info || !info->attr || !info->attr->aspath || !nmct2) return TRUE; if (info->attr->flag >= nmct2->p->prefixlen) { if (evaluate_last_asn(info->attr->aspath) == nmct2->last_as) { nmct2->ret_code = ROA_STATUS_VALID; return FALSE; } } /* If we did find a previous Valid, let's not over-write the ret_code */ if (nmct2->ret_code != ROA_STATUS_VALID) { nmct2->ret_code = ROA_STATUS_INVALID; } return TRUE; } pmacct-1.7.8/src/rpki/rpki.c0000644000175000017500000001356114354105275014665 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp/bgp.h" #include "rpki.h" #include "thread_pool.h" /* variables to be exported away */ thread_pool_t *rpki_pool; struct bgp_rt_structs *rpki_roa_db; struct bgp_misc_structs *rpki_misc_db; struct bgp_peer rpki_peer; /* Functions */ void rpki_daemon_wrapper() { /* initialize threads pool */ rpki_pool = allocate_thread_pool(1); assert(rpki_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): %d thread(s) initialized\n", config.name, 1); rpki_prepare_thread(); /* giving a kick to the RPKI thread */ send_to_pool(rpki_pool, rpki_daemon, NULL); } void rpki_prepare_thread() { rpki_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_RPKI]; memset(rpki_misc_db, 0, sizeof(struct bgp_misc_structs)); rpki_misc_db->is_thread = TRUE; rpki_misc_db->log_str = malloc(strlen("core/RPKI") + 1); strcpy(rpki_misc_db->log_str, "core/RPKI"); } int rpki_daemon() { struct bgp_misc_structs *m_data = rpki_misc_db; afi_t afi; safi_t safi; /* select() stuff */ struct timeval select_timeout; int select_fd, select_num; fd_set read_desc; /* rpki_rtr_cache stuff */ struct rpki_rtr_handle rpki_cache; /* initial cleanups */ reload_map_rpki_thread = FALSE; reload_log_rpki_thread = FALSE; memset(&rpki_cache, 0, sizeof(rpki_cache)); rpki_init_dummy_peer(&rpki_peer); rpki_roa_db = &inter_domain_routing_dbs[FUNC_TYPE_RPKI]; memset(rpki_roa_db, 0, sizeof(struct bgp_rt_structs)); bgp_attr_init(HASHTABSIZE, rpki_roa_db); /* Let's initialize clean shared RIB */ for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { rpki_roa_db->rib[afi][safi] = bgp_table_init(afi, safi); } } rpki_link_misc_structs(m_data); if (config.rpki_roas_file && config.rpki_rtr_cache) { Log(LOG_ERR, "ERROR ( %s/core/RPKI ): rpki_roas_file and rpki_rtr_cache are mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } if (config.rpki_roas_file) { rpki_roas_file_load(config.rpki_roas_file, rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); } if (config.rpki_rtr_cache) { if (config.rpki_rtr_cache_version != RPKI_RTR_V0 && config.rpki_rtr_cache_version != RPKI_RTR_V1) { Log(LOG_ERR, "ERROR ( %s/core/RPKI ): rpki_rtr_cache_version must be 0 or 1. Exiting.\n", config.name); exit_gracefully(1); } if (config.rpki_rtr_cache_version == RPKI_RTR_V0) { rpki_cache.retry.ivl = RPKI_RTR_V0_DEFAULT_RETRY_IVL; rpki_cache.refresh.ivl = RPKI_RTR_V0_DEFAULT_REFRESH_IVL; rpki_cache.expire.ivl = RPKI_RTR_V0_DEFAULT_EXPIRE_IVL; } if (config.rpki_rtr_cache_version == RPKI_RTR_V1) { rpki_cache.retry.ivl = RPKI_RTR_V1_DEFAULT_RETRY_IVL; rpki_cache.refresh.ivl = RPKI_RTR_V1_DEFAULT_REFRESH_IVL; rpki_cache.expire.ivl = RPKI_RTR_V1_DEFAULT_EXPIRE_IVL; } rpki_cache.now = rpki_cache.expire.tstamp = time(NULL); rpki_cache.fd = ERR; rpki_cache.socklen = sizeof(rpki_cache.sock); parse_hostport(config.rpki_rtr_cache, (struct sockaddr *)&rpki_cache.sock, &rpki_cache.socklen); } for (;;) { select_again: /* select inits */ FD_ZERO(&read_desc); select_fd = 0; select_timeout.tv_sec = 1; select_timeout.tv_usec = 0; if (config.rpki_rtr_cache) { if (rpki_cache.fd > 0) { select_fd = (rpki_cache.fd + 1); FD_SET(rpki_cache.fd, &read_desc); } select_timeout.tv_sec = rpki_rtr_eval_timeout(&rpki_cache); } select_num = select(select_fd, &read_desc, NULL, NULL, &select_timeout); if (config.rpki_rtr_cache) rpki_cache.now = time(NULL); if (select_num < 0) goto select_again; /* signals handling */ if (reload_map_rpki_thread) { rpki_roas_file_reload(); reload_map_rpki_thread = FALSE; } if (config.rpki_rtr_cache) { /* timeout */ if (!select_num) { if (rpki_cache.fd < 0) rpki_rtr_connect(&rpki_cache); if (!rpki_cache.session_id) rpki_rtr_send_reset_query(&rpki_cache); if (rpki_cache.serial) rpki_rtr_send_serial_query(&rpki_cache); rpki_rtr_eval_expire(&rpki_cache); } else rpki_rtr_parse_msg(&rpki_cache); } } return SUCCESS; } void rpki_roas_file_reload() { struct bgp_table *saved_rib_v4, *saved_rib_v6; struct bgp_table *new_rib_v4, *new_rib_v6; int ret; if (config.rpki_roas_file) { new_rib_v4 = bgp_table_init(AFI_IP, SAFI_UNICAST); new_rib_v6 = bgp_table_init(AFI_IP6, SAFI_UNICAST); saved_rib_v4 = rpki_roa_db->rib[AFI_IP][SAFI_UNICAST]; saved_rib_v6 = rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]; ret = rpki_roas_file_load(config.rpki_roas_file, new_rib_v4, new_rib_v6); /* load successful */ if (!ret) { rpki_roa_db->rib[AFI_IP][SAFI_UNICAST] = new_rib_v4; rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST] = new_rib_v6; /* allow some generous time for any existing lookup to complete */ sleep(DEFAULT_SLOTH_SLEEP_TIME); rpki_ribs_free(&rpki_peer, saved_rib_v4, saved_rib_v6); } else rpki_ribs_free(&rpki_peer, new_rib_v4, new_rib_v6); } } pmacct-1.7.8/src/rpki/rpki_msg.h0000644000175000017500000000431414354105275015534 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef RPKI_MSG_H #define RPKI_MSG_H /* prototypes */ extern int rpki_roas_file_load(char *, struct bgp_table *, struct bgp_table *); extern int rpki_info_add(struct bgp_peer *, struct prefix *, as_t, u_int8_t, struct bgp_table *, struct bgp_table *); extern int rpki_info_delete(struct bgp_peer *, struct prefix *, as_t, u_int8_t, struct bgp_table *, struct bgp_table *); extern void rpki_rtr_parse_msg(struct rpki_rtr_handle *); extern void rpki_rtr_parse_ipv4_prefix(struct rpki_rtr_handle *, struct rpki_rtr_ipv4_pref *); extern void rpki_rtr_parse_ipv6_prefix(struct rpki_rtr_handle *, struct rpki_rtr_ipv6_pref *); extern void rpki_rtr_connect(struct rpki_rtr_handle *); extern void rpki_rtr_close(struct rpki_rtr_handle *); extern void rpki_rtr_send_reset_query(struct rpki_rtr_handle *); extern void rpki_rtr_send_serial_query(struct rpki_rtr_handle *); extern void rpki_rtr_recv_cache_response(struct rpki_rtr_handle *); extern void rpki_rtr_recv_serial_notify(struct rpki_rtr_handle *); extern void rpki_rtr_recv_ipv4_pref(struct rpki_rtr_handle *); extern void rpki_rtr_recv_ipv6_pref(struct rpki_rtr_handle *); extern void rpki_rtr_recv_eod(struct rpki_rtr_handle *, u_int8_t); extern void rpki_rtr_recv_cache_reset(struct rpki_rtr_handle *); extern void rpki_rtr_recv_router_key(struct rpki_rtr_handle *); extern void rpki_rtr_recv_error_report(struct rpki_rtr_handle *); #endif //RPKI_MSG_H pmacct-1.7.8/src/rpki/Makefile.in0000644000175000017500000006030614354105416015615 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/rpki ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmrpki_la_LIBADD = am_libpmrpki_la_OBJECTS = libpmrpki_la-rpki.lo \ libpmrpki_la-rpki_msg.lo libpmrpki_la-rpki_lookup.lo \ libpmrpki_la-rpki_util.lo libpmrpki_la_OBJECTS = $(am_libpmrpki_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmrpki_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpmrpki_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmrpki_la-rpki.Plo \ ./$(DEPDIR)/libpmrpki_la-rpki_lookup.Plo \ ./$(DEPDIR)/libpmrpki_la-rpki_msg.Plo \ ./$(DEPDIR)/libpmrpki_la-rpki_util.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmrpki_la_SOURCES) DIST_SOURCES = $(libpmrpki_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmrpki.la libpmrpki_la_SOURCES = rpki.c rpki.h rpki_msg.c rpki_msg.h rpki_lookup.c \ rpki_lookup.h rpki_util.c rpki_util.h libpmrpki_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/rpki/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/rpki/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmrpki.la: $(libpmrpki_la_OBJECTS) $(libpmrpki_la_DEPENDENCIES) $(EXTRA_libpmrpki_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmrpki_la_LINK) $(libpmrpki_la_OBJECTS) $(libpmrpki_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmrpki_la-rpki.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmrpki_la-rpki_lookup.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmrpki_la-rpki_msg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmrpki_la-rpki_util.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmrpki_la-rpki.lo: rpki.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -MT libpmrpki_la-rpki.lo -MD -MP -MF $(DEPDIR)/libpmrpki_la-rpki.Tpo -c -o libpmrpki_la-rpki.lo `test -f 'rpki.c' || echo '$(srcdir)/'`rpki.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmrpki_la-rpki.Tpo $(DEPDIR)/libpmrpki_la-rpki.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpki.c' object='libpmrpki_la-rpki.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -c -o libpmrpki_la-rpki.lo `test -f 'rpki.c' || echo '$(srcdir)/'`rpki.c libpmrpki_la-rpki_msg.lo: rpki_msg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -MT libpmrpki_la-rpki_msg.lo -MD -MP -MF $(DEPDIR)/libpmrpki_la-rpki_msg.Tpo -c -o libpmrpki_la-rpki_msg.lo `test -f 'rpki_msg.c' || echo '$(srcdir)/'`rpki_msg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmrpki_la-rpki_msg.Tpo $(DEPDIR)/libpmrpki_la-rpki_msg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpki_msg.c' object='libpmrpki_la-rpki_msg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -c -o libpmrpki_la-rpki_msg.lo `test -f 'rpki_msg.c' || echo '$(srcdir)/'`rpki_msg.c libpmrpki_la-rpki_lookup.lo: rpki_lookup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -MT libpmrpki_la-rpki_lookup.lo -MD -MP -MF $(DEPDIR)/libpmrpki_la-rpki_lookup.Tpo -c -o libpmrpki_la-rpki_lookup.lo `test -f 'rpki_lookup.c' || echo '$(srcdir)/'`rpki_lookup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmrpki_la-rpki_lookup.Tpo $(DEPDIR)/libpmrpki_la-rpki_lookup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpki_lookup.c' object='libpmrpki_la-rpki_lookup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -c -o libpmrpki_la-rpki_lookup.lo `test -f 'rpki_lookup.c' || echo '$(srcdir)/'`rpki_lookup.c libpmrpki_la-rpki_util.lo: rpki_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -MT libpmrpki_la-rpki_util.lo -MD -MP -MF $(DEPDIR)/libpmrpki_la-rpki_util.Tpo -c -o libpmrpki_la-rpki_util.lo `test -f 'rpki_util.c' || echo '$(srcdir)/'`rpki_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmrpki_la-rpki_util.Tpo $(DEPDIR)/libpmrpki_la-rpki_util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpki_util.c' object='libpmrpki_la-rpki_util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmrpki_la_CFLAGS) $(CFLAGS) -c -o libpmrpki_la-rpki_util.lo `test -f 'rpki_util.c' || echo '$(srcdir)/'`rpki_util.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmrpki_la-rpki.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_lookup.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_msg.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_util.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmrpki_la-rpki.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_lookup.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_msg.Plo -rm -f ./$(DEPDIR)/libpmrpki_la-rpki_util.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/rpki/rpki.h0000644000175000017500000001255414354105275014673 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef RPKI_H #define RPKI_H /* defines */ #define ROA_STATUS_UNKNOWN 0 /* 'u' - Unknown */ #define ROA_STATUS_INVALID 1 /* 'i' - Invalid with no covering prefix */ #define ROA_STATUS_VALID 2 /* 'v' - Valid */ #define ROA_STATUS_OVERLAP_VALID 3 /* 'o' - Invalid with covering valid prefix */ #define ROA_STATUS_OVERLAP_UNKNOWN 4 /* 'O' - Invalid with covering unknown prefix */ #define ROA_STATUS_MAX 4 #define RPKI_RTR_V0 0 /* rfc6810 */ #define RPKI_RTR_V1 1 /* rfc8210 */ #define RPKI_RTR_V0_DEFAULT_RETRY_IVL 10 /* discretionary */ #define RPKI_RTR_V0_DEFAULT_REFRESH_IVL 10 /* discretionary */ #define RPKI_RTR_V0_DEFAULT_EXPIRE_IVL 7200 /* discretionary */ #define RPKI_RTR_V1_DEFAULT_RETRY_IVL 600 /* rfc8210 */ #define RPKI_RTR_V1_DEFAULT_REFRESH_IVL 3600 /* in case of missing/zero timer in eod */ #define RPKI_RTR_V1_DEFAULT_EXPIRE_IVL 7200 /* in case of missing/zero timer in eod */ #define RPKI_RTR_PDU_SERIAL_NOTIFY 0 #define RPKI_RTR_PDU_SERIAL_QUERY 1 #define RPKI_RTR_PDU_RESET_QUERY 2 #define RPKI_RTR_PDU_CACHE_RESPONSE 3 #define RPKI_RTR_PDU_IPV4_PREFIX 4 #define RPKI_RTR_PDU_IPV6_PREFIX 6 #define RPKI_RTR_PDU_END_OF_DATA 7 #define RPKI_RTR_PDU_CACHE_RESET 8 #define RPKI_RTR_PDU_ROUTER_KEY 9 #define RPKI_RTR_PDU_ERROR_REPORT 10 #define RPKI_RTR_PDU_SERIAL_NOTIFY_LEN 12 #define RPKI_RTR_PDU_SERIAL_QUERY_LEN 12 #define RPKI_RTR_PDU_RESET_QUERY_LEN 8 #define RPKI_RTR_PDU_CACHE_RESPONSE_LEN 8 #define RPKI_RTR_PDU_IPV4_PREFIX_LEN 20 #define RPKI_RTR_PDU_IPV6_PREFIX_LEN 32 #define RPKI_RTR_PDU_END_OF_DATA_V0_LEN 12 #define RPKI_RTR_PDU_END_OF_DATA_V1_LEN 24 #define RPKI_RTR_PDU_CACHE_RESET_LEN 8 #define RPKI_RTR_ERR_CORRUPT_DATA 0 #define RPKI_RTR_ERR_INTERNAL_ERROR 1 #define RPKI_RTR_ERR_NO_DATA 2 #define RPKI_RTR_ERR_INVALID_REQUEST 3 #define RPKI_RTR_ERR_PROTO_VERSION 4 #define RPKI_RTR_ERR_INVALID_PDU_TYPE 5 #define RPKI_RTR_ERR_WITHDRAWAL 6 #define RPKI_RTR_ERR_DUPLICATE 7 #define RPKI_RTR_PREFIX_FLAGS_WITHDRAW 0 #define RPKI_RTR_PREFIX_FLAGS_ANNOUNCE 1 struct rpki_rtr_serial { u_int8_t version; u_int8_t pdu_type; u_int16_t session_id; u_int32_t len; u_int32_t serial; } __attribute__ ((packed)); struct rpki_rtr_reset { u_int8_t version; u_int8_t pdu_type; u_int16_t unused; u_int32_t len; } __attribute__ ((packed)); struct rpki_rtr_cache_response { u_int8_t version; u_int8_t pdu_type; u_int16_t session_id; u_int32_t len; } __attribute__ ((packed)); struct rpki_rtr_ipv4_pref { u_int8_t version; u_int8_t pdu_type; u_int16_t unused_1; u_int32_t len; u_int8_t flags; u_int8_t pref_len; u_int8_t max_len; u_int8_t unused_2; u_int32_t prefix; u_int32_t asn; } __attribute__ ((packed)); struct rpki_rtr_ipv6_pref { u_int8_t version; u_int8_t pdu_type; u_int16_t unused_1; u_int32_t len; u_int8_t flags; u_int8_t pref_len; u_int8_t max_len; u_int8_t unused_2; u_int32_t prefix[4]; u_int32_t asn; } __attribute__ ((packed)); struct rpki_rtr_eod_v0 { u_int8_t version; u_int8_t pdu_type; u_int16_t session_id; u_int32_t len; u_int32_t serial; } __attribute__ ((packed)); struct rpki_rtr_eod_v1 { u_int8_t version; u_int8_t pdu_type; u_int16_t session_id; u_int32_t len; u_int32_t serial; u_int32_t refresh_ivl; u_int32_t retry_ivl; u_int32_t expire_ivl; } __attribute__ ((packed)); struct rpki_rtr_cache_reset { u_int8_t version; u_int8_t pdu_type; u_int16_t unused; u_int32_t len; } __attribute__ ((packed)); struct rpki_rtr_router_key { u_int8_t version; u_int8_t pdu_type; u_int8_t flags; u_int8_t unused; u_int32_t len; u_int8_t subject_key_id[20]; u_int32_t asn; /* subject public key info */ } __attribute__ ((packed)); struct rpki_rtr_err_report { u_int8_t version; u_int8_t pdu_type; u_int16_t errcode; u_int32_t tot_len; /* pdu len */ /* copy of pdu */ /* err text len */ /* err text */ } __attribute__ ((packed)); struct rpki_rtr_timer { time_t tstamp; u_int32_t ivl; }; struct rpki_rtr_handle { struct sockaddr_storage sock; socklen_t socklen; int fd; int dont_reconnect; time_t now; struct rpki_rtr_timer refresh; struct rpki_rtr_timer retry; struct rpki_rtr_timer expire; u_int16_t session_id; u_int32_t serial; }; #include "rpki_msg.h" #include "rpki_lookup.h" #include "rpki_util.h" /* prototypes */ extern void rpki_daemon_wrapper(); extern void rpki_prepare_thread(); extern int rpki_daemon(); extern void rpki_roas_file_reload(); /* global variables */ extern struct bgp_rt_structs *rpki_roa_db; extern struct bgp_misc_structs *rpki_misc_db; extern struct bgp_peer rpki_peer; #endif //RPKI_H pmacct-1.7.8/src/rpki/rpki_util.h0000644000175000017500000000301214354105275015715 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef RPKI_UTIL_H #define RPKI_UTIL_H /* prototypes */ extern void rpki_init_dummy_peer(struct bgp_peer *); extern int rpki_attrhash_cmp(const void *, const void *); extern const char *rpki_roa_print(u_int8_t); extern u_int8_t rpki_str2roa(char *); extern void rpki_ribs_free(struct bgp_peer *, struct bgp_table *, struct bgp_table *); extern void rpki_ribs_reset(struct bgp_peer *, struct bgp_table **, struct bgp_table **); extern void rpki_rtr_set_dont_reconnect(struct rpki_rtr_handle *); extern time_t rpki_rtr_eval_timeout(struct rpki_rtr_handle *); extern void rpki_rtr_eval_expire(struct rpki_rtr_handle *); extern void rpki_link_misc_structs(struct bgp_misc_structs *); #endif //RPKI_UTIL_H pmacct-1.7.8/src/rpki/rpki_msg.c0000644000175000017500000005450114354105275015532 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp/bgp.h" #include "rpki.h" /* functions */ int rpki_roas_file_load(char *file, struct bgp_table *rib_v4, struct bgp_table *rib_v6) { struct bgp_misc_structs *m_data = rpki_misc_db; Log(LOG_INFO, "INFO ( %s/%s ): [%s] (re)loading map.\n", config.name, m_data->log_str, file); #if defined WITH_JANSSON json_t *roas_obj, *roa_json, *roas_json; json_error_t file_err; int roas_idx; roas_obj = json_load_file(file, 0, &file_err); if (roas_obj) { if (!json_is_object(roas_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] json_is_object() failed for results: %s\n", config.name, m_data->log_str, file, file_err.text); return ERR; } else { roas_json = json_object_get(roas_obj, "roas"); if (roas_json == NULL || !json_is_array(roas_json)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] no 'roas' element or not an array.\n", config.name, m_data->log_str, file); json_decref(roas_obj); return ERR; } else { for (roas_idx = 0; (roa_json = json_array_get(roas_json, roas_idx)); roas_idx++) { json_t *prefix_json, *maxlen_json, *asn_json; struct prefix p; u_int8_t maxlen; as_t asn; int ret; memset(&p, 0, sizeof(p)); prefix_json = json_object_get(roa_json, "prefix"); if (prefix_json == NULL || !json_is_string(prefix_json)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] no 'prefix' element in ROA #%u.\n", config.name, m_data->log_str, file, (roas_idx + 1)); goto exit_lane; } else { ret = str2prefix(json_string_value(prefix_json), &p); if (!ret) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] invalid 'prefix' element in ROA #%u.\n", config.name, m_data->log_str, file, (roas_idx + 1)); goto exit_lane; } } asn_json = json_object_get(roa_json, "asn"); if (asn_json == NULL || (!json_is_string(asn_json) && !json_is_integer(asn_json))) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] no 'asn' element in ROA #%u.\n", config.name, m_data->log_str, file, (roas_idx + 1)); goto exit_lane; } else { if (json_is_string(asn_json)) { ret = bgp_str2asn((char *)json_string_value(asn_json), &asn); } else { ret = FALSE; asn = json_integer_value(asn_json); } if (ret) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] invalid 'asn' element in ROA #%u.\n", config.name, m_data->log_str, file, (roas_idx + 1)); goto exit_lane; } } maxlen_json = json_object_get(roa_json, "maxLength"); if (maxlen_json == NULL || !json_is_integer(maxlen_json)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] no 'maxLength' element in ROA #%u.\n", config.name, m_data->log_str, file, (roas_idx + 1)); goto exit_lane; } else maxlen = json_integer_value(maxlen_json); if (maxlen > (p.family == AF_INET ? 32 : 128) || maxlen < p.prefixlen) { char prefix_str[PREFIX_STRLEN]; prefix2str(&p, prefix_str, PREFIX_STRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'maxLength' < prefixLength: prefix=%s maxLength=%u asn=%u\n", config.name, m_data->log_str, file, prefix_str, maxlen, asn); } ret = rpki_info_add(&rpki_peer, &p, asn, maxlen, rib_v4, rib_v6); exit_lane: continue; } } json_decref(roas_obj); } Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, m_data->log_str, file); } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] json_loads() failed: %s.\n", config.name, m_data->log_str, file, file_err.text); return ERR; } #else Log(LOG_WARNING, "WARN ( %s/%s ): rpki_roas_file will not load (missing --enable-jansson).\n", config.name, m_data->log_str); #endif return SUCCESS; } int rpki_info_add(struct bgp_peer *peer, struct prefix *p, as_t asn, u_int8_t maxlen, struct bgp_table *rib_v4, struct bgp_table *rib_v6) { struct bgp_misc_structs *m_data = rpki_misc_db; struct bgp_node *route = NULL; struct bgp_info *new = NULL; struct bgp_attr attr, *attr_new = NULL; struct bgp_table *rib = NULL; afi_t afi; u_int32_t modulo; if (!m_data || !peer || !p || !rib_v4 || !rib_v6) return ERR; afi = family2afi(p->family); modulo = 0; if (afi == AFI_IP) rib = rib_v4; else if (afi == AFI_IP6) rib = rib_v6; else return ERR; route = bgp_node_get(peer, rib, p); memset(&attr, 0, sizeof(attr)); attr.flag = maxlen; /* abusing flag for maxlen */ attr.aspath = aspath_parse_ast(peer, asn); attr_new = bgp_attr_intern(peer, &attr); if (attr.aspath) aspath_unintern(peer, attr.aspath); /* Make new BGP info. */ new = bgp_info_new(peer); if (new) { new->peer = peer; new->attr = attr_new; } else return ERR; /* Register new BGP information. */ bgp_info_add(peer, route, new, modulo); /* route_node_get lock */ bgp_unlock_node(peer, route); return SUCCESS; } int rpki_info_delete(struct bgp_peer *peer, struct prefix *p, as_t asn, u_int8_t maxlen, struct bgp_table *rib_v4, struct bgp_table *rib_v6) { struct bgp_misc_structs *m_data = rpki_misc_db; struct bgp_node *route = NULL; struct bgp_info *ri = NULL; struct bgp_attr attr, *attr_new = NULL; struct bgp_table *rib = NULL; afi_t afi; u_int32_t modulo; u_int8_t end; if (!m_data || !peer || !p || !rib_v4 || !rib_v6) return ERR; afi = family2afi(p->family); modulo = 0; if (afi == AFI_IP) rib = rib_v4; else if (afi == AFI_IP6) rib = rib_v6; else return ERR; for (end = MAX(p->prefixlen, maxlen); p->prefixlen <= end; p->prefixlen++) { route = bgp_node_get(peer, rib, p); memset(&attr, 0, sizeof(attr)); attr.aspath = aspath_parse_ast(peer, asn); attr_new = bgp_attr_intern(peer, &attr); if (attr.aspath) aspath_unintern(peer, attr.aspath); /* Check previously received route. */ for (ri = route->info[modulo]; ri; ri = ri->next) { if (ri->peer == peer && rpki_attrhash_cmp(ri->attr, attr_new)) { bgp_info_delete(peer, route, ri, modulo); break; } } bgp_attr_unintern(peer, attr_new); /* route_node_get lock */ bgp_unlock_node(peer, route); } return SUCCESS; } void rpki_rtr_parse_msg(struct rpki_rtr_handle *cache) { struct rpki_rtr_serial peek; ssize_t msglen; if (cache->fd > 0) { memset(&peek, 0, sizeof(peek)); msglen = recv(cache->fd, &peek, 2, MSG_PEEK); if (msglen == 2) { if (peek.version != config.rpki_rtr_cache_version) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_parse_msg(): RPKI version mismatch (me=%u cache=%u)\n", config.name, config.rpki_rtr_cache_version, peek.version); rpki_rtr_close(cache); rpki_rtr_set_dont_reconnect(cache); return; } switch(peek.pdu_type) { case RPKI_RTR_PDU_SERIAL_NOTIFY: rpki_rtr_recv_serial_notify(cache); break; case RPKI_RTR_PDU_CACHE_RESPONSE: rpki_rtr_recv_cache_response(cache); break; case RPKI_RTR_PDU_IPV4_PREFIX: rpki_rtr_recv_ipv4_pref(cache); break; case RPKI_RTR_PDU_IPV6_PREFIX: rpki_rtr_recv_ipv6_pref(cache); break; case RPKI_RTR_PDU_END_OF_DATA: rpki_rtr_recv_eod(cache, peek.version); break; case RPKI_RTR_PDU_CACHE_RESET: rpki_rtr_recv_cache_reset(cache); break; case RPKI_RTR_PDU_ROUTER_KEY: rpki_rtr_recv_router_key(cache); break; case RPKI_RTR_PDU_ERROR_REPORT: rpki_rtr_recv_error_report(cache); break; default: Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_parse_msg(): unknown PDU type (%u)\n", config.name, peek.pdu_type); rpki_rtr_close(cache); break; } } else { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_parse_msg(): recv() peek failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_parse_ipv4_prefix(struct rpki_rtr_handle *cache, struct rpki_rtr_ipv4_pref *p4m) { struct bgp_misc_structs *m_data = rpki_misc_db; struct prefix_ipv4 p; as_t asn; memset(&p, 0, sizeof(p)); p.family = AF_INET; p.prefix.s_addr = p4m->prefix; p.prefixlen = p4m->pref_len; asn = ntohl(p4m->asn); if (p4m->max_len > 32 || p4m->max_len < p.prefixlen) { char prefix_str[PREFIX_STRLEN]; prefix2str((struct prefix *) &p, prefix_str, PREFIX_STRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): 'maxLength' < prefixLength: prefix=%s maxLength=%u asn=%u\n", config.name, m_data->log_str, prefix_str, p4m->max_len, asn); } switch(p4m->flags) { case RPKI_RTR_PREFIX_FLAGS_WITHDRAW: rpki_info_delete(&rpki_peer, (struct prefix *) &p, asn, p4m->max_len, rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); break; case RPKI_RTR_PREFIX_FLAGS_ANNOUNCE: rpki_info_add(&rpki_peer, (struct prefix *) &p, asn, p4m->max_len, rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); break; default: Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_parse_ipv4_prefix(): unknown flag (%u)\n", config.name, p4m->flags); break; } } void rpki_rtr_parse_ipv6_prefix(struct rpki_rtr_handle *cache, struct rpki_rtr_ipv6_pref *p6m) { struct bgp_misc_structs *m_data = rpki_misc_db; struct prefix_ipv6 p; as_t asn; memset(&p, 0, sizeof(p)); p.family = AF_INET6; memcpy(&p.prefix.s6_addr, p6m->prefix, 16); p.prefixlen = p6m->pref_len; asn = ntohl(p6m->asn); if (p6m->max_len > 128 || p6m->max_len < p.prefixlen) { char prefix_str[PREFIX_STRLEN]; prefix2str((struct prefix *) &p, prefix_str, PREFIX_STRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): 'maxLength' < prefixLength: prefix=%s maxLength=%u asn=%u\n", config.name, m_data->log_str, prefix_str, p6m->max_len, asn); } switch(p6m->flags) { case RPKI_RTR_PREFIX_FLAGS_WITHDRAW: rpki_info_delete(&rpki_peer, (struct prefix *) &p, asn, p6m->max_len, rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); break; case RPKI_RTR_PREFIX_FLAGS_ANNOUNCE: rpki_info_add(&rpki_peer, (struct prefix *) &p, asn, p6m->max_len, rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); break; default: Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_parse_ipv6_prefix(): unknown flag (%u)\n", config.name, p6m->flags); break; } } void rpki_rtr_connect(struct rpki_rtr_handle *cache) { int rc; if (cache->now >= (cache->retry.tstamp + cache->retry.ivl)) { cache->retry.tstamp = cache->now; } else return; if ((cache->fd = socket(cache->sock.ss_family, SOCK_STREAM, 0)) == -1) { Log(LOG_ERR, "ERROR ( %s/core/RPKI ): rpki_rtr_connect(): socket() failed: %s\n", config.name, strerror(errno)); exit_gracefully(1); } if (config.rpki_rtr_cache_ipprec) { int opt = config.rpki_rtr_cache_ipprec << 5; rc = setsockopt(cache->fd, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_connect(): setsockopt() failed for IP_TOS (errno: %d).\n", config.name, errno); } if (config.rpki_rtr_cache_pipe_size) { socklen_t l = sizeof(config.rpki_rtr_cache_pipe_size); int saved = 0, obtained = 0; getsockopt(cache->fd, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(cache->fd, SOL_SOCKET, SO_RCVBUF, &config.rpki_rtr_cache_pipe_size, (socklen_t) sizeof(config.rpki_rtr_cache_pipe_size)); getsockopt(cache->fd, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Setsocksize(cache->fd, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(cache->fd, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Log(LOG_INFO, "INFO ( %s/core/RPKI ): rpki_rtr_connect(): rpki_rtr_srv_pipe_size: obtained=%d target=%d.\n", config.name, obtained, config.rpki_rtr_cache_pipe_size); } rc = connect(cache->fd, (struct sockaddr *) &cache->sock, cache->socklen); if (rc < 0) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_connect(): connect() failed: %s\n", config.name, strerror(errno)); rpki_rtr_close(cache); } else { Log(LOG_INFO, "INFO ( %s/core/RPKI ): Connected to RTR Cache: %s\n", config.name, config.rpki_rtr_cache); cache->session_id = 0; cache->serial = 0; } } void rpki_rtr_close(struct rpki_rtr_handle *cache) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_close()\n", config.name); close(cache->fd); cache->fd = ERR; cache->session_id = 0; cache->serial = 0; rpki_ribs_reset(&rpki_peer, &rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], &rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); } void rpki_rtr_send_reset_query(struct rpki_rtr_handle *cache) { struct rpki_rtr_reset rqm; ssize_t msglen; if (cache->fd > 0) { if (cache->now >= (cache->refresh.tstamp + cache->refresh.ivl)) { cache->refresh.tstamp = cache->now; } else return; if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_send_reset_query()\n", config.name); memset(&rqm, 0, sizeof(rqm)); rqm.version = config.rpki_rtr_cache_version; rqm.pdu_type = RPKI_RTR_PDU_RESET_QUERY; rqm.len = htonl(RPKI_RTR_PDU_RESET_QUERY_LEN); msglen = send(cache->fd, &rqm, sizeof(rqm), 0); if (msglen != RPKI_RTR_PDU_RESET_QUERY_LEN) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_send_reset_query(): send() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_send_serial_query(struct rpki_rtr_handle *cache) { struct rpki_rtr_serial snm; ssize_t msglen; if (cache->fd > 0) { if (cache->now >= (cache->refresh.tstamp + cache->refresh.ivl)) { cache->refresh.tstamp = cache->now; } else return; if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_send_serial_query()\n", config.name); memset(&snm, 0, sizeof(snm)); snm.version = config.rpki_rtr_cache_version; snm.pdu_type = RPKI_RTR_PDU_SERIAL_QUERY; snm.len = htonl(RPKI_RTR_PDU_SERIAL_QUERY_LEN); snm.session_id = htons(cache->session_id); snm.serial = htonl(cache->serial); msglen = send(cache->fd, &snm, sizeof(snm), 0); if (msglen != RPKI_RTR_PDU_SERIAL_QUERY_LEN) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_send_serial_query(): send() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_cache_response(struct rpki_rtr_handle *cache) { struct rpki_rtr_cache_response crm; ssize_t msglen; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_cache_response()\n", config.name); memset(&crm, 0, sizeof(crm)); msglen = recv(cache->fd, &crm, sizeof(crm), MSG_WAITALL); if (msglen == RPKI_RTR_PDU_CACHE_RESPONSE_LEN) { cache->session_id = ntohs(crm.session_id); } else { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_cache_response(): recv() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_serial_notify(struct rpki_rtr_handle *cache) { struct rpki_rtr_serial snm; ssize_t msglen; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_serial_notify()\n", config.name); memset(&snm, 0, sizeof(snm)); msglen = recv(cache->fd, &snm, sizeof(snm), MSG_WAITALL); if (msglen != RPKI_RTR_PDU_SERIAL_NOTIFY_LEN) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_serial_notify(): recv() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_ipv4_pref(struct rpki_rtr_handle *cache) { struct rpki_rtr_ipv4_pref p4m; ssize_t msglen; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_ipv4_pref()\n", config.name); memset(&p4m, 0, sizeof(p4m)); msglen = recv(cache->fd, &p4m, sizeof(p4m), MSG_WAITALL); if (msglen == RPKI_RTR_PDU_IPV4_PREFIX_LEN) { rpki_rtr_parse_ipv4_prefix(cache, &p4m); } else { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_ipv4_pref(): recv() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_ipv6_pref(struct rpki_rtr_handle *cache) { struct rpki_rtr_ipv6_pref p6m; ssize_t msglen; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_ipv6_pref()\n", config.name); memset(&p6m, 0, sizeof(p6m)); msglen = recv(cache->fd, &p6m, sizeof(p6m), MSG_WAITALL); if (msglen == RPKI_RTR_PDU_IPV6_PREFIX_LEN) { rpki_rtr_parse_ipv6_prefix(cache, &p6m); } else { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_ipv6_pref(): recv() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_eod(struct rpki_rtr_handle *cache, u_int8_t version) { struct rpki_rtr_eod_v0 eodm_v0, *eodm_cmn = NULL; struct rpki_rtr_eod_v1 eodm_v1; char *eodm = NULL; ssize_t msglen = 0; u_int8_t eodm_len = 0; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_eod()\n", config.name); if (version == RPKI_RTR_V0) { memset(&eodm_v0, 0, sizeof(eodm_v0)); eodm = (char *) &eodm_v0; eodm_cmn = (struct rpki_rtr_eod_v0 *) &eodm_v0; eodm_len = RPKI_RTR_PDU_END_OF_DATA_V0_LEN; } else { memset(&eodm_v1, 0, sizeof(eodm_v1)); eodm = (char *) &eodm_v1; eodm_cmn = (struct rpki_rtr_eod_v0 *) &eodm_v1; eodm_len = RPKI_RTR_PDU_END_OF_DATA_V1_LEN; } msglen = recv(cache->fd, eodm, eodm_len, MSG_WAITALL); if (msglen == eodm_len) { if (cache->session_id != ntohs(eodm_cmn->session_id)) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_eod(): unexpected session_id: %u\n", config.name, eodm_cmn->session_id); rpki_rtr_close(cache); } cache->serial = ntohl(eodm_cmn->serial); cache->refresh.tstamp = cache->now; cache->expire.tstamp = cache->now; if (version == RPKI_RTR_V1) { if (eodm_v1.retry_ivl) cache->retry.ivl = ntohl(eodm_v1.retry_ivl); if (eodm_v1.refresh_ivl) cache->refresh.ivl = ntohl(eodm_v1.refresh_ivl); if (eodm_v1.expire_ivl) cache->expire.ivl = ntohl(eodm_v1.expire_ivl); if (cache->expire.tstamp <= cache->retry.ivl || cache->expire.tstamp <= cache->refresh.ivl) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_eod(): invalid expire interval (refresh_ivl=%u retry_ivl=%u expire_ivl=%u)\n", config.name, cache->refresh.ivl, cache->retry.ivl, cache->expire.ivl); rpki_rtr_close(cache); } } if (config.debug) { Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_eod(): refresh_ivl=%u retry_ivl=%u expire_ivl=%u\n", config.name, cache->refresh.ivl, cache->retry.ivl, cache->expire.ivl); } } else { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_eod(): recv() failed\n", config.name); rpki_rtr_close(cache); } } } void rpki_rtr_recv_cache_reset(struct rpki_rtr_handle *cache) { struct rpki_rtr_reset crm; ssize_t msglen; if (cache-> fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_cache_reset()\n", config.name); memset(&crm, 0, sizeof(crm)); msglen = recv(cache->fd, &crm, sizeof(crm), MSG_WAITALL); if (msglen != RPKI_RTR_PDU_CACHE_RESET_LEN) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_cache_reset(): recv() failed\n", config.name); rpki_rtr_close(cache); } /* this will trigger a reset query */ cache->session_id = 0; cache->serial = 0; rpki_ribs_reset(&rpki_peer, &rpki_roa_db->rib[AFI_IP][SAFI_UNICAST], &rpki_roa_db->rib[AFI_IP6][SAFI_UNICAST]); } } void rpki_rtr_recv_router_key(struct rpki_rtr_handle *cache) { struct rpki_rtr_router_key rkm; ssize_t msglen; char *rkmbuf = NULL; if (cache-> fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_router_key()\n", config.name); memset(&rkm, 0, sizeof(rkm)); msglen = recv(cache->fd, &rkm, sizeof(rkm), MSG_WAITALL); if (msglen != sizeof(rkm)) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_router_key(): recv() failed (1)\n", config.name); rpki_rtr_close(cache); goto exit_lane; } if (rkm.version == RPKI_RTR_V0) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_router_key(): Router Key not supported in RTRv0\n", config.name); rpki_rtr_close(cache); goto exit_lane; } if (rkm.len > msglen) { u_int32_t rem_len = (rkm.len - msglen); rkmbuf = malloc(rem_len); msglen = recv(cache->fd, rkmbuf, rem_len, MSG_WAITALL); if (msglen != rem_len) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_router_key(): recv() failed (2)\n", config.name); rpki_rtr_close(cache); goto exit_lane; } // XXX exit_lane: if (rkmbuf) free(rkmbuf); } } } void rpki_rtr_recv_error_report(struct rpki_rtr_handle *cache) { struct rpki_rtr_err_report erm; ssize_t msglen; char *ermbuf = NULL, *errmsg_ptr; u_int32_t *encpdu_len; if (cache->fd > 0) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core/RPKI ): rpki_rtr_recv_error_report()\n", config.name); memset(&erm, 0, sizeof(erm)); msglen = recv(cache->fd, &erm, sizeof(erm), MSG_WAITALL); if (msglen != sizeof(erm)) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_error_report(): recv() failed (1)\n", config.name); rpki_rtr_close(cache); goto exit_lane; } if (erm.tot_len > msglen) { u_int32_t rem_len = (erm.tot_len - msglen); ermbuf = malloc(rem_len + 1); msglen = recv(cache->fd, ermbuf, rem_len, MSG_WAITALL); if (msglen != rem_len) { Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_error_report(): recv() failed (2)\n", config.name); rpki_rtr_close(cache); goto exit_lane; } ermbuf[rem_len] = '\0'; encpdu_len = (u_int32_t *) ermbuf; errmsg_ptr = (char *) (ermbuf + (*encpdu_len) + 4 + 4); Log(LOG_WARNING, "WARN ( %s/core/RPKI ): rpki_rtr_recv_error_report(): %s\n", config.name, errmsg_ptr); exit_lane: if (ermbuf) free(ermbuf); } } } pmacct-1.7.8/src/rpki/Makefile.am0000644000175000017500000000034614354105275015605 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmrpki.la libpmrpki_la_SOURCES = rpki.c rpki.h rpki_msg.c rpki_msg.h rpki_lookup.c \ rpki_lookup.h rpki_util.c rpki_util.h libpmrpki_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/rpki/rpki_lookup.h0000644000175000017500000000220014354105275016247 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef RPKI_LOOKUP_H #define RPKI_LOOKUP_H /* prototypes */ extern u_int8_t rpki_prefix_lookup(struct prefix *, as_t); extern u_int8_t rpki_vector_prefix_lookup(struct bgp_node_vector *); extern int rpki_prefix_lookup_node_match_cmp(struct bgp_info *, struct node_match_cmp_term2 *); #endif //RPKI_LOOKUP_H pmacct-1.7.8/src/plugin_common.c0000644000175000017500000011711314354105275015617 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_common.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "ip_flow.h" #include "classifier.h" #include "crc32.h" #include "preprocess-internal.h" /* Global variables */ void (*insert_func)(struct primitives_ptrs *, struct insert_data *); /* pointer to INSERT function */ void (*purge_func)(struct chained_cache *[], int, int); /* pointer to purge function */ struct scratch_area sa; struct chained_cache *cache; struct chained_cache **queries_queue, **pending_queries_queue, *pqq_container; struct timeval flushtime; int qq_ptr, pqq_ptr, pp_size, pb_size, pn_size, pm_size, pt_size, pc_size; int dbc_size, quit; time_t refresh_deadline; void (*basetime_init)(time_t); void (*basetime_eval)(struct timeval *, struct timeval *, time_t); int (*basetime_cmp)(struct timeval *, struct timeval *); struct timeval basetime, ibasetime, new_basetime; time_t timeslot; int dyn_table, dyn_table_time_only; /* Functions */ void P_set_signals() { signal(SIGINT, P_exit_now); /* XXX: SIGHUP? */ signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); } void P_init_default_values() { if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { if (config.logfile_fd) fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } reload_map = FALSE; basetime_init = NULL; basetime_eval = NULL; basetime_cmp = NULL; memset(&basetime, 0, sizeof(basetime)); memset(&ibasetime, 0, sizeof(ibasetime)); memset(×lot, 0, sizeof(timeslot)); if (!config.sql_refresh_time) config.sql_refresh_time = DEFAULT_PLUGIN_COMMON_REFRESH_TIME; if (!config.print_cache_entries) config.print_cache_entries = PRINT_CACHE_ENTRIES; if (!config.dump_max_writers) config.dump_max_writers = DEFAULT_PLUGIN_COMMON_WRITERS_NO; dump_writers.list = malloc(config.dump_max_writers * sizeof(pid_t)); dump_writers_init(); pp_size = sizeof(struct pkt_primitives); pb_size = sizeof(struct pkt_bgp_primitives); pn_size = sizeof(struct pkt_nat_primitives); pm_size = sizeof(struct pkt_mpls_primitives); pt_size = sizeof(struct pkt_tunnel_primitives); pc_size = config.cpptrs.len; dbc_size = sizeof(struct chained_cache); memset(&sa, 0, sizeof(struct scratch_area)); sa.num = config.print_cache_entries*AVERAGE_CHAIN_LEN; sa.size = sa.num*dbc_size; Log(LOG_INFO, "INFO ( %s/%s ): cache entries=%d base cache memory=%" PRIu64 " bytes\n", config.name, config.type, config.print_cache_entries, ((config.print_cache_entries * dbc_size) + (2 * ((sa.num + config.print_cache_entries) * sizeof(struct chained_cache *))) + sa.size)); cache = (struct chained_cache *) pm_malloc(config.print_cache_entries*dbc_size); queries_queue = (struct chained_cache **) pm_malloc((sa.num+config.print_cache_entries)*sizeof(struct chained_cache *)); pending_queries_queue = (struct chained_cache **) pm_malloc((sa.num+config.print_cache_entries)*sizeof(struct chained_cache *)); sa.base = (unsigned char *) pm_malloc(sa.size); sa.ptr = sa.base; sa.next = NULL; memset(cache, 0, config.print_cache_entries*sizeof(struct chained_cache)); memset(queries_queue, 0, (sa.num+config.print_cache_entries)*sizeof(struct chained_cache *)); memset(pending_queries_queue, 0, (sa.num+config.print_cache_entries)*sizeof(struct chained_cache *)); memset(sa.base, 0, sa.size); memset(&flushtime, 0, sizeof(flushtime)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); /* handling purge preprocessor */ set_preprocess_funcs(config.sql_preprocess, &prep, PREP_DICT_PRINT); } void P_config_checks() { if (config.nfacctd_pro_rating && config.nfacctd_stitching) { Log(LOG_ERR, "ERROR ( %s/%s ): Pro-rating (ie. nfacctd_pro_rating) and stitching (ie. nfacctd_stitching) are mutual exclusive. Exiting.\n", config.name, config.type); goto exit_lane; } return; exit_lane: exit_gracefully(1); } unsigned int P_cache_modulo(struct primitives_ptrs *prim_ptrs) { struct pkt_data *pdata = prim_ptrs->data; struct pkt_primitives *srcdst = &pdata->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; register unsigned int modulo; modulo = cache_crc32((unsigned char *)srcdst, pp_size); if (pbgp) modulo ^= cache_crc32((unsigned char *)pbgp, pb_size); if (pnat) modulo ^= cache_crc32((unsigned char *)pnat, pn_size); if (pmpls) modulo ^= cache_crc32((unsigned char *)pmpls, pm_size); if (ptun) modulo ^= cache_crc32((unsigned char *)ptun, pt_size); if (pcust) modulo ^= cache_crc32((unsigned char *)pcust, pc_size); if (pvlen) modulo ^= cache_crc32((unsigned char *)pvlen, (PvhdrSz + pvlen->tot_len)); return modulo %= config.print_cache_entries; } struct chained_cache *P_cache_search(struct primitives_ptrs *prim_ptrs) { struct pkt_data *pdata = prim_ptrs->data; struct pkt_primitives *data = &pdata->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; unsigned int modulo = P_cache_modulo(prim_ptrs); struct chained_cache *cache_ptr = &cache[modulo]; int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE; int res_time = TRUE, res_cust = TRUE, res_vlen = TRUE; start: res_data = memcmp(&cache_ptr->primitives, data, sizeof(struct pkt_primitives)); if (basetime_cmp) { res_time = (*basetime_cmp)(&cache_ptr->basetime, &ibasetime); } else res_time = FALSE; if (pbgp) { if (cache_ptr->pbgp) res_bgp = memcmp(cache_ptr->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); } else res_bgp = FALSE; if (pnat) { if (cache_ptr->pnat) res_nat = memcmp(cache_ptr->pnat, pnat, sizeof(struct pkt_nat_primitives)); } else res_nat = FALSE; if (pmpls) { if (cache_ptr->pmpls) res_mpls = memcmp(cache_ptr->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); } else res_mpls = FALSE; if (ptun) { if (cache_ptr->ptun) res_tun = memcmp(cache_ptr->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); } else res_tun = FALSE; if (pcust) { if (cache_ptr->pcust) res_cust = memcmp(cache_ptr->pcust, pcust, config.cpptrs.len); } else res_cust = FALSE; if (pvlen) { if (cache_ptr->pvlen) res_vlen = vlen_prims_cmp(cache_ptr->pvlen, pvlen); } else res_vlen = FALSE; if (res_data || res_bgp || res_nat || res_mpls || res_tun || res_time || res_cust || res_vlen) { if (cache_ptr->valid == PRINT_CACHE_INUSE) { if (cache_ptr->next) { cache_ptr = cache_ptr->next; goto start; } } } else return cache_ptr; return NULL; } void P_cache_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; unsigned int modulo = P_cache_modulo(prim_ptrs); struct chained_cache *cache_ptr = &cache[modulo]; struct pkt_primitives *srcdst = &data->primitives; int res_data, res_bgp, res_nat, res_mpls, res_tun, res_time, res_cust, res_vlen; /* pro_rating vars */ int time_delta = 0, time_total = 0; pm_counter_t tot_bytes = 0, tot_packets = 0, tot_flows = 0; tot_bytes = data->pkt_len; tot_packets = data->pkt_num; tot_flows = data->flo_num; if (config.sql_history && (*basetime_eval)) { memcpy(&ibasetime, &basetime, sizeof(ibasetime)); (*basetime_eval)(&data->time_start, &ibasetime, timeslot); } new_timeslot: /* pro_rating, if needed */ if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) { if (data->time_end.tv_sec > data->time_start.tv_sec) { time_total = data->time_end.tv_sec - data->time_start.tv_sec; time_delta = MIN(data->time_end.tv_sec, ibasetime.tv_sec + timeslot) - MAX(data->time_start.tv_sec, ibasetime.tv_sec); if (time_delta > 0 && time_total > 0 && time_delta < time_total) { float ratio = (float) time_total / (float) time_delta; if (tot_bytes) data->pkt_len = MAX((float)tot_bytes / ratio, 1); if (tot_packets) data->pkt_num = MAX((float)tot_packets / ratio, 1); if (tot_flows) data->flo_num = MAX((float)tot_flows / ratio, 1); } } } start: res_data = res_bgp = res_nat = res_mpls = res_tun = res_time = res_cust = res_vlen = TRUE; res_data = memcmp(&cache_ptr->primitives, srcdst, sizeof(struct pkt_primitives)); if (basetime_cmp) { res_time = (*basetime_cmp)(&cache_ptr->basetime, &ibasetime); } else res_time = FALSE; if (pbgp) { if (cache_ptr->pbgp) res_bgp = memcmp(cache_ptr->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); } else res_bgp = FALSE; if (pnat) { if (cache_ptr->pnat) res_nat = memcmp(cache_ptr->pnat, pnat, sizeof(struct pkt_nat_primitives)); } else res_nat = FALSE; if (pmpls) { if (cache_ptr->pmpls) res_mpls = memcmp(cache_ptr->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); } else res_mpls = FALSE; if (ptun) { if (cache_ptr->ptun) res_tun = memcmp(cache_ptr->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); } else res_tun = FALSE; if (pcust) { if (cache_ptr->pcust) res_cust = memcmp(cache_ptr->pcust, pcust, config.cpptrs.len); } else res_cust = FALSE; if (pvlen) { if (cache_ptr->pvlen) res_vlen = vlen_prims_cmp(cache_ptr->pvlen, pvlen); } else res_vlen = FALSE; if (res_data || res_bgp || res_nat || res_mpls || res_tun || res_time || res_cust || res_vlen) { /* aliasing of entries */ if (cache_ptr->valid == PRINT_CACHE_INUSE) { if (cache_ptr->next) { cache_ptr = cache_ptr->next; goto start; } else { cache_ptr = P_cache_attach_new_node(cache_ptr); if (!cache_ptr) goto safe_action; else { queries_queue[qq_ptr] = cache_ptr; qq_ptr++; } } } else { queries_queue[qq_ptr] = cache_ptr; qq_ptr++; } /* we add the new entry in the cache */ memcpy(&cache_ptr->primitives, srcdst, sizeof(struct pkt_primitives)); if (pbgp) { if (!cache_ptr->pbgp) cache_ptr->pbgp = (struct pkt_bgp_primitives *) malloc(PbgpSz); if (cache_ptr->pbgp) memcpy(cache_ptr->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); else goto safe_action; } else { if (cache_ptr->pbgp) free(cache_ptr->pbgp); cache_ptr->pbgp = NULL; } if (pnat) { if (!cache_ptr->pnat) cache_ptr->pnat = (struct pkt_nat_primitives *) malloc(PnatSz); if (cache_ptr->pnat) memcpy(cache_ptr->pnat, pnat, sizeof(struct pkt_nat_primitives)); else goto safe_action; } else { if (cache_ptr->pnat) free(cache_ptr->pnat); cache_ptr->pnat = NULL; } if (pmpls) { if (!cache_ptr->pmpls) cache_ptr->pmpls = (struct pkt_mpls_primitives *) malloc(PmplsSz); if (cache_ptr->pmpls) memcpy(cache_ptr->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); else goto safe_action; } else { if (cache_ptr->pmpls) free(cache_ptr->pmpls); cache_ptr->pmpls = NULL; } if (ptun) { if (!cache_ptr->ptun) cache_ptr->ptun = (struct pkt_tunnel_primitives *) malloc(PtunSz); if (cache_ptr->ptun) memcpy(cache_ptr->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); else goto safe_action; } else { if (cache_ptr->ptun) free(cache_ptr->ptun); cache_ptr->ptun = NULL; } if (pcust) { if (!cache_ptr->pcust) cache_ptr->pcust = malloc(config.cpptrs.len); if (cache_ptr->pcust) memcpy(cache_ptr->pcust, pcust, config.cpptrs.len); else goto safe_action; } else { if (cache_ptr->pcust) free(cache_ptr->pcust); cache_ptr->pcust = NULL; } /* if we have a pvlen from before let's free it up due to the vlen nature of the memory area */ if (cache_ptr->pvlen) { vlen_prims_free(cache_ptr->pvlen); cache_ptr->pvlen = NULL; } if (pvlen) { cache_ptr->pvlen = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen); if (!cache_ptr->pvlen) goto safe_action; } cache_ptr->packet_counter = data->pkt_num; cache_ptr->flow_counter = data->flo_num; cache_ptr->bytes_counter = data->pkt_len; cache_ptr->flow_type = data->flow_type; cache_ptr->tcp_flags = data->tcp_flags; cache_ptr->tunnel_tcp_flags = data->tunnel_tcp_flags; if (config.nfacctd_stitching) { if (!cache_ptr->stitch) { cache_ptr->stitch = (struct pkt_stitching *) malloc(sizeof(struct pkt_stitching)); } if (cache_ptr->stitch) { P_set_stitch(cache_ptr, data, idata); } else Log(LOG_WARNING, "WARN ( %s/%s ): Finished memory for flow stitching.\n", config.name, config.type); } else assert(!cache_ptr->stitch); cache_ptr->valid = PRINT_CACHE_INUSE; cache_ptr->basetime.tv_sec = ibasetime.tv_sec; cache_ptr->basetime.tv_usec = ibasetime.tv_usec; } else { if (cache_ptr->valid == PRINT_CACHE_INUSE) { /* everything is ok; summing counters */ cache_ptr->packet_counter += data->pkt_num; cache_ptr->flow_counter += data->flo_num; cache_ptr->bytes_counter += data->pkt_len; cache_ptr->flow_type = data->flow_type; cache_ptr->tcp_flags |= data->tcp_flags; cache_ptr->tunnel_tcp_flags |= data->tunnel_tcp_flags; if (config.nfacctd_stitching) { if (cache_ptr->stitch) { P_update_stitch(cache_ptr, data, idata); } } } else { /* entry invalidated; restarting counters */ cache_ptr->packet_counter = data->pkt_num; cache_ptr->flow_counter = data->flo_num; cache_ptr->bytes_counter = data->pkt_len; cache_ptr->flow_type = data->flow_type; cache_ptr->tcp_flags = data->tcp_flags; cache_ptr->tunnel_tcp_flags = data->tunnel_tcp_flags; if (config.nfacctd_stitching) { P_set_stitch(cache_ptr, data, idata); } cache_ptr->valid = PRINT_CACHE_INUSE; cache_ptr->basetime.tv_sec = ibasetime.tv_sec; cache_ptr->basetime.tv_usec = ibasetime.tv_usec; queries_queue[qq_ptr] = cache_ptr; qq_ptr++; } } /* pro_rating */ if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) { if ((ibasetime.tv_sec + timeslot) < data->time_end.tv_sec) { ibasetime.tv_sec += timeslot; goto new_timeslot; } } return; safe_action: { pid_t ret; Log(LOG_INFO, "INFO ( %s/%s ): Finished cache entries (ie. print_cache_entries). Purging.\n", config.name, config.type); if (config.type_id == PLUGIN_ID_PRINT && config.sql_table && !config.print_output_file_append) Log(LOG_WARNING, "WARN ( %s/%s ): Make sure print_output_file_append is set to true.\n", config.name, config.type); if (qq_ptr) P_cache_mark_flush(queries_queue, qq_ptr, FALSE); /* Writing out to replenish cache space */ dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) { switch (ret = fork()) { case 0: /* Child */ pm_setproctitle("%s %s [%s]", config.type, "Plugin -- Writer (urgent)", config.name); config.is_forked = TRUE; (*purge_func)(queries_queue, qq_ptr, TRUE); exit_gracefully(0); default: /* Parent */ if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork writer: %s\n", config.name, config.type, strerror(errno)); else dump_writers_add(ret); break; } } else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); P_cache_flush(queries_queue, qq_ptr); qq_ptr = FALSE; if (pqq_ptr) { P_cache_insert_pending(pending_queries_queue, pqq_ptr, pqq_container); pqq_ptr = 0; } /* try to insert again */ (*insert_func)(prim_ptrs, idata); } } void P_cache_insert_pending(struct chained_cache *queue[], int index, struct chained_cache *container) { struct chained_cache *cache_ptr; struct primitives_ptrs prim_ptrs; struct pkt_data pdata; unsigned int modulo, j; if (!index || !container) return; for (j = 0; j < index; j++) { memset(&prim_ptrs, 0, sizeof(prim_ptrs)); prim_ptrs.data = &pdata; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); modulo = P_cache_modulo(&prim_ptrs); cache_ptr = &cache[modulo]; start: if (cache_ptr->valid == PRINT_CACHE_INUSE) { if (cache_ptr->next) { cache_ptr = cache_ptr->next; goto start; } else { cache_ptr = P_cache_attach_new_node(cache_ptr); if (!cache_ptr) { Log(LOG_WARNING, "WARN ( %s/%s ): Finished cache entries. Pending entries will be lost.\n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): You may want to set a larger print_cache_entries value.\n", config.name, config.type); break; } else { queries_queue[qq_ptr] = cache_ptr; qq_ptr++; } } } else { queries_queue[qq_ptr] = cache_ptr; qq_ptr++; } if (cache_ptr->pbgp) free(cache_ptr->pbgp); if (cache_ptr->pnat) free(cache_ptr->pnat); if (cache_ptr->pmpls) free(cache_ptr->pmpls); if (cache_ptr->ptun) free(cache_ptr->ptun); if (cache_ptr->pcust) free(cache_ptr->pcust); if (cache_ptr->pvlen) free(cache_ptr->pvlen); if (cache_ptr->stitch) free(cache_ptr->stitch); memcpy(cache_ptr, &container[j], dbc_size); container[j].pbgp = NULL; container[j].pnat = NULL; container[j].pmpls = NULL; container[j].ptun = NULL; container[j].pcust = NULL; container[j].pvlen = NULL; container[j].stitch = NULL; cache_ptr->valid = PRINT_CACHE_INUSE; cache_ptr->next = NULL; } free(container); } void P_cache_handle_flush_event(struct ports_table *pt, struct protos_table *prt, struct protos_table *tost) { pid_t ret; if (qq_ptr) P_cache_mark_flush(queries_queue, qq_ptr, FALSE); dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) { switch (ret = fork()) { case 0: /* Child */ pm_setproctitle("%s %s [%s]", config.type, "Plugin -- Writer", config.name); config.is_forked = TRUE; (*purge_func)(queries_queue, qq_ptr, FALSE); exit_gracefully(0); default: /* Parent */ if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork writer: %s\n", config.name, config.type, strerror(errno)); else dump_writers_add(ret); break; } } else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); P_cache_flush(queries_queue, qq_ptr); gettimeofday(&flushtime, NULL); refresh_deadline += config.sql_refresh_time; qq_ptr = FALSE; memset(&new_basetime, 0, sizeof(new_basetime)); if (pqq_ptr) { P_cache_insert_pending(pending_queries_queue, pqq_ptr, pqq_container); pqq_ptr = 0; } if (reload_map) { load_networks(config.networks_file, &nt, &nc); load_ports(config.ports_file, pt); load_protos(config.protos_file, prt); load_tos(config.tos_file, tost); reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } } void P_cache_mark_flush(struct chained_cache *queue[], int index, int exiting) { struct timeval commit_basetime; int j, delay = 0; memset(&commit_basetime, 0, sizeof(commit_basetime)); /* check-pointing */ if (new_basetime.tv_sec) commit_basetime.tv_sec = new_basetime.tv_sec; else commit_basetime.tv_sec = basetime.tv_sec; /* evaluating any delay we may have to introduce */ if (config.sql_startup_delay) { if (timeslot) delay = config.sql_startup_delay/timeslot; delay = delay*timeslot; } /* mark committed entries as such */ if (!exiting) { for (j = 0, pqq_ptr = 0; j < index; j++) { if (commit_basetime.tv_sec < (queue[j]->basetime.tv_sec+delay)) { pending_queries_queue[pqq_ptr] = queue[j]; pqq_ptr++; } else queue[j]->valid = PRINT_CACHE_COMMITTED; } if (pqq_ptr) { pqq_container = (struct chained_cache *) malloc(pqq_ptr*dbc_size); if (!pqq_container) { Log(LOG_ERR, "ERROR ( %s/%s ): P_cache_mark_flush() cannot allocate pqq_container. Exiting ..\n", config.name, config.type); exit_gracefully(1); } } /* we copy un-committed elements to a container structure for re-insertion in cache. As we copy elements out of the cache we mark entries as free */ for (j = 0; j < pqq_ptr; j++) { memcpy(&pqq_container[j], pending_queries_queue[j], dbc_size); pending_queries_queue[j]->pbgp = NULL; pending_queries_queue[j]->pnat = NULL; pending_queries_queue[j]->pmpls = NULL; pending_queries_queue[j]->ptun = NULL; pending_queries_queue[j]->pcust = NULL; pending_queries_queue[j]->pvlen = NULL; pending_queries_queue[j]->stitch = NULL; pending_queries_queue[j]->valid = PRINT_CACHE_FREE; pending_queries_queue[j] = &pqq_container[j]; } } else { for (j = 0, pqq_ptr = 0; j < index; j++) queue[j]->valid = PRINT_CACHE_COMMITTED; } } void P_cache_flush(struct chained_cache *queue[], int index) { int j; for (j = 0; j < index; j++) { queue[j]->valid = PRINT_CACHE_FREE; queue[j]->next = NULL; } /* rewinding scratch area stuff */ sa.ptr = sa.base; } struct chained_cache *P_cache_attach_new_node(struct chained_cache *elem) { if ((sa.ptr + (2 * sizeof(struct chained_cache))) <= (sa.base + sa.size)) { sa.ptr += sizeof(struct chained_cache); elem->next = (struct chained_cache *) sa.ptr; return (struct chained_cache *) sa.ptr; } else return NULL; } void P_sum_host_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; struct host_addr tmp; memcpy(&tmp, &data->primitives.dst_ip, HostAddrSz); memset(&data->primitives.dst_ip, 0, HostAddrSz); P_cache_insert(prim_ptrs, idata); memcpy(&data->primitives.src_ip, &tmp, HostAddrSz); P_cache_insert(prim_ptrs, idata); } void P_sum_port_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; u_int16_t port; port = data->primitives.dst_port; data->primitives.dst_port = 0; P_cache_insert(prim_ptrs, idata); data->primitives.src_port = port; P_cache_insert(prim_ptrs, idata); } void P_sum_as_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; as_t asn; asn = data->primitives.dst_as; data->primitives.dst_as = 0; P_cache_insert(prim_ptrs, idata); data->primitives.src_as = asn; P_cache_insert(prim_ptrs, idata); } #if defined (HAVE_L2) void P_sum_mac_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; u_char macaddr[ETH_ADDR_LEN]; memcpy(macaddr, &data->primitives.eth_dhost, ETH_ADDR_LEN); memset(data->primitives.eth_dhost, 0, ETH_ADDR_LEN); P_cache_insert(prim_ptrs, idata); memcpy(&data->primitives.eth_shost, macaddr, ETH_ADDR_LEN); P_cache_insert(prim_ptrs, idata); } #endif void P_exit_now(int signum) { if (qq_ptr) P_cache_mark_flush(queries_queue, qq_ptr, TRUE); dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) (*purge_func)(queries_queue, qq_ptr, FALSE); else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); if (config.pidfile) remove_pid_file(config.pidfile); wait(NULL); exit_gracefully(0); } int P_trigger_exec(char *filename) { char *args[2] = { filename, NULL }; int pid; #ifdef HAVE_VFORK switch (pid = vfork()) { #else switch (pid = fork()) { #endif case -1: return -1; case 0: execv(filename, args); _exit(0); } return 0; } void P_init_historical_acct(time_t now) { time_t t = 0; basetime.tv_sec = now; basetime.tv_usec = 0; if (config.sql_history == COUNT_SECONDLY) timeslot = config.sql_history_howmany; else if (config.sql_history == COUNT_MINUTELY) timeslot = config.sql_history_howmany*60; else if (config.sql_history == COUNT_HOURLY) timeslot = config.sql_history_howmany*3600; else if (config.sql_history == COUNT_DAILY) timeslot = config.sql_history_howmany*86400; else if (config.sql_history == COUNT_WEEKLY) timeslot = config.sql_history_howmany*86400*7; else if (config.sql_history == COUNT_MONTHLY) { basetime.tv_sec = roundoff_time(basetime.tv_sec, "d"); /* resetting day of month */ timeslot = calc_monthly_timeslot(basetime.tv_sec, config.sql_history_howmany, ADD); } /* round off stuff */ t = roundoff_time(basetime.tv_sec, config.sql_history_roundoff); while ((t+timeslot) < basetime.tv_sec) { t += timeslot; if (config.sql_history == COUNT_MONTHLY) timeslot = calc_monthly_timeslot(t, config.sql_history_howmany, ADD); } if (config.sql_history_offset) { if (config.sql_history_offset >= timeslot) { Log(LOG_ERR, "ERROR ( %s/%s ): History offset (ie. sql_history_offset) must be < history (ie. sql_history).\n", config.name, config.type); exit_gracefully(1); } t = t - (timeslot + config.sql_history_offset); } basetime.tv_sec = t; memset(&new_basetime, 0, sizeof(new_basetime)); } void P_init_refresh_deadline(time_t *now, int refresh_time, int startup_delay, char *roundoff) { time_t t; t = roundoff_time((*now), roundoff); while ((t + refresh_time) < (*now)) t += refresh_time; *now = t; *now += (refresh_time + startup_delay); /* it's a deadline not a basetime */ } void P_eval_historical_acct(struct timeval *stamp, struct timeval *basetime, time_t timeslot) { if (stamp->tv_sec) { if (config.sql_history != COUNT_MONTHLY) { int residual; if (basetime->tv_sec > stamp->tv_sec) { residual = timeslot - ((basetime->tv_sec - stamp->tv_sec) % timeslot); } else { residual = ((stamp->tv_sec - basetime->tv_sec) % timeslot); } basetime->tv_sec = stamp->tv_sec - residual; } else { while (basetime->tv_sec > stamp->tv_sec) { timeslot = calc_monthly_timeslot(basetime->tv_sec, config.sql_history_howmany, SUB); basetime->tv_sec -= timeslot; } while ((basetime->tv_sec+timeslot) < stamp->tv_sec) { basetime->tv_sec += timeslot; timeslot = calc_monthly_timeslot(basetime->tv_sec, config.sql_history_howmany, ADD); } } } } int P_cmp_historical_acct(struct timeval *entry_basetime, struct timeval *insert_basetime) { int ret = TRUE; ret = memcmp(entry_basetime, insert_basetime, sizeof(struct timeval)); return ret; } void primptrs_set_all_from_chained_cache(struct primitives_ptrs *prim_ptrs, struct chained_cache *entry) { struct pkt_data *data; if (prim_ptrs && entry) { data = prim_ptrs->data; memset(data, 0, PdataSz); data->primitives = entry->primitives; prim_ptrs->pbgp = entry->pbgp; prim_ptrs->pnat = entry->pnat; prim_ptrs->pmpls = entry->pmpls; prim_ptrs->ptun = entry->ptun; prim_ptrs->pcust = entry->pcust; prim_ptrs->pvlen = entry->pvlen; } } void P_handle_table_dyn_rr(char *new, int newlen, char *old, struct p_table_rr *rk_rr) { char index_str[SRVBUFLEN]; int oldlen; oldlen = strlen(old); if (oldlen <= newlen) strcpy(new, old); else { strncpy(new, old, newlen); return; } memset(index_str, 0, SRVBUFLEN); snprintf(index_str, SRVBUFLEN, "_%u", rk_rr->next); strncat(new, index_str, (newlen-oldlen)); rk_rr->next++; rk_rr->next %= rk_rr->max; } void P_update_time_reference(struct insert_data *idata) { idata->now = time(NULL); if (config.nfacctd_stitching) { gettimeofday(&idata->nowtv, NULL); if (config.timestamps_secs) { idata->nowtv.tv_usec = 0; } } if (config.sql_history) { while (idata->now > (basetime.tv_sec + timeslot)) { new_basetime.tv_sec = basetime.tv_sec; basetime.tv_sec += timeslot; if (config.sql_history == COUNT_MONTHLY) timeslot = calc_monthly_timeslot(basetime.tv_sec, config.sql_history_howmany, ADD); } } } void P_set_stitch(struct chained_cache *cache_ptr, struct pkt_data *data, struct insert_data *idata) { if (data->time_start.tv_sec) { memcpy(&cache_ptr->stitch->timestamp_min, &data->time_start, sizeof(struct timeval)); } else { memcpy(&cache_ptr->stitch->timestamp_min, &idata->nowtv, sizeof(struct timeval)); } if (data->time_end.tv_sec) { memcpy(&cache_ptr->stitch->timestamp_max, &data->time_end, sizeof(struct timeval)); } else { memcpy(&cache_ptr->stitch->timestamp_max, &idata->nowtv, sizeof(struct timeval)); } } void P_update_stitch(struct chained_cache *cache_ptr, struct pkt_data *data, struct insert_data *idata) { if (data->time_end.tv_sec) { if (data->time_end.tv_sec > cache_ptr->stitch->timestamp_max.tv_sec && data->time_end.tv_usec > cache_ptr->stitch->timestamp_max.tv_usec) { memcpy(&cache_ptr->stitch->timestamp_max, &data->time_end, sizeof(struct timeval)); } } else { memcpy(&cache_ptr->stitch->timestamp_max, &idata->nowtv, sizeof(struct timeval)); } } cdada_list_t *ptm_labels_to_linked_list(const char *ptm_labels) { /* Max amount of tokens per string: 128 Labels */ const int MAX_TOKENS = 256; /* len of the incoming/normalized string */ size_t PTM_LABELS_LEN = strlen(ptm_labels); /* incoming/normalized str to array */ char ptm_array_labels[PTM_LABELS_LEN + 1]; memset(&ptm_array_labels, 0, sizeof(ptm_array_labels)); /* no overflow risk */ strcpy(ptm_array_labels, ptm_labels); cdada_list_t *ptm_linked_list = cdada_list_create(ptm_label); ptm_label lbl; char *token = NULL; char *tokens[MAX_TOKENS]; /* init pointers to NULL */ size_t idx_0; for (idx_0 = 0; idx_0 < MAX_TOKENS; idx_0++) { tokens[idx_0] = NULL; } size_t tokens_counter = 0; for (token = strtok(ptm_array_labels, DEFAULT_SEP); token != NULL; token = strtok(NULL, DEFAULT_SEP)) { tokens[tokens_counter] = token; tokens_counter++; } size_t list_counter; for (list_counter = 0; (list_counter < tokens_counter) && (tokens[list_counter] != NULL) && ((list_counter + 1) < tokens_counter) && (tokens[list_counter + 1] != NULL); list_counter += 2) { memset(&lbl, 0, sizeof(lbl)); if (strlen(tokens[list_counter]) > (MAX_PTM_LABEL_TOKEN_LEN - 1)) { tokens[list_counter][MAX_PTM_LABEL_TOKEN_LEN - 2] = '$'; tokens[list_counter][MAX_PTM_LABEL_TOKEN_LEN - 1] = '\0'; } if (strlen(tokens[list_counter + 1]) > (MAX_PTM_LABEL_TOKEN_LEN - 1)) { tokens[list_counter + 1][MAX_PTM_LABEL_TOKEN_LEN - 2] = '$'; tokens[list_counter + 1][MAX_PTM_LABEL_TOKEN_LEN - 1] = '\0'; } strncpy(lbl.key, tokens[list_counter], (MAX_PTM_LABEL_TOKEN_LEN - 1)); strncpy(lbl.value, tokens[list_counter + 1], (MAX_PTM_LABEL_TOKEN_LEN - 1)); cdada_list_push_back(ptm_linked_list, &lbl); } return ptm_linked_list; } cdada_list_t *tcpflags_to_linked_list(size_t tcpflags_decimal) { const int TCP_FLAGS = 6; /* Generate the tcpflag's binary array */ const char tcpflags_mask[][TCP_FLAG_LEN] = {"URG", "ACK", "PSH", "RST", "SYN", "FIN"}; size_t tcpflags_binary[TCP_FLAGS]; memset(&tcpflags_binary, 0, sizeof(tcpflags_binary)); /* tcpflags binary format (valid decimals between 1 & 63) */ size_t idx_0; if ((tcpflags_decimal > 0) && (tcpflags_decimal) < 64) { for (idx_0 = (TCP_FLAGS -1); tcpflags_decimal > 0 && idx_0 >= 0; idx_0--) { tcpflags_binary[idx_0] = (tcpflags_decimal % 2); tcpflags_decimal /= 2; } } /* Generate the tcpflags' linked-list */ cdada_list_t *tcpflag_linked_list = cdada_list_create(tcpflag); tcpflag tcpstate; size_t idx_1; for (idx_1 = 0; idx_1 < TCP_FLAGS; idx_1++) { memset(&tcpstate, 0, sizeof(tcpstate)); if (!tcpflags_binary[idx_1]) { strncpy(tcpstate.flag, "NULL", (TCP_FLAG_LEN - 1)); } else { strncpy(tcpstate.flag, tcpflags_mask[idx_1], (TCP_FLAG_LEN - 1)); } cdada_list_push_back(tcpflag_linked_list, &tcpstate); } return tcpflag_linked_list; } cdada_list_t *fwd_status_to_linked_list() { const int FWD_STATUS_REASON_CODES = 23; /* RFC-7270: forwardingStatus with a compliant reason code */ const unsigned int fwd_status_decimal[] = { 64, 65, 66, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 192, 193, 194, 195 }; const char fwd_status_description[][FWD_TYPES_STR_LEN] = { "FORWARDED Unknown", "FORWARDED Fragmented", "FORWARDED Not Fragmented", "DROPPED Unknown", "DROPPED ACL deny", "DROPPED ACL drop", "DROPPED Unroutable", "DROPPED Adjacency", "DROPPED Fragmentation and DF set", "DROPPED Bad header checksum", "DROPPED Bad total Length", "DROPPED Bad header length", "DROPPED bad TTL", "DROPPED Policer", "DROPPED WRED", "DROPPED RPF", "DROPPED For us", "DROPPED Bad output interface", "DROPPED Hardware", "CONSUMED Unknown", "CONSUMED Punt Adjacency", "CONSUMED Incomplete Adjacency", "CONSUMED For us", }; /* Generate the fwd_status' linked-list */ cdada_list_t *fwd_status_linked_list = cdada_list_create(fwd_status); fwd_status fwdstate; size_t idx_0; for (idx_0 = 0; idx_0 < FWD_STATUS_REASON_CODES; idx_0++) { memset(&fwdstate, 0, sizeof(fwdstate)); fwdstate.decimal = fwd_status_decimal[idx_0]; strncpy(fwdstate.description, fwd_status_description[idx_0], (FWD_TYPES_STR_LEN - 1)); cdada_list_push_back(fwd_status_linked_list, &fwdstate); } return fwd_status_linked_list; } void mpls_label_stack_to_str(char *str_label_stack, int sls_len, u_int32_t *label_stack, int ls_len) { int max_mpls_label_stack_dec = 0, idx_0; char label_buf[MAX_MPLS_LABEL_LEN]; u_int8_t ls_depth = 0; if (!(ls_len % 4)) { ls_depth = (ls_len / 4); } else { return; } memset(str_label_stack, 0, sls_len); for (idx_0 = 0; idx_0 < ls_depth; idx_0++) { memset(&label_buf, 0, sizeof(label_buf)); snprintf(label_buf, MAX_MPLS_LABEL_LEN, "%u", label_stack[idx_0]); strncat(str_label_stack, label_buf, (sls_len - max_mpls_label_stack_dec)); /* Avoiding separator to last label */ if (idx_0 != (ls_depth - 1)) { strncat(str_label_stack, "_", (sls_len - max_mpls_label_stack_dec)); max_mpls_label_stack_dec = (strlen(label_buf) + strlen("_") + 2); } else { max_mpls_label_stack_dec = (strlen(label_buf) + 2); } } } /* XXX, merge load_protos() and load_ports() */ void load_protos(char *filename, struct protos_table *pt) { FILE *file; char buf[SUPERSHORTBUFLEN]; int ret, rows = 1, newline = TRUE, buf_eff_len, idx; struct stat st; memset(&st, 0, sizeof(st)); if (filename) { if ((file = fopen(filename,"r")) == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); goto handle_error; } else { memset(pt, 0, sizeof(struct protos_table)); while (!feof(file)) { if (fgets(buf, sizeof(buf), file)) { if (strchr(buf, '\n')) { if (!newline) { newline = TRUE; continue; } } else { if (!newline) continue; newline = FALSE; } trim_spaces(buf); buf_eff_len = strlen(buf); if (!buf_eff_len || (buf[0] == '!')) { continue; } for (idx = 0, ret = 0; idx < buf_eff_len; idx++) { ret = isdigit(buf[idx]); if (!ret) { break; } } if (!ret) { for (idx = 0; _protocols[idx].number != -1; idx++) { if (!strcmp(buf, _protocols[idx].name)) { ret = _protocols[idx].number; break; } } } else { ret = atoi(buf); } /* 255 / 'others' excluded from valid IP protocols */ if ((ret >= 0) && (ret < (PROTOS_TABLE_ENTRIES - 1))) { pt->table[ret] = TRUE; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] invalid protocol specified.\n", config.name, config.type, filename, rows); } rows++; } } fclose(file); stat(filename, &st); pt->timestamp = st.st_mtime; } } /* filename check to not print nulls as load_networks() may not be secured inside an if statement */ if (filename) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, config.type, filename); } return; handle_error: if (pt->timestamp) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back the old Protocols Table.\n", config.name, config.type, filename); /* we update the timestamp to avoid loops */ stat(filename, &st); pt->timestamp = st.st_mtime; } else exit_gracefully(1); } void load_ports(char *filename, struct ports_table *pt) { FILE *file; char buf[8]; int ret, rows = 0, newline = TRUE; struct stat st; memset(&st, 0, sizeof(st)); if (filename) { if ((file = fopen(filename,"r")) == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); goto handle_error; } else { memset(pt, 0, sizeof(struct ports_table)); while (!feof(file)) { if (fgets(buf, 8, file)) { if (strchr(buf, '\n')) { if (!newline) { newline = TRUE; continue; } } else { if (!newline) continue; newline = FALSE; } trim_spaces(buf); if (!strlen(buf) || (buf[0] == '!')) continue; ret = atoi(buf); if ((ret > 0) && (ret < PORTS_TABLE_ENTRIES)) pt->table[ret] = TRUE; else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] invalid port specified.\n", config.name, config.type, filename, rows); } } fclose(file); stat(filename, &st); pt->timestamp = st.st_mtime; } } /* filename check to not print nulls as load_networks() may not be secured inside an if statement */ if (filename) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, config.type, filename); } return; handle_error: if (pt->timestamp) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back the old Ports Table.\n", config.name, config.type, filename); /* we update the timestamp to avoid loops */ stat(filename, &st); pt->timestamp = st.st_mtime; } else exit_gracefully(1); } void load_tos(char *filename, struct protos_table *tost) { load_protos(filename, tost); } pmacct-1.7.8/src/pmacctd.c0000644000175000017500000013737414354105275014377 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "pmacct-dlt.h" #include "pretag_handlers.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_frag.h" #include "ip_flow.h" #include "net_aggr.h" #include "thread_pool.h" #include "bgp/bgp.h" #include "isis/isis.h" #include "bmp/bmp.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #include "ndpi/ndpi_util.h" #endif #include "jhash.h" /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", PMACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -i interface ] [ -c primitive [ , ... ] ] [ -P plugin [ , ... ] ] [ filter ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -a \tPrint list of supported aggregation primitives\n"); printf(" -c \tAggregation method, see full list of primitives with -a (DEFAULT: src_host)\n"); printf(" -D \tDaemonize\n"); printf(" -N \tDisable promiscuous mode\n"); printf(" -z \tAllow to run with non root privileges (ie. setcap in use)\n"); printf(" -n \tPath to a file containing networks and/or ASNs definitions\n"); printf(" -t \tPath to a file containing ports definitions\n"); printf(" -P \t[ memory | print | mysql | pgsql | sqlite3 | amqp | kafka | nfprobe | sfprobe ] \n\tActivate plugin\n"); printf(" -d \tEnable debug\n"); printf(" -i \tListen on the specified interface\n"); printf(" -I \tRead packets from the specified savefile\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -w \tWait for the listening interface to become available\n"); printf(" -Z \tReading from a savefile, sleep the given amount of seconds at startup and between replays\n"); printf(" -W \tReading from a savefile, don't exit but sleep when finished\n"); printf(" -Y \tReading from a savefile, replay the number of times specified\n"); printf(" -R \tRenormalize sampled data\n"); printf(" -L \tSet snapshot length\n"); printf(" -u \tLeave IP protocols in numerical format\n"); printf("\nMemory plugin (-P memory) options:\n"); printf(" -p \tSocket for client-server communication (DEFAULT: /tmp/collect.pipe)\n"); printf(" -b \tNumber of buckets\n"); printf(" -m \tNumber of memory pools\n"); printf(" -s \tMemory pool size\n"); printf("\nPrint plugin (-P print) plugin options:\n"); printf(" -r \tRefresh time (in seconds)\n"); printf(" -O \t[ formatted | csv | json | avro ] \n\tOutput format\n"); printf(" -o \tPath to output file\n"); printf(" -M \tPrint event init/close marker messages\n"); printf(" -A \tAppend output (applies to -o)\n"); printf(" -E \tCSV format separator (applies to -O csv, DEFAULT: ',')\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } void pm_pcap_device_copy_all(struct pm_pcap_devices *dst, struct pm_pcap_devices *src) { memcpy(dst, src, sizeof(struct pm_pcap_devices)); } void pm_pcap_device_copy_entry(struct pm_pcap_devices *dst, struct pm_pcap_devices *src, int src_idx) { memcpy(&dst->list[dst->num], &src->list[src_idx], sizeof(struct pm_pcap_device)); dst->num++; } int pm_pcap_device_getindex_by_ifname_direction(struct pm_pcap_devices *map, char *ifname, int direction) { int loc_idx; for (loc_idx = 0; loc_idx < map->num; loc_idx++) { if (strlen(map->list[loc_idx].str) == strlen(ifname) && !strncmp(map->list[loc_idx].str, ifname, strlen(ifname)) && direction == map->list[loc_idx].pcap_if->direction) { return loc_idx; } } return ERR; } pcap_t *pm_pcap_open(const char *dev_ptr, int snaplen, int promisc, int to_ms, int protocol, int direction, char *errbuf) { pcap_t *p; int ret; p = pcap_create(dev_ptr, errbuf); if (p == NULL) return NULL; ret = pcap_set_snaplen(p, snaplen); if (ret < 0) goto err; ret = pcap_set_promisc(p, promisc); if (ret < 0) goto err; ret = pcap_set_timeout(p, to_ms); if (ret < 0) goto err; #ifdef PCAP_SET_PROTOCOL ret = pcap_set_protocol(p, protocol); if (ret < 0) goto err; #else if (protocol) { Log(LOG_WARNING, "WARN ( %s/core ): pcap_protocol specified but linked against a version of libpcap that does not support pcap_set_protocol().\n", config.name); } #endif ret = pcap_activate(p); if (ret < 0) goto err; #ifdef PCAP_SET_DIRECTION ret = pcap_setdirection(p, direction); if (ret < 0) goto err; #endif return p; err: if (ret == PCAP_ERROR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev_ptr, pcap_geterr(p)); } else if (ret == PCAP_ERROR_NO_SUCH_DEVICE || ret == PCAP_ERROR_PERM_DENIED || ret == PCAP_ERROR_PROMISC_PERM_DENIED) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", dev_ptr, pcap_statustostr(ret), pcap_geterr(p)); } else { snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev_ptr, pcap_statustostr(ret)); } pcap_close(p); return NULL; } int pm_pcap_add_interface(struct pm_pcap_device *dev_ptr, char *ifname, struct pm_pcap_interface *pm_pcap_if_entry, int psize) { /* pcap library stuff */ char errbuf[PCAP_ERRBUF_SIZE]; int ret = SUCCESS, attempts = FALSE, index; int direction; if (pm_pcap_if_entry && pm_pcap_if_entry->direction) direction = pm_pcap_if_entry->direction; else direction = config.pcap_direction; throttle_startup: if (attempts < PCAP_MAX_ATTEMPTS) { if ((dev_ptr->dev_desc = pm_pcap_open(ifname, psize, config.promisc, 1000, config.pcap_protocol, direction, errbuf)) == NULL) { if (!config.pcap_if_wait) { Log(LOG_ERR, "ERROR ( %s/core ): [%s] pm_pcap_open(): %s. Exiting.\n", config.name, ifname, errbuf); exit_gracefully(1); } else { sleep(PCAP_RETRY_PERIOD); /* XXX: User defined value? */ attempts++; goto throttle_startup; } } dev_ptr->active = TRUE; dev_ptr->pcap_if = pm_pcap_if_entry; strncpy(dev_ptr->str, ifname, (sizeof(dev_ptr->str) - 1)); if (config.pcap_ifindex == PCAP_IFINDEX_SYS) dev_ptr->id = if_nametoindex(dev_ptr->str); else if (config.pcap_ifindex == PCAP_IFINDEX_HASH) dev_ptr->id = jhash(dev_ptr->str, strlen(dev_ptr->str), 0); else if (config.pcap_ifindex == PCAP_IFINDEX_MAP) { if (config.pcap_interfaces_map) { dev_ptr->id = pm_pcap_interfaces_map_lookup_ifname(&pm_pcap_if_map, dev_ptr->str); } else { Log(LOG_ERR, "ERROR ( %s/core ): pcap_ifindex set to 'map' but no pcap_interface_map is defined. Exiting.\n", config.name); exit_gracefully(1); } } else dev_ptr->id = 0; dev_ptr->fd = pcap_fileno(dev_ptr->dev_desc); if (config.nfacctd_pipe_size) { #if defined (PCAP_TYPE_linux) || (PCAP_TYPE_snoop) socklen_t slen = sizeof(config.nfacctd_pipe_size); int x; Setsocksize(pcap_fileno(dev_ptr->dev_desc), SOL_SOCKET, SO_RCVBUF, &config.nfacctd_pipe_size, slen); getsockopt(pcap_fileno(dev_ptr->dev_desc), SOL_SOCKET, SO_RCVBUF, &x, &slen); Log(LOG_DEBUG, "DEBUG ( %s/core ): pmacctd_pipe_size: obtained=%d target=%d.\n", config.name, x, config.nfacctd_pipe_size); #endif } dev_ptr->link_type = pcap_datalink(dev_ptr->dev_desc); for (index = 0; _devices[index].link_type != -1; index++) { if (dev_ptr->link_type == _devices[index].link_type) dev_ptr->data = &_devices[index]; } pm_pcap_check(dev_ptr); pm_pcap_add_filter(dev_ptr); } else { Log(LOG_WARNING, "WARN ( %s/core ): [%s] pm_pcap_open(): giving up after too many attempts.\n", config.name, ifname); ret = ERR; } return ret; } void pm_pcap_check(struct pm_pcap_device *dev_ptr) { struct plugins_list_entry *list; /* we need to solve some link constraints */ if (dev_ptr->data == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): data link not supported: %d\n", config.name, dev_ptr->link_type); exit_gracefully(1); } else { Log(LOG_INFO, "INFO ( %s/core ): [%s,%u] link type is: %d\n", config.name, dev_ptr->str, dev_ptr->id, dev_ptr->link_type); } if (dev_ptr->link_type != DLT_EN10MB && dev_ptr->link_type != DLT_IEEE802 && dev_ptr->link_type != DLT_LINUX_SLL) { list = plugins_list; while (list) { if (list->cfg.what_to_count & COUNT_SRC_MAC) { Log(LOG_WARNING, "WARN ( %s/core ): 'src_mac' aggregation not available for link type: %d\n", config.name, dev_ptr->link_type); list->cfg.what_to_count ^= COUNT_SRC_MAC; } if (list->cfg.what_to_count & COUNT_DST_MAC) { Log(LOG_WARNING, "WARN ( %s/core ): 'dst_mac' aggregation not available for link type: %d\n", config.name, dev_ptr->link_type); list->cfg.what_to_count ^= COUNT_DST_MAC; } if (list->cfg.what_to_count & COUNT_VLAN) { Log(LOG_WARNING, "WARN ( %s/core ): 'vlan' aggregation not available for link type: %d\n", config.name, dev_ptr->link_type); list->cfg.what_to_count ^= COUNT_VLAN; } list = list->next; } } } int main(int argc,char **argv, char **envp) { /* pcap library stuff */ struct pcap_pkthdr pkt_hdr; const u_char *pkt_body; pcap_if_t *pm_pcap_ifs = NULL; int index, index_rr = 0, logf, ret; int pm_pcap_savefile_round = 0; struct plugins_list_entry *list; struct plugin_requests req; char config_file[SRVBUFLEN]; int psize = DEFAULT_SNAPLEN; struct id_table bpas_table; struct id_table blp_table; struct id_table bmed_table; struct id_table biss_table; struct id_table bta_table; struct pm_pcap_device *dev_ptr; struct pm_pcap_callback_data cb_data; /* select() stuff */ fd_set read_descs, bkp_read_descs; int select_fd, bkp_select_fd; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; struct sockaddr_storage client; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); compute_once(); /* a bunch of default definitions */ reload_map = FALSE; reload_map_pmacctd = FALSE; print_stats = FALSE; reload_geoipv2_file = FALSE; bpas_map_allocated = FALSE; blp_map_allocated = FALSE; bmed_map_allocated = FALSE; biss_map_allocated = FALSE; bta_map_caching = FALSE; sampling_map_caching = FALSE; custom_primitives_allocated = FALSE; find_id_func = PM_find_id; plugins_list = NULL; errflag = 0; memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(&failed_plugins, 0, sizeof(failed_plugins)); memset(&req, 0, sizeof(req)); memset(dummy_tlhdr, 0, sizeof(dummy_tlhdr)); memset(sll_mac, 0, sizeof(sll_mac)); memset(&bpas_table, 0, sizeof(bpas_table)); memset(&blp_table, 0, sizeof(blp_table)); memset(&bmed_table, 0, sizeof(bmed_table)); memset(&biss_table, 0, sizeof(biss_table)); memset(&bta_table, 0, sizeof(bta_table)); memset(&client, 0, sizeof(client)); memset(&cb_data, 0, sizeof(cb_data)); memset(&tunnel_registry, 0, sizeof(tunnel_registry)); memset(&reload_map_tstamp, 0, sizeof(reload_map_tstamp)); memset(&device, 0, sizeof(device)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); pm_pcap_device_initialize(&devices); pm_pcap_device_initialize(&bkp_devices); log_notifications_init(&log_notifications); config.acct_type = ACCT_PM; config.progname = pmacctd_globstr; rows = 0; /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_PMACCTD)) != -1)) { if (!cfg_cmdline[rows]) cfg_cmdline[rows] = malloc(SRVBUFLEN); memset(cfg_cmdline[rows], 0, SRVBUFLEN); switch (cp) { case 'P': strlcpy(cfg_cmdline[rows], "plugins: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'z': strlcpy(cfg_cmdline[rows], "pmacctd_nonroot: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'n': strlcpy(cfg_cmdline[rows], "networks_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 't': strlcpy(cfg_cmdline[rows], "ports_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "print_output: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "print_output_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'M': strlcpy(cfg_cmdline[rows], "print_markers: true", SRVBUFLEN); rows++; break; case 'A': strlcpy(cfg_cmdline[rows], "print_output_file_append: true", SRVBUFLEN); rows++; break; case 'E': strlcpy(cfg_cmdline[rows], "print_output_separator: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'u': strlcpy(cfg_cmdline[rows], "print_num_protos: true", SRVBUFLEN); rows++; break; case 'N': strlcpy(cfg_cmdline[rows], "promisc: false", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); free(cfg_cmdline[rows]); cfg_cmdline[rows] = NULL; break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'c': strlcpy(cfg_cmdline[rows], "aggregate: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'b': strlcpy(cfg_cmdline[rows], "imt_buckets: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'm': strlcpy(cfg_cmdline[rows], "imt_mem_pools_number: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'p': strlcpy(cfg_cmdline[rows], "imt_path: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'r': strlcpy(cfg_cmdline[rows], "sql_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 's': strlcpy(cfg_cmdline[rows], "imt_mem_pools_size: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'i': strlcpy(cfg_cmdline[rows], "pcap_interface: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'I': strlcpy(cfg_cmdline[rows], "pcap_savefile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'w': strlcpy(cfg_cmdline[rows], "pcap_interface_wait: true", SRVBUFLEN); rows++; break; case 'W': strlcpy(cfg_cmdline[rows], "pcap_savefile_wait: true", SRVBUFLEN); rows++; break; case 'Z': strlcpy(cfg_cmdline[rows], "pcap_savefile_delay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Y': strlcpy(cfg_cmdline[rows], "pcap_savefile_replay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'L': strlcpy(cfg_cmdline[rows], "snaplen: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'R': strlcpy(cfg_cmdline[rows], "sfacctd_renormalize: true", SRVBUFLEN); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, PMACCTD_USAGE_HEADER); exit(0); break; case 'a': print_primitives(config.acct_type, PMACCTD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } /* XXX: glue; i'm conscious it's a dirty solution from an engineering viewpoint; someday later i'll fix this */ list = plugins_list; while(list) { list->cfg.acct_type = ACCT_PM; list->cfg.progname = pmacctd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); /* Let's check whether we need superuser privileges */ if (config.snaplen) psize = config.snaplen; else config.snaplen = psize; if (!config.pcap_savefile) { if (getuid() != 0 && !config.pmacctd_nonroot) { printf("%s %s (%s)\n\n", PMACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("ERROR ( %s/core ): You need superuser privileges to run this command.\nExiting ...\n\n", config.name); exit_gracefully(1); } } initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); list = plugins_list; while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { list = plugins_list; while (list) { if (!strcmp(list->type.string, "print") && !list->cfg.print_output_file) printf("INFO ( %s/%s ): Daemonizing. Bye bye screen.\n", list->name, list->type.string); list = list->next; } if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, PMACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); /* Enforcing policies over aggregation methods */ list = plugins_list; while (list) { if (list->type.id != PLUGIN_ID_CORE) { /* applies to all plugins */ plugin_pipe_check(&list->cfg); if (list->cfg.sampling_rate && config.ext_sampling_rate) { Log(LOG_ERR, "ERROR ( %s/core ): Internal packet sampling and external packet sampling are mutual exclusive.\n", config.name); exit_gracefully(1); } /* applies to specific plugins */ if (list->type.id == PLUGIN_ID_TEE) { Log(LOG_ERR, "ERROR ( %s/core ): 'tee' plugin not supported in 'pmacctd'.\n", config.name); exit_gracefully(1); } else if (list->type.id == PLUGIN_ID_NFPROBE) { /* If we already renormalizing an external sampling rate, we cancel the sampling information from the probe plugin */ if (config.sfacctd_renormalize && (list->cfg.ext_sampling_rate || list->cfg.sampling_rate)) { list->cfg.ext_sampling_rate = 0; list->cfg.sampling_rate = 0; } config.handle_fragments = TRUE; list->cfg.nfprobe_what_to_count = list->cfg.what_to_count; list->cfg.nfprobe_what_to_count_2 = list->cfg.what_to_count_2; list->cfg.what_to_count = 0; list->cfg.what_to_count_2 = 0; #if defined (HAVE_L2) if (list->cfg.nfprobe_version == 9 || list->cfg.nfprobe_version == 10) { list->cfg.what_to_count |= COUNT_SRC_MAC; list->cfg.what_to_count |= COUNT_DST_MAC; list->cfg.what_to_count |= COUNT_VLAN; } #endif list->cfg.what_to_count |= COUNT_SRC_HOST; list->cfg.what_to_count |= COUNT_DST_HOST; if (list->cfg.networks_file || list->cfg.networks_mask || list->cfg.nfacctd_net) { list->cfg.what_to_count |= COUNT_SRC_NMASK; list->cfg.what_to_count |= COUNT_DST_NMASK; } list->cfg.what_to_count |= COUNT_SRC_PORT; list->cfg.what_to_count |= COUNT_DST_PORT; list->cfg.what_to_count |= COUNT_IP_TOS; list->cfg.what_to_count |= COUNT_IP_PROTO; if (list->cfg.networks_file || ((list->cfg.bgp_daemon || list->cfg.bmp_daemon) && list->cfg.nfacctd_as == NF_AS_BGP)) { list->cfg.what_to_count |= COUNT_SRC_AS; list->cfg.what_to_count |= COUNT_DST_AS; list->cfg.what_to_count |= COUNT_PEER_DST_IP; } if (list->cfg.nfprobe_version == 9 || list->cfg.nfprobe_version == 10) { if (list->cfg.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS) list->cfg.what_to_count_2 |= COUNT_NDPI_CLASS; if (list->cfg.nfprobe_what_to_count_2 & COUNT_MPLS_LABEL_TOP) list->cfg.what_to_count_2 |= COUNT_MPLS_LABEL_TOP; } if (list->cfg.pre_tag_map) { list->cfg.what_to_count |= COUNT_TAG; list->cfg.what_to_count |= COUNT_TAG2; list->cfg.what_to_count_2 |= COUNT_LABEL; } list->cfg.what_to_count |= COUNT_IN_IFACE; list->cfg.what_to_count |= COUNT_OUT_IFACE; if ((list->cfg.what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_LOCAL_PREF|COUNT_MED|COUNT_AS_PATH| COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS|COUNT_PEER_SRC_IP|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF| COUNT_MPLS_VPN_RD)) || (list->cfg.what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM|COUNT_SRC_ROA|COUNT_DST_ROA))) { Log(LOG_ERR, "ERROR ( %s/core ): 'src_as', 'dst_as' and 'peer_dst_ip' are currently the only BGP-related primitives supported within the 'nfprobe' plugin.\n", config.name); exit_gracefully(1); } list->cfg.what_to_count |= COUNT_COUNTERS; if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; list->cfg.data_type = PIPE_TYPE_METADATA; list->cfg.data_type |= PIPE_TYPE_EXTRAS; if (list->cfg.what_to_count & (COUNT_PEER_DST_IP)) list->cfg.data_type |= PIPE_TYPE_BGP; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_LABEL)) list->cfg.data_type |= PIPE_TYPE_VLEN; } else if (list->type.id == PLUGIN_ID_SFPROBE) { /* If we already renormalizing an external sampling rate, we cancel the sampling information from the probe plugin */ if (config.sfacctd_renormalize && (list->cfg.ext_sampling_rate || list->cfg.sampling_rate)) { list->cfg.ext_sampling_rate = 0; list->cfg.sampling_rate = 0; } if (psize < 128) psize = config.snaplen = 128; /* SFL_DEFAULT_HEADER_SIZE */ list->cfg.what_to_count = COUNT_PAYLOAD; list->cfg.what_to_count_2 = 0; #if defined (WITH_NDPI) if (list->cfg.ndpi_num_roots) list->cfg.what_to_count_2 |= COUNT_NDPI_CLASS; #endif if (list->cfg.networks_file || ((list->cfg.bgp_daemon || list->cfg.bmp_daemon) && list->cfg.nfacctd_as == NF_AS_BGP)) { list->cfg.what_to_count |= COUNT_SRC_AS; list->cfg.what_to_count |= COUNT_DST_AS; list->cfg.what_to_count |= COUNT_PEER_DST_IP; } if (list->cfg.networks_file || list->cfg.networks_mask || list->cfg.nfacctd_net) { list->cfg.what_to_count |= COUNT_SRC_NMASK; list->cfg.what_to_count |= COUNT_DST_NMASK; } if (list->cfg.pre_tag_map) { list->cfg.what_to_count |= COUNT_TAG; list->cfg.what_to_count |= COUNT_TAG2; } if ((list->cfg.what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_LOCAL_PREF|COUNT_MED|COUNT_AS_PATH| COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS|COUNT_PEER_SRC_IP|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF| COUNT_MPLS_VPN_RD)) || (list->cfg.what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM|COUNT_SRC_ROA|COUNT_DST_ROA))) { Log(LOG_ERR, "ERROR ( %s/core ): 'src_as', 'dst_as' and 'peer_dst_ip' are currently the only BGP-related primitives supported within the 'sfprobe' plugin.\n", config.name); exit_gracefully(1); } #if defined (HAVE_L2) list->cfg.what_to_count |= COUNT_VLAN; list->cfg.what_to_count |= COUNT_COS; #endif if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; list->cfg.data_type = PIPE_TYPE_PAYLOAD; } else { if (list->cfg.what_to_count_2 & (COUNT_POST_NAT_SRC_HOST|COUNT_POST_NAT_DST_HOST| COUNT_POST_NAT_SRC_PORT|COUNT_POST_NAT_DST_PORT|COUNT_NAT_EVENT| COUNT_TIMESTAMP_START|COUNT_TIMESTAMP_END|COUNT_TIMESTAMP_ARRIVAL| COUNT_EXPORT_PROTO_TIME|COUNT_FWD_STATUS|COUNT_FW_EVENT)) list->cfg.data_type |= PIPE_TYPE_NAT; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP|COUNT_MPLS_LABEL_BOTTOM)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_TUNNEL_SRC_MAC|COUNT_TUNNEL_DST_MAC| COUNT_TUNNEL_SRC_HOST|COUNT_TUNNEL_DST_HOST|COUNT_TUNNEL_IP_PROTO| COUNT_TUNNEL_IP_TOS|COUNT_TUNNEL_SRC_PORT|COUNT_TUNNEL_DST_PORT| COUNT_VXLAN)) { list->cfg.data_type |= PIPE_TYPE_TUN; cb_data.has_tun_prims = TRUE; } if (list->cfg.what_to_count_2 & (COUNT_LABEL|COUNT_MPLS_LABEL_STACK)) list->cfg.data_type |= PIPE_TYPE_VLEN; evaluate_sums(&list->cfg.what_to_count, &list->cfg.what_to_count_2, list->name, list->type.string); if (list->cfg.what_to_count & (COUNT_SRC_PORT|COUNT_DST_PORT|COUNT_SUM_PORT|COUNT_TCPFLAGS)) config.handle_fragments = TRUE; if (list->cfg.what_to_count & COUNT_FLOWS) { config.handle_fragments = TRUE; config.handle_flows = TRUE; } if (!list->cfg.what_to_count && !list->cfg.what_to_count_2 && !list->cfg.cpptrs.num) { Log(LOG_WARNING, "WARN ( %s/%s ): defaulting to SRC HOST aggregation.\n", list->name, list->type.string); list->cfg.what_to_count |= COUNT_SRC_HOST; } if (list->cfg.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) { if (!list->cfg.networks_file && list->cfg.nfacctd_as != NF_AS_BGP) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation selected but NO 'networks_file' or 'pmacctd_as' are specified. Exiting...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; } if (list->cfg.what_to_count & (COUNT_SRC_NET|COUNT_DST_NET|COUNT_SUM_NET|COUNT_SRC_NMASK|COUNT_DST_NMASK|COUNT_PEER_DST_IP)) { if (!list->cfg.nfacctd_net) { if (list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; if (list->cfg.networks_mask) list->cfg.nfacctd_net |= NF_NET_STATIC; if (!list->cfg.nfacctd_net) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'pmacctd_net', 'networks_file', 'networks_mask' is specified. Exiting ...\n\n", list->name, list->type.string); exit_gracefully(1); } } else { if ((list->cfg.nfacctd_net == NF_NET_NEW && !list->cfg.networks_file) || (list->cfg.nfacctd_net == NF_NET_STATIC && !list->cfg.networks_mask) || (list->cfg.nfacctd_net == NF_NET_BGP && !list->cfg.bgp_daemon && !list->cfg.bmp_daemon) || (list->cfg.nfacctd_net == NF_NET_IGP && !list->cfg.nfacctd_isis) || (list->cfg.nfacctd_net == NF_NET_KEEP)) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'bgp_daemon', 'bmp_daemon', 'isis_daemon', 'networks_file', 'networks_mask' is specified. Exiting ...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; } } list->cfg.type_id = list->type.id; bgp_config_checks(&list->cfg); list->cfg.what_to_count |= COUNT_COUNTERS; list->cfg.data_type |= PIPE_TYPE_METADATA; } /* applies to all plugins */ if ((list->cfg.what_to_count_2 & COUNT_NDPI_CLASS) || (list->cfg.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS)) { config.handle_fragments = TRUE; config.classifier_ndpi = TRUE; } } list = list->next; } /* plugins glue: creation (since 094) */ #if defined (WITH_NDPI) if (config.classifier_ndpi) { config.handle_fragments = TRUE; pm_ndpi_wfl = pm_ndpi_workflow_init(); pm_ndpi_export_proto_to_class(pm_ndpi_wfl); } else pm_ndpi_wfl = NULL; #endif if (config.aggregate_primitives) { req.key_value_table = (void *) &custom_primitives_registry; load_id_file(MAP_CUSTOM_PRIMITIVES, config.aggregate_primitives, NULL, &req, &custom_primitives_allocated); } else memset(&custom_primitives_registry, 0, sizeof(custom_primitives_registry)); /* fixing per plugin custom primitives pointers, offsets and lengths */ list = plugins_list; while(list) { custom_primitives_reconcile(&list->cfg.cpptrs, &custom_primitives_registry); if (custom_primitives_vlen(&list->cfg.cpptrs)) list->cfg.data_type |= PIPE_TYPE_VLEN; list = list->next; } if (config.handle_fragments) init_ip_fragment_handler(); if (config.handle_flows) init_ip_flow_handler(); load_networks(config.networks_file, &nt, &nc); if (config.pcap_interfaces_map) { pm_pcap_interfaces_map_initialize(&pm_pcap_if_map); pm_pcap_interfaces_map_initialize(&pm_bkp_pcap_if_map); pm_pcap_interfaces_map_load(&pm_pcap_if_map); } else { pm_pcap_if_map.list = NULL; pm_pcap_if_map.num = 0; } if (!config.pcap_direction) config.pcap_direction = PCAP_D_INOUT; /* If any device/savefile have been specified, choose a suitable device where to listen for traffic */ if (!config.pcap_if && !config.pcap_savefile && !config.pcap_interfaces_map) { char errbuf[PCAP_ERRBUF_SIZE]; Log(LOG_WARNING, "WARN ( %s/core ): Selecting a suitable devices.\n", config.name); ret = pcap_findalldevs(&pm_pcap_ifs, errbuf); if (ret == ERR || !pm_pcap_ifs) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to get interfaces list: %s. Exiting.\n", config.name, errbuf); exit_gracefully(1); } config.pcap_if = pm_pcap_ifs[0].name; Log(LOG_DEBUG, "DEBUG ( %s/core ): device is %s\n", config.name, config.pcap_if); } /* reading filter; if it exists, we'll take an action later */ if (!strlen(config_file)) config.clbuf = copy_argv(&argv[optind]); if ((config.pcap_if || config.pcap_interfaces_map) && config.pcap_savefile) { Log(LOG_ERR, "ERROR ( %s/core ): interface (-i), pcap_interfaces_map and pcap_savefile (-I) directives are mutually exclusive. Exiting.\n", config.name); exit_gracefully(1); } if (config.pcap_if && config.pcap_interfaces_map) { Log(LOG_ERR, "ERROR ( %s/core ): interface (-i) and pcap_interfaces_map directives are mutually exclusive. Exiting.\n", config.name); exit_gracefully(1); } bkp_select_fd = 0; FD_ZERO(&bkp_read_descs); if (config.pcap_if) { ret = pm_pcap_add_interface(&devices.list[0], config.pcap_if, NULL, psize); if (!ret) { cb_data.device = &devices.list[0]; devices.num = 1; load_plugin_filters(devices.list[0].link_type); } } else if (config.pcap_interfaces_map) { struct pm_pcap_interface *pm_pcap_if_entry; int pm_pcap_if_idx = 0; char *ifname; while ((ifname = pm_pcap_interfaces_map_getnext_ifname(&pm_pcap_if_map, &pm_pcap_if_idx))) { if (devices.num == PCAP_MAX_INTERFACES) { Log(LOG_ERR, "ERROR ( %s/core ): Maximum number of interfaces reached (%u). Exiting.\n", config.name, PCAP_MAX_INTERFACES); exit_gracefully(1); } pm_pcap_if_entry = pm_pcap_interfaces_map_getentry_by_idx(&pm_pcap_if_map, (pm_pcap_if_idx - 1)); ret = pm_pcap_add_interface(&devices.list[devices.num], ifname, pm_pcap_if_entry, psize); if (!ret) { if (bkp_select_fd <= devices.list[devices.num].fd) { bkp_select_fd = devices.list[devices.num].fd; bkp_select_fd++; } if (devices.list[devices.num].fd) FD_SET(devices.list[devices.num].fd, &bkp_read_descs); devices.num++; } } if (devices.num) { load_plugin_filters(devices.list[0].link_type); } if (!pm_pcap_if_idx) { Log(LOG_ERR, "ERROR ( %s/core ): No interfaces selected. Exiting.\n", config.name); exit_gracefully(1); } } else if (config.pcap_savefile) { open_pcap_savefile(&devices.list[0], config.pcap_savefile); pm_pcap_check(&devices.list[0]); pm_pcap_add_filter(&devices.list[0]); cb_data.device = &devices.list[0]; devices.num = 1; pm_pcap_savefile_round = 1; } load_plugins(&req); /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ sighandler_action.sa_handler = startup_handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = push_stats; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); if (config.bgp_daemon && config.bmp_daemon) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_daemon and bmp_daemon are currently mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } /* starting the ISIS threa */ if (config.nfacctd_isis) { req.bpf_filter = TRUE; nfacctd_isis_wrapper(); /* Let's give the ISIS thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } /* starting the BGP thread */ if (config.bgp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_stdcomm_pattern_to_asn && config.bgp_daemon_lrgcomm_pattern_to_asn) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_stdcomm_pattern_to_asn and bgp_lrgcomm_pattern_to_asn are mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } load_comm_patterns(&config.bgp_daemon_stdcomm_pattern, &config.bgp_daemon_extcomm_pattern, &config.bgp_daemon_lrgcomm_pattern, &config.bgp_daemon_stdcomm_pattern_to_asn, &config.bgp_daemon_lrgcomm_pattern_to_asn); if (config.bgp_daemon_peer_as_src_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_peer_as_src_map) { load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); cb_data.bpas_table = (u_char *) &bpas_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_peer_as_src_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.bpas_table = NULL; if (config.bgp_daemon_src_local_pref_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_local_pref_map) { load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); cb_data.blp_table = (u_char *) &blp_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_local_pref_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.blp_table = NULL; if (config.bgp_daemon_src_med_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_med_map) { load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); cb_data.bmed_table = (u_char *) &bmed_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_med_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.bmed_table = NULL; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); cb_data.bta_table = (u_char *) &bta_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): 'bgp_daemon' configured but no 'bgp_agent_map' has been specified. Exiting.\n", config.name); exit_gracefully(1); } /* Limiting BGP peers to only two: one would suffice in pmacctd but in case maps are reloadable (ie. bta), it could be handy to keep a backup feed in memory */ config.bgp_daemon_max_peers = 2; cb_data.f_agent = (u_char *) &client; bgp_daemon_wrapper(); /* Let's give the BGP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } /* starting the BMP thread */ if (config.bmp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); cb_data.bta_table = (u_char *) &bta_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): 'bmp_daemon' configured but no 'bgp_agent_map' has been specified. Exiting.\n", config.name); exit_gracefully(1); } /* Limiting BGP peers to only two: one would suffice in pmacctd but in case maps are reloadable (ie. bta), it could be handy to keep a backup feed in memory */ config.bgp_daemon_max_peers = 2; bmp_daemon_wrapper(); /* Let's give the BMP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } #if defined WITH_GEOIP if (config.geoip_ipv4_file || config.geoip_ipv6_file) { req.bpf_filter = TRUE; } #endif #if defined WITH_GEOIPV2 if (config.geoipv2_file) { req.bpf_filter = TRUE; } #endif if (config.nfacctd_flow_to_rd_map) { Log(LOG_ERR, "ERROR ( %s/core ): 'flow_to_rd_map' is not supported by this daemon. Exiting.\n", config.name); exit_gracefully(1); } /* Init tunnel handlers */ tunnel_registry_init(); /* plugins glue: creation (until 093) */ evaluate_packet_handlers(); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); /* signals to be handled only by the core process; we set proper handlers after plugin creation */ sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); kill(getpid(), SIGCHLD); /* When reading packets from a savefile, things are lightning fast; we will sit here just few seconds, thus allowing plugins to complete their startup operations */ if (config.pcap_savefile) { if (!config.pcap_sf_delay) { Log(LOG_INFO, "INFO ( %s/core ): PCAP capture file, sleeping for 2 seconds\n", config.name); sleep(2); } else sleep(config.pcap_sf_delay); } #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif sigemptyset(&cb_data.sig.set); sigaddset(&cb_data.sig.set, SIGCHLD); sigaddset(&cb_data.sig.set, SIGHUP); sigaddset(&cb_data.sig.set, SIGUSR1); sigaddset(&cb_data.sig.set, SIGUSR2); sigaddset(&cb_data.sig.set, SIGTERM); if (config.daemon) { sigaddset(&cb_data.sig.set, SIGINT); } cb_data.sig.is_set = TRUE; /* Main loop (for the case of a single interface): if pcap_loop() exits maybe an error occurred; we will try closing and reopening again our listening device */ if (!config.pcap_interfaces_map) { for (;;) { if (!devices.list[0].active) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] has become unavailable; throttling ...\n", config.name, config.pcap_if); ret = pm_pcap_add_interface(&devices.list[0], config.pcap_if, NULL, psize); if (!ret) { cb_data.device = &devices.list[0]; devices.num = 1; load_plugin_filters(devices.list[0].link_type); } } read_packet: pcap_loop(devices.list[0].dev_desc, -1, pm_pcap_cb, (u_char *) &cb_data); pcap_close(devices.list[0].dev_desc); if (config.pcap_savefile) { if (config.pcap_sf_replay < 0 || (config.pcap_sf_replay > 0 && pm_pcap_savefile_round < config.pcap_sf_replay)) { pm_pcap_savefile_round++; open_pcap_savefile(&devices.list[0], config.pcap_savefile); if (config.pcap_sf_delay) sleep(config.pcap_sf_delay); goto read_packet; } if (config.pcap_sf_wait) { fill_pipe_buffer(); Log(LOG_INFO, "INFO ( %s/core ): finished reading PCAP capture file\n", config.name); wait(NULL); } stop_all_childs(); } devices.list[0].active = FALSE; } } else { for (;;) { select_fd = bkp_select_fd; memcpy(&read_descs, &bkp_read_descs, sizeof(bkp_read_descs)); select(select_fd, &read_descs, NULL, NULL, NULL); if (reload_map_pmacctd) { struct pm_pcap_interface *pm_pcap_if_entry; int pm_pcap_if_idx = 0; char *ifname; pm_pcap_interfaces_map_copy(&pm_bkp_pcap_if_map, &pm_pcap_if_map); pm_pcap_interfaces_map_destroy(&pm_pcap_if_map); pm_pcap_interfaces_map_load(&pm_pcap_if_map); pm_pcap_device_copy_all(&bkp_devices, &devices); pm_pcap_device_initialize(&devices); /* Add interfaces and re-build relevant structs */ while ((ifname = pm_pcap_interfaces_map_getnext_ifname(&pm_pcap_if_map, &pm_pcap_if_idx))) { if (!pm_pcap_interfaces_map_lookup_ifname(&pm_bkp_pcap_if_map, ifname)) { if (devices.num == PCAP_MAX_INTERFACES) { Log(LOG_WARNING, "WARN ( %s/core ): Maximum number of interfaces reached (%u). Ignoring '%s'.\n", config.name, PCAP_MAX_INTERFACES, ifname); } else { pm_pcap_if_entry = pm_pcap_interfaces_map_getentry_by_idx(&pm_pcap_if_map, (pm_pcap_if_idx - 1)); if (!pm_pcap_add_interface(&devices.list[devices.num], ifname, pm_pcap_if_entry, psize)) { if (bkp_select_fd <= devices.list[devices.num].fd) { bkp_select_fd = devices.list[devices.num].fd; bkp_select_fd++; } if (devices.list[devices.num].fd && !FD_ISSET(devices.list[devices.num].fd, &bkp_read_descs)) { FD_SET(devices.list[devices.num].fd, &bkp_read_descs); } devices.num++; } } } else { int device_idx, direction; direction = pm_pcap_interfaces_map_get_direction(&pm_pcap_if_map, pm_pcap_if_idx); device_idx = pm_pcap_device_getindex_by_ifname_direction(&bkp_devices, ifname, direction); if (device_idx >= 0) { Log(LOG_INFO, "INFO ( %s/core ): [%s,%u] link type is: %d\n", config.name, bkp_devices.list[device_idx].str, bkp_devices.list[device_idx].id, bkp_devices.list[device_idx].link_type); pm_pcap_device_copy_entry(&devices, &bkp_devices, device_idx); } else Log(LOG_WARNING, "WARN ( %s/core ): Mayday. Interface '%s' went lost.\n", config.name, ifname); } } /* Remove unlisted interfaces */ pm_pcap_if_idx = 0; while ((ifname = pm_pcap_interfaces_map_getnext_ifname(&pm_bkp_pcap_if_map, &pm_pcap_if_idx))) { if (!pm_pcap_interfaces_map_lookup_ifname(&pm_pcap_if_map, ifname)) { int device_idx, direction; direction = pm_pcap_interfaces_map_get_direction(&pm_pcap_if_map, pm_pcap_if_idx); device_idx = pm_pcap_device_getindex_by_ifname_direction(&bkp_devices, ifname, direction); if (device_idx >= 0) { Log(LOG_INFO, "INFO ( %s/core ): [%s,%u] removed.\n", config.name, bkp_devices.list[device_idx].str, bkp_devices.list[device_idx].id); FD_CLR(bkp_devices.list[device_idx].fd, &bkp_read_descs); pcap_close(bkp_devices.list[device_idx].dev_desc); } else Log(LOG_WARNING, "WARN ( %s/core ): Mayday. Interface '%s' went lost (2).\n", config.name, ifname); } } if (devices.num) { load_plugin_filters(devices.list[0].link_type); } reload_map_pmacctd = FALSE; } for (dev_ptr = NULL, index = 0; index < devices.num; index++) { int loc_idx = (index + index_rr) % devices.num; if (devices.list[loc_idx].fd && FD_ISSET(devices.list[loc_idx].fd, &read_descs)) { dev_ptr = &devices.list[loc_idx]; index_rr = (index_rr + 1) % devices.num; break; } } if (dev_ptr) { pkt_body = pcap_next(dev_ptr->dev_desc, &pkt_hdr); if (pkt_body) { cb_data.device = dev_ptr; pm_pcap_cb((u_char *) &cb_data, &pkt_hdr, pkt_body); } } } } } pmacct-1.7.8/src/imt_plugin.h0000644000175000017500000001275214354105275015130 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef IMT_PLUGIN_H #define IMT_PLUGIN_H #include /* defines */ #define NUM_MEMORY_POOLS 16 #define MEMORY_POOL_SIZE 8192 #define MAX_HOSTS 32771 #define MAX_QUERIES 4096 /* Structures */ struct acc { struct pkt_primitives primitives; pm_counter_t bytes_counter; pm_counter_t packet_counter; pm_counter_t flow_counter; u_int8_t flow_type; u_int8_t tcp_flags; u_int8_t tunnel_tcp_flags; unsigned int signature; u_int8_t reset_flag; struct timeval rstamp; /* classifiers: reset timestamp */ struct pkt_bgp_primitives *pbgp; struct cache_legacy_bgp_primitives *clbgp; struct pkt_nat_primitives *pnat; struct pkt_mpls_primitives *pmpls; struct pkt_tunnel_primitives *ptun; u_char *pcust; struct pkt_vlen_hdr_primitives *pvlen; struct acc *next; }; struct bucket_desc { unsigned int num; unsigned short int howmany; }; struct memory_pool_desc { int id; unsigned char *base_ptr; unsigned char *ptr; int space_left; int len; struct memory_pool_desc *next; }; struct query_header { int type; /* type of query */ pm_cfgreg_t what_to_count; /* aggregation */ pm_cfgreg_t what_to_count_2; /* aggregation */ unsigned int num; /* number of queries */ unsigned int ip_sz; /* IP addresses size (in bytes) */ unsigned int cnt_sz; /* counters size (in bytes) */ struct extra_primitives extras; /* offsets for non-standard aggregation primitives structures */ int datasize; /* total length of aggregation primitives structures */ char passwd[12]; /* OBSOLETED: password */ }; struct query_entry { pm_cfgreg_t what_to_count; /* aggregation */ pm_cfgreg_t what_to_count_2; /* aggregation */ struct pkt_primitives data; /* actual data */ struct pkt_bgp_primitives pbgp; /* extended BGP data */ struct pkt_legacy_bgp_primitives plbgp; /* extended BGP data */ struct pkt_nat_primitives pnat; /* extended NAT + timestamp data */ struct pkt_mpls_primitives pmpls; /* extended MPLS data */ struct pkt_tunnel_primitives ptun; /* extended tunnel data */ u_char *pcust; /* custom-defined data */ struct pkt_vlen_hdr_primitives *pvlen; /* variable-length data */ }; struct reply_buffer { unsigned char buf[LARGEBUFLEN]; unsigned char *ptr; int len; int packed; }; struct stripped_class { pm_class_t id; char protocol[MAX_PROTOCOL_LEN]; #if defined (WITH_NDPI) ndpi_protocol_category_t category; #endif }; struct imt_custom_primitive_entry { /* compiled from map */ char name[MAX_CUSTOM_PRIMITIVE_NAMELEN]; u_int16_t field_type; u_int16_t len; u_int8_t semantics; /* compiled internally */ u_int16_t off; pm_cfgreg_t type; }; struct imt_custom_primitives { struct imt_custom_primitive_entry primitive[MAX_CUSTOM_PRIMITIVES]; int len; int num; }; /* prototypes */ extern void insert_accounting_structure(struct primitives_ptrs *); extern struct acc *search_accounting_structure(struct primitives_ptrs *); extern int compare_accounting_structure(struct acc *, struct primitives_ptrs *); extern void init_memory_pool_table(); extern void clear_memory_pool_table(); extern struct memory_pool_desc *request_memory_pool(int); extern void set_reset_flag(struct acc *); extern void reset_counters(struct acc *); extern int build_query_server(char *); extern void process_query_data(int, unsigned char *, int, struct extra_primitives *, int, int); extern void mask_elem(struct pkt_primitives *, struct pkt_bgp_primitives *, struct pkt_legacy_bgp_primitives *, struct pkt_nat_primitives *, struct pkt_mpls_primitives *, struct pkt_tunnel_primitives *, struct acc *, u_int64_t, u_int64_t, struct extra_primitives *); extern void enQueue_elem(int, struct reply_buffer *, void *, int, int); extern void Accumulate_Counters(struct pkt_data *, struct acc *); extern int test_zero_elem(struct acc *); extern void sum_host_insert(struct primitives_ptrs *); extern void sum_port_insert(struct primitives_ptrs *); extern void sum_as_insert(struct primitives_ptrs *); #if defined HAVE_L2 extern void sum_mac_insert(struct primitives_ptrs *); #endif extern void exit_now(int); extern void free_extra_allocs(); /* global vars */ extern void (*imt_insert_func)(struct primitives_ptrs *); /* pointer to INSERT function */ extern unsigned char *mpd; /* memory pool descriptors table */ extern unsigned char *a; /* accounting in-memory table */ extern struct memory_pool_desc *current_pool; /* pointer to currently used memory pool */ extern struct acc **lru_elem_ptr; /* pointer to Last Recently Used (lru) element in a bucket */ extern int no_more_space; extern struct timeval cycle_stamp; /* timestamp for the current cycle */ extern struct timeval table_reset_stamp; /* global table reset timestamp */ #endif //IMT_PLUGIN_H pmacct-1.7.8/src/xflow_status.h0000644000175000017500000001236514354105275015523 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef XFLOW_STATUS_H #define XFLOW_STATUS_H /* defines */ #define XFLOW_RESET_BOUNDARY 50 #define XFLOW_STATUS_TABLE_SZ 9973 #define XFLOW_STATUS_TABLE_MAX_ENTRIES 100000 /* structures */ struct xflow_status_entry_counters { // XXX: change to 64 bit? u_int32_t good; u_int32_t jumps_f; u_int32_t jumps_b; u_int64_t total; u_int64_t bytes; }; struct xflow_status_entry_sampling { u_int32_t interface; /* sFlow/NetFlow v9: interface generating the sample */ u_int32_t sample_pool; /* sampling rate */ u_int32_t seqno; /* sFlow: flow samples sequence number */ u_int32_t sampler_id; /* NetFlow v9: flow sampler ID field */ struct xflow_status_entry_sampling *next; }; struct xflow_status_entry_class { pm_class_t class_id; /* NetFlow v9: classfier ID field */ pm_class_t class_int_id; /* NetFlow v9: internal classfier ID field */ char class_name[MAX_PROTOCOL_LEN]; /* NetFlow v9: classfier name field */ struct xflow_status_entry_class *next; }; struct xflow_status_map_cache { pm_id_t tag; pm_id_t tag2; s_uint16_t port; /* BGP port */ int ret; struct timeval stamp; }; struct xflow_status_entry { struct host_addr agent_addr; /* NetFlow/IPFIX: socket IP address sFlow: agentID IP address */ struct host_addr exp_addr; /* NetFlow/IPFIX: exporter IP address, ie. #130/#131 (host_addr struct) */ struct sockaddr exp_sa; /* NetFlow/IPFIX: exporter IP address, ie. #130/#131 (sockaddr struct) */ u_int32_t seqno; /* Sequence number */ u_int32_t aux1; /* Some more distinguishing fields: NetFlow v5: Engine Type + Engine ID NetFlow v9: Source ID IPFIX: ObservedDomainID sFlow v5: agentSubID */ u_int32_t aux2; /* Some more distinguishing (internal) flags */ u_int16_t inc; /* increment, NetFlow v5: required by flow sequence number */ u_int32_t peer_v4_idx; /* last known BGP peer index for ipv4 address family */ u_int32_t peer_v6_idx; /* last known BGP peer index for ipv6 address family */ struct xflow_status_map_cache bta_v4; /* last known bgp_agent_map IPv4 result */ struct xflow_status_map_cache bta_v6; /* last known bgp_agent_map IPv6 result */ struct xflow_status_map_cache st; /* last known sampling_map result */ struct xflow_status_entry_counters counters; struct xflow_status_entry_sampling *sampling; struct xflow_status_entry_class *class; cdada_map_t *in_rd_map; /* hash map for ingress vrf id -> mpls vpn rd lookup */ cdada_map_t *out_rd_map; /* hash map for egress vrf id -> mpls vpn rd lookup */ void *sf_cnt; /* struct (ab)used for sFlow counters logging */ #ifdef WITH_GNUTLS pm_dtls_peer_t dtls; #endif struct xflow_status_entry *next; }; typedef struct { u_int32_t entries; u_int32_t tot_bad_datagrams; u_int8_t memerr; u_int8_t smp_entry_status_table_memerr; u_int8_t class_entry_status_table_memerr; struct xflow_status_entry *t[XFLOW_STATUS_TABLE_SZ]; } xflow_status_table_t; /* prototypes */ extern u_int32_t hash_status_table(u_int32_t, struct sockaddr *, u_int32_t); extern struct xflow_status_entry *search_status_table(xflow_status_table_t *, struct sockaddr *, u_int32_t, u_int32_t, int, int); extern void update_good_status_table(struct xflow_status_entry *, u_int32_t); extern void update_bad_status_table(struct xflow_status_entry *); extern void print_status_table(xflow_status_table_t *, time_t, int); extern struct xflow_status_entry_sampling *search_smp_if_status_table(struct xflow_status_entry_sampling *, u_int32_t); extern struct xflow_status_entry_sampling *search_smp_id_status_table(struct xflow_status_entry_sampling *, u_int32_t, u_int8_t); extern struct xflow_status_entry_sampling *create_smp_entry_status_table(xflow_status_table_t *, struct xflow_status_entry *); extern struct xflow_status_entry_class *search_class_id_status_table(struct xflow_status_entry_class *, pm_class_t); extern struct xflow_status_entry_class *create_class_entry_status_table(xflow_status_table_t *, struct xflow_status_entry *); extern void set_vector_f_status(struct packet_ptrs_vector *); extern void set_vector_f_status_g(struct packet_ptrs_vector *); extern void update_status_table(struct xflow_status_entry *, u_int32_t, int); extern xflow_status_table_t xflow_status_table; #ifdef WITH_GNUTLS extern xflow_status_table_t dtls_status_table; #endif #endif // XFLOW_STATUS_H pmacct-1.7.8/src/zmq_common.c0000644000175000017500000005716314354105275015140 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "zmq_common.h" /* Global variables */ struct p_zmq_host nfacctd_zmq_host; struct p_zmq_host telemetry_zmq_host; /* Functions */ void p_zmq_set_address(struct p_zmq_host *zmq_host, char *address) { char proto[] = "://", tcp_proto[] = "tcp://", inproc_proto[] = "inproc://"; if (zmq_host && address) { if (!strstr(address, proto)) { snprintf(zmq_host->sock.str, sizeof(zmq_host->sock.str), "tcp://%s", address); } else { if (strstr(address, tcp_proto)) { snprintf(zmq_host->sock.str, sizeof(zmq_host->sock.str), "%s", address); } else if (strstr(address, inproc_proto)) { snprintf(zmq_host->sock_inproc.str, sizeof(zmq_host->sock_inproc.str), "%s", address); } else { Log(LOG_ERR, "ERROR ( %s ): p_zmq_set_address() unsupported protocol in '%s'.\nExiting.\n", zmq_host->log_id, address); exit_gracefully(1); } } } } void p_zmq_set_topic(struct p_zmq_host *zmq_host, u_int8_t topic) { if (zmq_host) zmq_host->topic = topic; } void p_zmq_set_retry_timeout(struct p_zmq_host *zmq_host, int tout) { int ret; if (zmq_host) { ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_RECONNECT_IVL, &tout, sizeof(tout)); if (ret != 0) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() RECONNECT_IVL failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } } } void p_zmq_set_username(struct p_zmq_host *zmq_host, char *username) { if (zmq_host) { if (strlen(username) >= sizeof(zmq_host->zap.username)) { Log(LOG_ERR, "ERROR ( %s ): p_zmq_set_username(): username '%s' too long (maximum %lu chars). Exiting.\n", zmq_host->log_id, username, (sizeof(zmq_host->zap.username) - 1)); exit_gracefully(1); } else strlcpy(zmq_host->zap.username, username, sizeof(zmq_host->zap.username)); } } void p_zmq_set_password(struct p_zmq_host *zmq_host, char *password) { if (zmq_host) { if (strlen(password) >= sizeof(zmq_host->zap.password)) { Log(LOG_ERR, "ERROR ( %s ): p_zmq_set_password(): password '%s' too long (maximum %lu chars). Exiting.\n", zmq_host->log_id, password, (sizeof(zmq_host->zap.password) - 1)); exit_gracefully(1); } else strlcpy(zmq_host->zap.password, password, sizeof(zmq_host->zap.password)); } } void p_zmq_set_random_username(struct p_zmq_host *zmq_host) { if (zmq_host) generate_random_string(zmq_host->zap.username, (sizeof(zmq_host->zap.username) - 1)); } void p_zmq_set_random_password(struct p_zmq_host *zmq_host) { if (zmq_host) generate_random_string(zmq_host->zap.password, (sizeof(zmq_host->zap.password) - 1)); } void p_zmq_set_hwm(struct p_zmq_host *zmq_host, int hwm) { if (zmq_host) zmq_host->hwm = hwm; } void p_zmq_set_log_id(struct p_zmq_host *zmq_host, char *log_id) { if (zmq_host) strlcpy(zmq_host->log_id, log_id, sizeof(zmq_host->log_id)); } char *p_zmq_get_address(struct p_zmq_host *zmq_host) { if (zmq_host) { if (strlen(zmq_host->sock.str)) return zmq_host->sock.str; else if (strlen(zmq_host->sock_inproc.str)) return zmq_host->sock_inproc.str; } return NULL; } u_int8_t p_zmq_get_topic(struct p_zmq_host *zmq_host) { if (zmq_host) return zmq_host->topic; return 0; } void *p_zmq_get_sock(struct p_zmq_host *zmq_host) { if (zmq_host) return zmq_host->sock.obj; return NULL; } int p_zmq_get_fd(struct p_zmq_host *zmq_host) { int fd = ERR; size_t len = sizeof(fd); if (zmq_host) { zmq_getsockopt(zmq_host->sock.obj, ZMQ_FD, &fd, &len); } return fd; } void p_zmq_init_push(struct p_zmq_host *zmq_host, char *address) { if (zmq_host) { memset(zmq_host, 0, sizeof(struct p_zmq_host)); p_zmq_set_address(zmq_host, address); } } void p_zmq_init_pub(struct p_zmq_host *zmq_host, char *address, u_int8_t topic) { if (zmq_host) { memset(zmq_host, 0, sizeof(struct p_zmq_host)); p_zmq_set_address(zmq_host, address); p_zmq_set_topic(zmq_host, topic); } } void p_zmq_plugin_pipe_init_core(struct p_zmq_host *zmq_host, u_int8_t plugin_id, char *username, char *password) { if (zmq_host) { p_zmq_init_pub(zmq_host, NULL, plugin_id); if (!username) p_zmq_set_random_username(zmq_host); else p_zmq_set_username(zmq_host, username); if (!password) p_zmq_set_random_password(zmq_host); else p_zmq_set_password(zmq_host, password); } } void p_zmq_init_sub(struct p_zmq_host *zmq_host) { p_zmq_plugin_pipe_init_plugin(zmq_host); } void p_zmq_init_pull(struct p_zmq_host *zmq_host) { p_zmq_plugin_pipe_init_plugin(zmq_host); } void p_zmq_plugin_pipe_init_plugin(struct p_zmq_host *zmq_host) { if (zmq_host) { /* if (zmq_host->sock.obj) { zmq_unbind(zmq_host->sock.obj, zmq_host->sock.str); zmq_close(zmq_host->sock.obj); } if (zmq_host->zap.sock.obj) zmq_close(zmq_host->zap.sock.obj); if (zmq_host->zap.thread) zmq_threadclose(zmq_host->zap.thread); if (zmq_host->ctx) { zmq_ctx_shutdown(zmq_host->ctx); zmq_ctx_term(zmq_host->ctx); zmq_host->ctx = NULL; } */ zmq_host->ctx = NULL; } } int p_zmq_plugin_pipe_set_profile(struct configuration *cfg, char *value) { if (!strcmp("micro", value)) { cfg->pipe_zmq_profile = PLUGIN_PIPE_ZMQ_MICRO; cfg->buffer_size = PLUGIN_PIPE_ZMQ_MICRO_SIZE; } else if (!strcmp("small", value)) { cfg->pipe_zmq_profile = PLUGIN_PIPE_ZMQ_SMALL; cfg->buffer_size = PLUGIN_PIPE_ZMQ_SMALL_SIZE; } else if (!strcmp("medium", value)) { cfg->pipe_zmq_profile = PLUGIN_PIPE_ZMQ_MEDIUM; cfg->buffer_size = PLUGIN_PIPE_ZMQ_MEDIUM_SIZE; } else if (!strcmp("large", value)) { cfg->pipe_zmq_profile = PLUGIN_PIPE_ZMQ_LARGE; cfg->buffer_size = PLUGIN_PIPE_ZMQ_LARGE_SIZE; } else if (!strcmp("xlarge", value)) { cfg->pipe_zmq_profile = PLUGIN_PIPE_ZMQ_XLARGE; cfg->buffer_size = PLUGIN_PIPE_ZMQ_XLARGE_SIZE; } else return ERR; return SUCCESS; } int p_zmq_bind(struct p_zmq_host *zmq_host) { int ret = 0, as_server = TRUE; size_t sock_strlen; if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_SERVER, &as_server, sizeof(int)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_PLAIN_SERVER failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } } if (strlen(zmq_host->sock_inproc.str)) { if (zmq_host->sock_inproc.obj_rx) { ret = zmq_bind(zmq_host->sock_inproc.obj_rx, zmq_host->sock_inproc.str); } else { ret = zmq_bind(zmq_host->sock_inproc.obj, zmq_host->sock_inproc.str); } } else if (strlen(zmq_host->sock.str)) { ret = zmq_bind(zmq_host->sock.obj, zmq_host->sock.str); } else { ret = zmq_bind(zmq_host->sock.obj, "tcp://127.0.0.1:*"); } if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_bind() failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } if (!strlen(zmq_host->sock.str) && !strlen(zmq_host->sock_inproc.str)) { sock_strlen = sizeof(zmq_host->sock.str); ret = zmq_getsockopt(zmq_host->sock.obj, ZMQ_LAST_ENDPOINT, zmq_host->sock.str, &sock_strlen); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_getsockopt() ZMQ_LAST_ENDPOINT failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } } return ret; } int p_zmq_connect(struct p_zmq_host *zmq_host) { int ret = 0; if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_USERNAME, zmq_host->zap.username, strlen(zmq_host->zap.username)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_PLAIN_USERNAME failed: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_PASSWORD, zmq_host->zap.password, strlen(zmq_host->zap.password)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_PLAIN_PASSWORD failed: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } } if (strlen(zmq_host->sock.str)) { ret = zmq_connect(zmq_host->sock.obj, zmq_host->sock.str); } else if (strlen(zmq_host->sock_inproc.str)) { if (zmq_host->sock_inproc.obj_tx) { ret = zmq_connect(zmq_host->sock_inproc.obj_tx, zmq_host->sock_inproc.str); } else { ret = zmq_connect(zmq_host->sock_inproc.obj, zmq_host->sock_inproc.str); } } if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_connect() failed: %s (%s)\nExiting.\n", zmq_host->log_id, (strlen(zmq_host->sock.str) ? zmq_host->sock.str : zmq_host->sock_inproc.str), zmq_strerror(errno)); exit_gracefully(1); } return ret; } void p_zmq_ctx_setup(struct p_zmq_host *zmq_host) { if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); } void p_zmq_zap_setup(struct p_zmq_host *zmq_host) { zmq_host->zap.thread = zmq_threadstart(&p_zmq_zap_handler, zmq_host); } void p_zmq_pub_setup(struct p_zmq_host *zmq_host) { p_zmq_send_setup(zmq_host, ZMQ_PUB, FALSE); } void p_zmq_push_setup(struct p_zmq_host *zmq_host) { p_zmq_send_setup(zmq_host, ZMQ_PUSH, FALSE); } void p_zmq_push_connect_setup(struct p_zmq_host *zmq_host) { p_zmq_send_setup(zmq_host, ZMQ_PUSH, TRUE); } void p_zmq_send_setup(struct p_zmq_host *zmq_host, int type, int do_connect) { int ret, only_one = 1; void *sock; if (!zmq_host) return; if (type != ZMQ_PUB && type != ZMQ_PUSH) return; if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); if (!do_connect) { if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { p_zmq_zap_setup(zmq_host); } } sock = zmq_socket(zmq_host->ctx, type); if (!sock) { Log(LOG_ERR, "ERROR ( %s ): zmq_socket() failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_setsockopt(sock, ZMQ_SNDHWM, &zmq_host->hwm, sizeof(int)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_SNDHWM failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_setsockopt(sock, ZMQ_BACKLOG, &only_one, sizeof(int)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_BACKLOG failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } if (strlen(zmq_host->sock_inproc.str)) { zmq_host->sock_inproc.obj = sock; if (do_connect) { zmq_host->sock_inproc.obj_tx = zmq_host->sock_inproc.obj; } else { zmq_host->sock_inproc.obj_rx = zmq_host->sock_inproc.obj; } } else { zmq_host->sock.obj = sock; } if (!do_connect) p_zmq_bind(zmq_host); else p_zmq_connect(zmq_host); Log(LOG_DEBUG, "DEBUG ( %s ): p_zmq_send_setup() addr=%s username=%s password=%s\n", zmq_host->log_id, (strlen(zmq_host->sock.str) ? zmq_host->sock.str : zmq_host->sock_inproc.str), zmq_host->zap.username, zmq_host->zap.password); } void p_zmq_sub_setup(struct p_zmq_host *zmq_host) { p_zmq_recv_setup(zmq_host, ZMQ_SUB, FALSE); } void p_zmq_pull_setup(struct p_zmq_host *zmq_host) { p_zmq_recv_setup(zmq_host, ZMQ_PULL, FALSE); } void p_zmq_pull_bind_setup(struct p_zmq_host *zmq_host) { p_zmq_recv_setup(zmq_host, ZMQ_PULL, TRUE); } void p_zmq_recv_setup(struct p_zmq_host *zmq_host, int type, int do_bind) { int ret; void *sock; if (!zmq_host) return; if (type != ZMQ_SUB && type != ZMQ_PULL) return; if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); if (do_bind) { if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { p_zmq_zap_setup(zmq_host); } } sock = zmq_socket(zmq_host->ctx, type); if (!sock) { Log(LOG_ERR, "ERROR ( %s ): zmq_socket() failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_setsockopt(sock, ZMQ_RCVHWM, &zmq_host->hwm, sizeof(int)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_RCVHWM failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } if (strlen(zmq_host->sock_inproc.str)) { zmq_host->sock_inproc.obj = sock; if (!do_bind) { zmq_host->sock_inproc.obj_tx = zmq_host->sock_inproc.obj; } else { zmq_host->sock_inproc.obj_rx = zmq_host->sock_inproc.obj; } } else zmq_host->sock.obj = sock; if (!do_bind) ret = p_zmq_connect(zmq_host); else ret = p_zmq_bind(zmq_host); if (type == ZMQ_SUB) { if (zmq_host->topic) { ret = zmq_setsockopt(sock, ZMQ_SUBSCRIBE, &zmq_host->topic, sizeof(zmq_host->topic)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() SUBSCRIBE failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } } /* subscribe to all topics */ else zmq_setsockopt(sock, ZMQ_SUBSCRIBE, NULL, 0); } Log(LOG_DEBUG, "DEBUG ( %s ): p_zmq_recv_setup() addr=%s username=%s password=%s\n", zmq_host->log_id, (strlen(zmq_host->sock.str) ? zmq_host->sock.str : zmq_host->sock_inproc.str), zmq_host->zap.username, zmq_host->zap.password); } int p_zmq_topic_send(struct p_zmq_host *zmq_host, void *buf, u_int64_t len) { int ret; ret = zmq_send(zmq_host->sock.obj, &zmq_host->topic, sizeof(zmq_host->topic), ZMQ_SNDMORE); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): publishing topic to ZMQ: zmq_send(): %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); return ret; } ret = zmq_send(zmq_host->sock.obj, buf, len, 0); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): publishing data to ZMQ: zmq_send(): %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); return ret; } return ret; } int p_zmq_recv_poll(struct p_zmq_sock *sock, int timeout) { zmq_pollitem_t item[1]; void *s; if (sock->obj_rx) s = sock->obj_rx; else s = sock->obj; item[0].socket = s; item[0].events = ZMQ_POLLIN; return zmq_poll(item, 1, timeout); } int p_zmq_topic_recv(struct p_zmq_host *zmq_host, void *buf, u_int64_t len) { int ret = 0, events; size_t elen = sizeof(events); u_int8_t topic, retries = 0; zmq_events_again: ret = zmq_getsockopt(zmq_host->sock.obj, ZMQ_EVENTS, &events, &elen); if (ret == ERR) { if (retries < PM_ZMQ_EVENTS_RETRIES) { Log(LOG_DEBUG, "DEBUG ( %s ): consuming topic from ZMQ: zmq_getsockopt() for ZMQ_EVENTS: %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); retries++; goto zmq_events_again; } else { Log(LOG_ERR, "ERROR ( %s ): consuming topic from ZMQ: zmq_getsockopt() for ZMQ_EVENTS: %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); return ret; } } if (events & ZMQ_POLLIN) { ret = zmq_recv(zmq_host->sock.obj, &topic, 1, 0); /* read topic first */ if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): consuming topic from ZMQ: zmq_recv(): %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); return ret; } ret = zmq_recv(zmq_host->sock.obj, buf, len, 0); /* read actual data then */ if (ret == ERR) Log(LOG_ERR, "ERROR ( %s ): consuming data from ZMQ: zmq_recv(): %s [topic=%u]\n", zmq_host->log_id, zmq_strerror(errno), zmq_host->topic); else if (ret > len) { Log(LOG_ERR, "ERROR ( %s ): consuming data from ZMQ: zmq_recv(): buffer overrun [topic=%u]\n", zmq_host->log_id, zmq_host->topic); ret = ERR; } } return ret; } char *p_zmq_recv_str(struct p_zmq_sock *sock) { char buf[SRVBUFLEN]; int len; void *s; if (sock->obj_rx) s = sock->obj_rx; else s = sock->obj; memset(buf, 0, sizeof(buf)); len = zmq_recv(s, buf, (sizeof(buf) - 1), 0); if (len == ERR) return NULL; else return strndup(buf, sizeof(buf)); } int p_zmq_send_str(struct p_zmq_sock *sock, char *buf) { int len; void *s; if (sock->obj_rx) s = sock->obj_rx; else s = sock->obj; len = zmq_send(s, buf, strlen(buf), 0); return len; } int p_zmq_sendmore_str(struct p_zmq_sock *sock, char *buf) { int len; void *s; if (sock->obj_rx) s = sock->obj_rx; else s = sock->obj; len = zmq_send(s, buf, strlen(buf), ZMQ_SNDMORE); return len; } int p_zmq_recv_bin(struct p_zmq_sock *sock, void *buf, size_t len) { int rcvlen; void *s; if (sock->obj_rx) s = sock->obj_rx; else s = sock->obj; rcvlen = zmq_recv(s, buf, len, 0); return rcvlen; } int p_zmq_send_bin(struct p_zmq_sock *sock, void *buf, size_t len, int nonblock) { int sndlen; void *s; if (sock->obj_tx) s = sock->obj_tx; else s = sock->obj; if (!nonblock) sndlen = zmq_send(s, buf, len, 0); else sndlen = zmq_send(s, buf, len, ZMQ_DONTWAIT); return sndlen; } int p_zmq_sendmore_bin(struct p_zmq_sock *sock, void *buf, size_t len, int nonblock) { int sndlen; void *s; if (sock->obj_tx) s = sock->obj_tx; else s = sock->obj; if (!nonblock) sndlen = zmq_send(s, buf, len, ZMQ_SNDMORE); else sndlen = zmq_send(s, buf, len, (ZMQ_SNDMORE|ZMQ_DONTWAIT)); return sndlen; } void p_zmq_zap_handler(void *zh) { struct p_zmq_host *zmq_host = (struct p_zmq_host *) zh; struct p_zmq_sock zmq_sock; int ret; memset(&zmq_sock, 0, sizeof(zmq_sock)); zmq_sock.obj = zmq_socket(zmq_host->ctx, ZMQ_REP); if (!zmq_sock.obj) { Log(LOG_ERR, "ERROR ( %s ): zmq_socket() ZAP failed (%s)\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } snprintf(zmq_sock.str, sizeof(zmq_sock.str), "%s", "inproc://zeromq.zap.01"); ret = zmq_bind(zmq_sock.obj, zmq_sock.str); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_bind() ZAP failed (%s)\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } while (TRUE) { char *version, *sequence, *domain, *address, *identity; char *mechanism, *username, *password; version = p_zmq_recv_str(&zmq_sock); if (!version) break; sequence = p_zmq_recv_str(&zmq_sock); domain = p_zmq_recv_str(&zmq_sock); address = p_zmq_recv_str(&zmq_sock); identity = p_zmq_recv_str(&zmq_sock); mechanism = p_zmq_recv_str(&zmq_sock); if (!strcmp(version, "1.0") && !strcmp(mechanism, "PLAIN")) { username = p_zmq_recv_str(&zmq_sock); password = p_zmq_recv_str(&zmq_sock); p_zmq_sendmore_str(&zmq_sock, version); p_zmq_sendmore_str(&zmq_sock, sequence); if (!strcmp(username, zmq_host->zap.username) && !strcmp(password, zmq_host->zap.password)) { p_zmq_sendmore_str(&zmq_sock, "200"); p_zmq_sendmore_str(&zmq_sock, "OK"); p_zmq_sendmore_str(&zmq_sock, "anonymous"); p_zmq_send_str(&zmq_sock, ""); } else { p_zmq_sendmore_str(&zmq_sock, "400"); p_zmq_sendmore_str(&zmq_sock, "Invalid username or password"); p_zmq_sendmore_str(&zmq_sock, ""); p_zmq_send_str(&zmq_sock, ""); } free(username); free(password); } else { p_zmq_sendmore_str(&zmq_sock, version); p_zmq_sendmore_str(&zmq_sock, sequence); p_zmq_sendmore_str(&zmq_sock, "400"); p_zmq_sendmore_str(&zmq_sock, "Unsupported auth mechanism"); p_zmq_sendmore_str(&zmq_sock, ""); p_zmq_send_str(&zmq_sock, ""); } free(version); free(sequence); free(domain); free(address); free(identity); free(mechanism); } zmq_close(zmq_sock.obj); } void p_zmq_router_setup(struct p_zmq_host *zmq_host, char *host, int port) { char server_str[SHORTBUFLEN]; int ret, as_server = TRUE; if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); zmq_host->sock.obj = zmq_socket(zmq_host->ctx, ZMQ_ROUTER); if (!zmq_host->sock.obj) { Log(LOG_ERR, "ERROR ( %s ): zmq_socket() failed for ZMQ_ROUTER: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } if (strlen(zmq_host->zap.username) && strlen(zmq_host->zap.password)) { p_zmq_zap_setup(zmq_host); ret = zmq_setsockopt(zmq_host->sock.obj, ZMQ_PLAIN_SERVER, &as_server, sizeof(int)); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_setsockopt() ZMQ_PLAIN_SERVER failed for topic %u: %s\nExiting.\n", zmq_host->log_id, zmq_host->topic, zmq_strerror(errno)); exit_gracefully(1); } } snprintf(server_str, SHORTBUFLEN, "tcp://%s:%u", host, port); ret = zmq_bind(zmq_host->sock.obj, server_str); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_bind() failed for ZMQ_ROUTER: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } } void p_zmq_dealer_inproc_setup(struct p_zmq_host *zmq_host) { int ret; if (!zmq_host->ctx) zmq_host->ctx = zmq_ctx_new(); zmq_host->sock_inproc.obj = zmq_socket(zmq_host->ctx, ZMQ_DEALER); if (!zmq_host->sock_inproc.obj) { Log(LOG_ERR, "ERROR ( %s ): zmq_socket() failed for ZMQ_DEALER: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_bind(zmq_host->sock_inproc.obj, zmq_host->sock_inproc.str); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_bind() failed for ZMQ_DEALER: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } } void p_zmq_proxy_setup(struct p_zmq_host *zmq_host) { int ret; ret = zmq_proxy(zmq_host->sock.obj, zmq_host->sock_inproc.obj, NULL); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): zmq_proxy() failed: %s\nExiting.\n", zmq_host->log_id, zmq_strerror(errno)); exit_gracefully(1); } } void p_zmq_router_backend_setup(struct p_zmq_host *zmq_host, int thread_nbr) { int idx; p_zmq_dealer_inproc_setup(zmq_host); zmq_host->router_worker.threads = malloc(sizeof(void *) * thread_nbr); for (idx = 0; idx < thread_nbr; idx++) { zmq_host->router_worker.threads[thread_nbr] = zmq_threadstart(&p_zmq_router_worker, zmq_host); } p_zmq_proxy_setup(zmq_host); } void p_zmq_router_worker(void *zh) { struct p_zmq_host *zmq_host = (struct p_zmq_host *) zh; struct p_zmq_sock sock; int ret; assert(zmq_host); memset(&sock, 0, sizeof(sock)); sock.obj = zmq_socket(zmq_host->ctx, ZMQ_REP); if (!sock.obj) { Log(LOG_ERR, "ERROR ( %s ): p_zmq_router_worker zmq_socket() failed: %s (%s)\nExiting.\n", zmq_host->log_id, zmq_host->sock_inproc.str, zmq_strerror(errno)); exit_gracefully(1); } ret = zmq_connect(sock.obj, zmq_host->sock_inproc.str); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s ): p_zmq_router_worker zmq_connect() failed: %s (%s)\nExiting.\n", zmq_host->log_id, zmq_host->sock_inproc.str, zmq_strerror(errno)); exit_gracefully(1); } zmq_host->router_worker.func(zmq_host, &sock); } void p_zmq_close(struct p_zmq_host *zmq_host) { p_zmq_plugin_pipe_init_plugin(zmq_host); } pmacct-1.7.8/src/setproctitle.c0000644000175000017500000001254114354105275015471 0ustar paolopaolo/* * setproctitle()-related routines in this file are derived from Sendmail * 8.13.5 which is: * * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include "pmacct.h" /* * SETPROCTITLE -- set process title for ps */ #define SPT_NONE 0 /* don't use it at all */ #define SPT_REUSEARGV 1 /* cover argv with title information */ #define SPT_BUILTIN 2 /* use libc builtin */ #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ #include "setproctitle.h" #define MAXLINE (2*LONGLONGSRVBUFLEN) #define SPACELEFT(x) (sizeof(x)-strlen(x)) #if defined PROGNAME && SPT_TYPE == SPT_REUSEARGV extern char *__progname; #endif /* * NEWSTR -- Create a copy of a C string */ char *spt_newstr(s) const char *s; { size_t l; char *n; l = strlen(s); n = malloc(l + 1); strlcpy(n, s, l + 1); return n; } #ifndef SPT_TYPE # define SPT_TYPE SPT_NONE #endif /* ! SPT_TYPE */ #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN #if SPT_TYPE == SPT_PSTAT # include #endif /* SPT_TYPE == SPT_PSTAT */ #ifndef SPT_PADCHAR # define SPT_PADCHAR ' ' #endif /* ! SPT_PADCHAR */ #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ #ifndef SPT_BUFSIZE # define SPT_BUFSIZE MAXLINE #endif /* ! SPT_BUFSIZE */ /* * Pointers for setproctitle. * This allows "ps" listings to give more useful information. */ static char **Argv = NULL; /* pointer to argument vector */ static char *LastArgv = NULL; /* end of argv */ void initsetproctitle(argc, argv, envp) int argc; char **argv; char **envp; { register int i; extern char **environ; /* ** Move the environment so setproctitle can use the space at ** the top of memory. */ if (envp != NULL) { for (i = 0; envp[i] != NULL; i++) continue; environ = (char **) malloc(sizeof (char *) * (i + 1)); for (i = 0; envp[i] != NULL; i++) environ[i] = spt_newstr(envp[i]); environ[i] = NULL; } /* ** Save start and extent of argv for setproctitle. */ Argv = argv; /* ** Determine how much space we can use for setproctitle. ** Use all contiguous argv and envp pointers starting at argv[0] */ for (i = 0; i < argc; i++) { if (i == 0 || LastArgv + 1 == argv[i]) LastArgv = argv[i] + strlen(argv[i]); } for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++) { if (LastArgv + 1 == envp[i]) LastArgv = envp[i] + strlen(envp[i]); } #if defined PROGNAME && SPT_TYPE == SPT_REUSEARGV if (config.uacctd_group) __progname = uacctd_globstr; /* XXX: hack */ else if (config.acct_type == ACCT_PM) __progname = pmacctd_globstr; else if (config.acct_type == ACCT_NF) __progname = nfacctd_globstr; else if (config.acct_type == ACCT_SF) __progname = sfacctd_globstr; else if (config.acct_type == ACCT_PMTELE) __progname = pmtele_globstr; else if (config.acct_type == ACCT_PMBGP) __progname = pmbgpd_globstr; else if (config.acct_type == ACCT_PMBMP) __progname = pmbmpd_globstr; #endif } #if SPT_TYPE != SPT_BUILTIN /*VARARGS1*/ static void # ifdef __STDC__ setproctitle(const char *fmt, ...) # else /* __STDC__ */ setproctitle(fmt, va_alist) const char *fmt; va_dcl # endif /* __STDC__ */ { # if SPT_TYPE != SPT_NONE register int i; register char *p; char buf[SPT_BUFSIZE]; va_list ap; # if SPT_TYPE == SPT_PSTAT union pstun pst; # endif /* SPT_TYPE == SPT_PSTAT */ memset(buf, 0, SPT_BUFSIZE); p = buf; va_start(ap, fmt); vsnprintf(p, SPACELEFT(buf), fmt, ap); va_end(ap); i = (int) strlen(buf); if (i < 0) return; # if SPT_TYPE == SPT_PSTAT pst.pst_command = buf; pstat(PSTAT_SETCMD, pst, i, 0, 0); # endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_REUSEARGV if (LastArgv == NULL) return; if (i > (LastArgv - Argv[0]) - 2) { i = (LastArgv - Argv[0]) - 2; buf[i] = '\0'; } (void) strlcpy(Argv[0], buf, i + 1); p = &Argv[0][i]; while (p < LastArgv) *p++ = SPT_PADCHAR; Argv[1] = NULL; # endif /* SPT_TYPE == SPT_REUSEARGV */ # endif /* SPT_TYPE != SPT_NONE */ } #endif /* SPT_TYPE != SPT_BUILTIN */ /* * PM_SETPROCTITLE -- set process task and set process title for ps */ /*VARARGS2*/ void #ifdef __STDC__ pm_setproctitle(const char *fmt, ...) #else /* __STDC__ */ pm_setproctitle(fmt, va_alist) const char *fmt; va_dcl #endif /* __STDC__ */ { char buf[SPT_BUFSIZE]; char prefix[16]; va_list ap; memset(prefix, 0, sizeof(prefix)); memset(buf, 0, sizeof(buf)); if (config.uacctd_group) strcpy(prefix, uacctd_globstr); /* XXX: hack */ else if (config.acct_type == ACCT_PM) strcpy(prefix, pmacctd_globstr); else if (config.acct_type == ACCT_NF) strcpy(prefix, nfacctd_globstr); else if (config.acct_type == ACCT_SF) strcpy(prefix, sfacctd_globstr); else if (config.acct_type == ACCT_PMTELE) strcpy(prefix, pmtele_globstr); else if (config.acct_type == ACCT_PMBGP) strcpy(prefix, pmbgpd_globstr); else if (config.acct_type == ACCT_PMBMP) strcpy(prefix, pmbmpd_globstr); va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); #if SPT_TYPE != SPT_BUILTIN setproctitle("%s: %s", prefix, buf); #else setproctitle("%s", buf); #endif } pmacct-1.7.8/src/nfacctd.c0000644000175000017500000040755414354105275014366 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #ifdef WITH_KAFKA #include "kafka_common.h" #endif #include "nfacctd.h" #include "pretag_handlers.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_flow.h" #include "ip_frag.h" #include "classifier.h" #include "net_aggr.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "isis/isis.h" #include "bmp/bmp.h" #include "telemetry/telemetry.h" #if defined WITH_EBPF #include "ebpf/ebpf_rp_balancer.h" #endif #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif #include "tee_plugin/tee_plugin.h" /* Global variables */ struct template_cache tpl_cache; struct host_addr debug_a; char debug_agent_addr[50]; u_int16_t debug_agent_port; cdada_map_t *tpl_data_map, *tpl_opt_map; /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", NFACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -L IP address ] [ -l port ] [ -c primitive [ , ... ] ] [ -P plugin [ , ... ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -L \tBind to the specified IP address\n"); printf(" -l \tListen on the specified UDP port\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -a \tPrint list of supported aggregation primitives\n"); printf(" -c \tAggregation method, see full list of primitives with -a (DEFAULT: src_host)\n"); printf(" -D \tDaemonize\n"); printf(" -n \tPath to a file containing networks and/or ASNs definitions\n"); printf(" -t \tPath to a file containing ports definitions\n"); printf(" -P \t[ memory | print | mysql | pgsql | sqlite3 | amqp | kafka | tee ] \n\tActivate plugin\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -R \tRenormalize sampled data\n"); printf(" -u \tLeave IP protocols in numerical format\n"); printf(" -I \tRead packets from the specified savefile\n"); printf(" -Z \tReading from a savefile, sleep the given amount of seconds at startup and between replays\n"); printf(" -W \tReading from a savefile, don't exit but sleep when finished\n"); printf(" -Y \tReading from a savefile, replay the number of times specified\n"); printf("\nMemory plugin (-P memory) options:\n"); printf(" -p \tSocket for client-server communication (DEFAULT: /tmp/collect.pipe)\n"); printf(" -b \tNumber of buckets\n"); printf(" -m \tNumber of memory pools\n"); printf(" -s \tMemory pool size\n"); printf("\nPrint plugin (-P print) plugin options:\n"); printf(" -r \tRefresh time (in seconds)\n"); printf(" -O \t[ formatted | csv | json | avro ] \n\tOutput format\n"); printf(" -o \tPath to output file\n"); printf(" -M \tPrint event init/close marker messages\n"); printf(" -A \tAppend output (applies to -o)\n"); printf(" -E \tCSV format separator (applies to -O csv, DEFAULT: ',')\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { struct plugins_list_entry *list; struct plugin_requests req; struct packet_ptrs_vector pptrs; char config_file[SRVBUFLEN]; unsigned char *netflow_packet; unsigned char *netflow_templates_packet; int logf, rc = 0, yes=1, allowed; struct host_addr addr; struct hosts_table allow; struct id_table bpas_table; struct id_table blp_table; struct id_table bmed_table; struct id_table biss_table; struct id_table bta_table; struct id_table bitr_table; struct id_table sampling_table; u_int32_t idx; int ret; int capture_methods = 0; struct sockaddr_storage server, server_templates; struct sockaddr_storage client; struct ipv6_mreq multi_req6; struct tee_receiver tee_templates; socklen_t clen = sizeof(client), slen = 0; struct ip_mreq multi_req4; int templates_sock = 0; #ifdef WITH_GNUTLS struct sockaddr_storage server_dtls; int dtls_sock = 0; #endif int pm_pcap_savefile_round = 0; unsigned char dummy_packet[64]; unsigned char dummy_packet_vlan[64]; unsigned char dummy_packet_mpls[128]; unsigned char dummy_packet_vlan_mpls[128]; struct pcap_pkthdr dummy_pkthdr; struct pcap_pkthdr dummy_pkthdr_vlan; struct pcap_pkthdr dummy_pkthdr_mpls; struct pcap_pkthdr dummy_pkthdr_vlan_mpls; unsigned char dummy_packet6[92]; unsigned char dummy_packet_vlan6[92]; unsigned char dummy_packet_mpls6[128]; unsigned char dummy_packet_vlan_mpls6[128]; struct pcap_pkthdr dummy_pkthdr6; struct pcap_pkthdr dummy_pkthdr_vlan6; struct pcap_pkthdr dummy_pkthdr_mpls6; struct pcap_pkthdr dummy_pkthdr_vlan_mpls6; struct packet_ptrs recv_pptrs; struct pcap_pkthdr recv_pkthdr; sigset_t signal_set; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; /* select() stuff */ fd_set read_descs, bkp_read_descs; int select_fd, bkp_select_fd, num_descs; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); NF_compute_once(); /* a bunch of default definitions */ reload_map = FALSE; print_stats = FALSE; reload_geoipv2_file = FALSE; sampling_map_allocated = FALSE; bpas_map_allocated = FALSE; blp_map_allocated = FALSE; bmed_map_allocated = FALSE; biss_map_allocated = FALSE; bta_map_allocated = FALSE; bitr_map_allocated = FALSE; custom_primitives_allocated = FALSE; bta_map_caching = TRUE; sampling_map_caching = TRUE; find_id_func = NF_find_id; plugins_list = NULL; netflow_packet = malloc(NETFLOW_MSG_SIZE); netflow_templates_packet = malloc(NETFLOW_MSG_SIZE); data_plugins = 0; tee_plugins = 0; errflag = 0; memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&server, 0, sizeof(server)); memset(&client, 0, sizeof(client)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(&failed_plugins, 0, sizeof(failed_plugins)); memset(&pptrs, 0, sizeof(pptrs)); memset(&req, 0, sizeof(req)); memset(&class, 0, sizeof(class)); memset(&xflow_status_table, 0, sizeof(xflow_status_table)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); memset(&bpas_table, 0, sizeof(bpas_table)); memset(&blp_table, 0, sizeof(blp_table)); memset(&bmed_table, 0, sizeof(bmed_table)); memset(&biss_table, 0, sizeof(biss_table)); memset(&bta_table, 0, sizeof(bta_table)); memset(&bitr_table, 0, sizeof(bitr_table)); memset(&sampling_table, 0, sizeof(sampling_table)); memset(&reload_map_tstamp, 0, sizeof(reload_map_tstamp)); #ifdef WITH_GNUTLS memset(&dtls_status_table, 0, sizeof(dtls_status_table)); #endif log_notifications_init(&log_notifications); config.acct_type = ACCT_NF; config.progname = nfacctd_globstr; rows = 0; memset(&device, 0, sizeof(device)); memset(&recv_pptrs, 0, sizeof(recv_pptrs)); memset(&recv_pkthdr, 0, sizeof(recv_pkthdr)); select_fd = 0; bkp_select_fd = 0; num_descs = 0; FD_ZERO(&read_descs); FD_ZERO(&bkp_read_descs); { u_int16_t tpl_hash_keylen = calc_template_keylen(); char pm_cdada_map_container[tpl_hash_keylen]; tpl_data_map = cdada_map_create(pm_cdada_map_container); if (!tpl_data_map) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to allocate tpl_data_map. Exiting.\n", config.name, config.type); exit_gracefully(1); } tpl_opt_map = cdada_map_create(pm_cdada_map_container); if (!tpl_opt_map) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to allocate tpl_opt_map. Exiting.\n", config.name, config.type); exit_gracefully(1); } } /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_NFACCTD)) != -1)) { if (!cfg_cmdline[rows]) cfg_cmdline[rows] = malloc(SRVBUFLEN); memset(cfg_cmdline[rows], 0, SRVBUFLEN); switch (cp) { case 'L': strlcpy(cfg_cmdline[rows], "nfacctd_ip: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'l': strlcpy(cfg_cmdline[rows], "nfacctd_port: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'P': strlcpy(cfg_cmdline[rows], "plugins: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'n': strlcpy(cfg_cmdline[rows], "networks_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 't': strlcpy(cfg_cmdline[rows], "ports_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "print_output: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "print_output_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'M': strlcpy(cfg_cmdline[rows], "print_markers: true", SRVBUFLEN); rows++; break; case 'A': strlcpy(cfg_cmdline[rows], "print_output_file_append: true", SRVBUFLEN); rows++; break; case 'E': strlcpy(cfg_cmdline[rows], "print_output_separator: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'u': strlcpy(cfg_cmdline[rows], "print_num_protos: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); free(cfg_cmdline[rows]); cfg_cmdline[rows] = NULL; break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'c': strlcpy(cfg_cmdline[rows], "aggregate: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'b': strlcpy(cfg_cmdline[rows], "imt_buckets: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'm': strlcpy(cfg_cmdline[rows], "imt_mem_pools_number: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'p': strlcpy(cfg_cmdline[rows], "imt_path: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'r': strlcpy(cfg_cmdline[rows], "sql_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 's': strlcpy(cfg_cmdline[rows], "imt_mem_pools_size: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'R': strlcpy(cfg_cmdline[rows], "sfacctd_renormalize: true", SRVBUFLEN); rows++; break; case 'I': strlcpy(cfg_cmdline[rows], "pcap_savefile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'W': strlcpy(cfg_cmdline[rows], "pcap_savefile_wait: true", SRVBUFLEN); rows++; break; case 'Z': strlcpy(cfg_cmdline[rows], "pcap_savefile_delay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Y': strlcpy(cfg_cmdline[rows], "pcap_savefile_replay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, NFACCTD_USAGE_HEADER); exit(0); break; case 'a': print_primitives(config.acct_type, NFACCTD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } /* XXX: glue; i'm conscious it's a dirty solution from an engineering viewpoint; someday later i'll fix this */ list = plugins_list; while (list) { list->cfg.acct_type = ACCT_NF; list->cfg.progname = nfacctd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); list = plugins_list; while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { list = plugins_list; while (list) { if (!strcmp(list->type.string, "print") && !list->cfg.print_output_file) printf("INFO ( %s/%s ): Daemonizing. Bye bye screen.\n", list->name, list->type.string); list = list->next; } if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, NFACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); /* Enforcing policies over aggregation methods */ list = plugins_list; while (list) { if (list->type.id != PLUGIN_ID_CORE) { /* applies to all plugins */ plugin_pipe_check(&list->cfg); if (list->cfg.sampling_rate && config.ext_sampling_rate) { Log(LOG_ERR, "ERROR ( %s/core ): Internal packet sampling and external packet sampling are mutual exclusive.\n", config.name); exit_gracefully(1); } /* applies to specific plugins */ if (list->type.id == PLUGIN_ID_NFPROBE || list->type.id == PLUGIN_ID_SFPROBE) { Log(LOG_ERR, "ERROR ( %s/core ): 'nfprobe' and 'sfprobe' plugins not supported in 'nfacctd'.\n", config.name); exit_gracefully(1); } else if (list->type.id == PLUGIN_ID_TEE) { tee_plugins++; list->cfg.what_to_count = COUNT_NONE; list->cfg.data_type = PIPE_TYPE_MSG; } else { list->cfg.data_type = PIPE_TYPE_METADATA; if (list->cfg.what_to_count_2 & (COUNT_POST_NAT_SRC_HOST|COUNT_POST_NAT_DST_HOST| COUNT_POST_NAT_SRC_PORT|COUNT_POST_NAT_DST_PORT|COUNT_NAT_EVENT| COUNT_TIMESTAMP_START|COUNT_TIMESTAMP_END|COUNT_TIMESTAMP_ARRIVAL| COUNT_EXPORT_PROTO_TIME|COUNT_FWD_STATUS|COUNT_FW_EVENT)) list->cfg.data_type |= PIPE_TYPE_NAT; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP| COUNT_MPLS_LABEL_BOTTOM)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_TUNNEL_SRC_MAC|COUNT_TUNNEL_DST_MAC| COUNT_TUNNEL_SRC_HOST|COUNT_TUNNEL_DST_HOST|COUNT_TUNNEL_IP_PROTO| COUNT_TUNNEL_IP_TOS|COUNT_TUNNEL_SRC_PORT|COUNT_TUNNEL_DST_PORT| COUNT_VXLAN)) list->cfg.data_type |= PIPE_TYPE_TUN; if (list->cfg.what_to_count_2 & (COUNT_LABEL|COUNT_MPLS_LABEL_STACK)) list->cfg.data_type |= PIPE_TYPE_VLEN; if (list->cfg.what_to_count & (COUNT_SRC_PORT|COUNT_DST_PORT|COUNT_SUM_PORT|COUNT_TCPFLAGS)) { enable_ip_fragment_handler(); } evaluate_sums(&list->cfg.what_to_count, &list->cfg.what_to_count_2, list->name, list->type.string); if (!list->cfg.what_to_count && !list->cfg.what_to_count_2 && !list->cfg.cpptrs.num) { Log(LOG_WARNING, "WARN ( %s/%s ): defaulting to SRC HOST aggregation.\n", list->name, list->type.string); list->cfg.what_to_count |= COUNT_SRC_HOST; } if (list->cfg.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) { if (!list->cfg.networks_file && list->cfg.nfacctd_as & NF_AS_NEW) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation selected but NO 'networks_file' specified. Exiting.\n\n", list->name, list->type.string); exit_gracefully(1); } if (!list->cfg.bgp_daemon && !list->cfg.bmp_daemon && list->cfg.nfacctd_as == NF_AS_BGP) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation selected but 'bgp_daemon' or 'bmp_daemon' is not enabled. Exiting.\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; } if (list->cfg.what_to_count & (COUNT_SRC_NET|COUNT_DST_NET|COUNT_SUM_NET|COUNT_SRC_NMASK|COUNT_DST_NMASK|COUNT_PEER_DST_IP)) { if (!list->cfg.nfacctd_net) { if (list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; if (list->cfg.networks_mask) list->cfg.nfacctd_net |= NF_NET_STATIC; if (!list->cfg.nfacctd_net) list->cfg.nfacctd_net = NF_NET_KEEP; } else { if ((list->cfg.nfacctd_net == NF_NET_NEW && !list->cfg.networks_file) || (list->cfg.nfacctd_net == NF_NET_STATIC && !list->cfg.networks_mask) || (list->cfg.nfacctd_net == NF_NET_BGP && !list->cfg.bgp_daemon && !list->cfg.bmp_daemon) || (list->cfg.nfacctd_net == NF_NET_IGP && !list->cfg.nfacctd_isis)) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'bgp_daemon', 'bmp_daemon', 'isis_daemon', 'networks_file', 'networks_mask' is specified. Exiting.\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; } } #if defined (WITH_NDPI) if (list->cfg.what_to_count_2 & COUNT_NDPI_CLASS) { enable_ip_fragment_handler(); config.classifier_ndpi = TRUE; } #endif list->cfg.type_id = list->type.id; bgp_config_checks(&list->cfg); data_plugins++; list->cfg.what_to_count |= COUNT_COUNTERS; } } list = list->next; } if (tee_plugins && data_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): 'tee' plugins are not compatible with data (memory/mysql/pgsql/etc.) plugins. Exiting.\n\n", config.name); exit_gracefully(1); } if (config.pcap_savefile) capture_methods++; if (config.nfacctd_port || config.nfacctd_ip) capture_methods++; #ifdef WITH_KAFKA if (config.nfacctd_kafka_broker_host || config.nfacctd_kafka_topic) capture_methods++; #endif #ifdef WITH_ZMQ if (config.nfacctd_zmq_address) capture_methods++; #endif if (capture_methods > 1) { Log(LOG_ERR, "ERROR ( %s/core ): pcap_savefile, nfacctd_ip, nfacctd_kafka_* and nfacctd_zmq_* are mutual exclusive. Exiting.\n\n", config.name); exit_gracefully(1); } if (config.nfacctd_templates_port) { if (!config.nfacctd_port && !config.nfacctd_ip && capture_methods) { Log(LOG_ERR, "ERROR ( %s/core ): nfacctd_templates_port only applies to live UDP collection (nfacctd_ip, nfacctd_port). Exiting.\n\n", config.name); exit_gracefully(1); } } if (config.nfacctd_templates_receiver) { if (tee_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): nfacctd_templates_receiver and tee plugin ae mutual exclusive. Exiting.\n\n", config.name); exit_gracefully(1); } } #ifdef WITH_KAFKA if ((config.nfacctd_kafka_broker_host && !config.nfacctd_kafka_topic) || (config.nfacctd_kafka_topic && !config.nfacctd_kafka_broker_host)) { Log(LOG_ERR, "ERROR ( %s/core ): Kafka collection requires both nfacctd_kafka_broker_host and nfacctd_kafka_topic to be specified. Exiting.\n\n", config.name); exit_gracefully(1); } if (config.nfacctd_kafka_broker_host && tee_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): Kafka collection is mutual exclusive with 'tee' plugins. Exiting.\n\n", config.name); exit_gracefully(1); } #endif #ifdef WITH_ZMQ if (config.nfacctd_zmq_address && tee_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): ZeroMQ collection is mutual exclusive with 'tee' plugins. Exiting.\n\n", config.name); exit_gracefully(1); } #endif /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ sighandler_action.sa_handler = startup_handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = push_stats; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port && !config.dtls_path) { Log(LOG_ERR, "ERROR ( %s/core ): 'nfacctd_dtls_port' specified but missing 'dtls_path'. Exiting.\n", config.name); exit_gracefully(1); } if (config.dtls_path) { pm_dtls_init(&config.dtls_globs, config.dtls_path); } #endif if (config.pcap_savefile) { open_pcap_savefile(&device, config.pcap_savefile); pm_pcap_savefile_round = 1; enable_ip_fragment_handler(); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { NF_init_kafka_host(&nfacctd_kafka_host); recv_pptrs.pkthdr = &recv_pkthdr; enable_ip_fragment_handler(); } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { int pipe_fd = 0; NF_init_zmq_host(&nfacctd_zmq_host, &pipe_fd); recv_pptrs.pkthdr = &recv_pkthdr; enable_ip_fragment_handler(); } #endif else { /* If no IP address is supplied, let's set our default behaviour: IPv4 address, INADDR_ANY, port 2100 */ if (!config.nfacctd_port) config.nfacctd_port = DEFAULT_NFACCTD_PORT; collector_port = config.nfacctd_port; if (!config.nfacctd_ip) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&server; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.nfacctd_port); slen = sizeof(struct sockaddr_in6); if (config.nfacctd_templates_port) { sa6 = (struct sockaddr_in6 *)&server_templates; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.nfacctd_templates_port); } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port) { sa6 = (struct sockaddr_in6 *)&server_dtls; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.nfacctd_dtls_port); } #endif } else { trim_spaces(config.nfacctd_ip); ret = str_to_addr(config.nfacctd_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/core ): 'nfacctd_ip' value is not valid. Exiting.\n", config.name); exit_gracefully(1); } slen = addr_to_sa((struct sockaddr *)&server, &addr, config.nfacctd_port); if (config.nfacctd_templates_port) { addr_to_sa((struct sockaddr *)&server_templates, &addr, config.nfacctd_templates_port); } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port) { addr_to_sa((struct sockaddr *)&server_dtls, &addr, config.nfacctd_dtls_port); } #endif } /* socket creation */ config.sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); if (config.sock < 0) { /* retry with IPv4 */ if (!config.nfacctd_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.nfacctd_port); slen = sizeof(struct sockaddr_in); config.sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); } if (config.sock < 0) { Log(LOG_ERR, "ERROR ( %s/core ): socket() failed.\n", config.name); exit_gracefully(1); } } if (config.nfacctd_templates_port) { config.nfacctd_templates_sock = socket(((struct sockaddr *)&server_templates)->sa_family, SOCK_DGRAM, 0); if (config.nfacctd_templates_sock < 0) { /* retry with IPv4 */ if (!config.nfacctd_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server_templates; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.nfacctd_templates_port); slen = sizeof(struct sockaddr_in); config.nfacctd_templates_sock = socket(((struct sockaddr *)&server_templates)->sa_family, SOCK_DGRAM, 0); } if (config.nfacctd_templates_sock < 0) { Log(LOG_ERR, "ERROR ( %s/core ): TPLS socket() failed.\n", config.name); exit_gracefully(1); } } } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port) { config.nfacctd_dtls_sock = socket(((struct sockaddr *)&server_dtls)->sa_family, SOCK_DGRAM, 0); if (config.nfacctd_dtls_sock < 0) { /* retry with IPv4 */ if (!config.nfacctd_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server_dtls; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.nfacctd_dtls_port); slen = sizeof(struct sockaddr_in); config.nfacctd_dtls_sock = socket(((struct sockaddr *)&server_dtls)->sa_family, SOCK_DGRAM, 0); } if (config.nfacctd_dtls_sock < 0) { Log(LOG_ERR, "ERROR ( %s/core ): DTLS socket() failed.\n", config.name); exit_gracefully(1); } } } #endif if (config.nfacctd_templates_port || config.nfacctd_dtls_port) { FD_SET(config.sock, &bkp_read_descs); bkp_select_fd = config.sock; if (config.nfacctd_templates_sock) { FD_SET(config.nfacctd_templates_sock, &bkp_read_descs); bkp_select_fd = (bkp_select_fd < config.nfacctd_templates_sock) ? config.nfacctd_templates_sock : bkp_select_fd; } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_sock) { FD_SET(config.nfacctd_dtls_sock, &bkp_read_descs); bkp_select_fd = (bkp_select_fd < config.nfacctd_dtls_sock) ? config.nfacctd_dtls_sock : bkp_select_fd; } #endif bkp_select_fd++; } /* bind socket to port */ #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.sock, SOL_SOCKET, SO_REUSEPORT, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEPORT.\n", config.name); #endif rc = setsockopt(config.sock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEADDR.\n", config.name); #if (defined HAVE_SO_BINDTODEVICE) if (config.nfacctd_interface) { rc = setsockopt(config.sock, SOL_SOCKET, SO_BINDTODEVICE, config.nfacctd_interface, (socklen_t) strlen(config.nfacctd_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, errno); } #endif if (config.nfacctd_templates_port) { #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.nfacctd_templates_sock, SOL_SOCKET, SO_REUSEPORT, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEPORT.\n", config.name); #endif rc = setsockopt(config.nfacctd_templates_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEADDR.\n", config.name); #if (defined HAVE_SO_BINDTODEVICE) if (config.nfacctd_interface) { rc = setsockopt(config.nfacctd_templates_sock, SOL_SOCKET, SO_BINDTODEVICE, config.nfacctd_interface, (socklen_t) strlen(config.nfacctd_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, errno); } #endif } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port) { #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.nfacctd_dtls_sock, SOL_SOCKET, SO_REUSEPORT, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEPORT.\n", config.name); #endif rc = setsockopt(config.nfacctd_dtls_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEADDR.\n", config.name); #if (defined HAVE_SO_BINDTODEVICE) if (config.nfacctd_interface) { rc = setsockopt(config.nfacctd_dtls_sock, SOL_SOCKET, SO_BINDTODEVICE, config.nfacctd_interface, (socklen_t) strlen(config.nfacctd_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, errno); } #endif } #endif if (config.nfacctd_ipv6_only) { int yes=1; rc = setsockopt(config.sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for IPV6_V6ONLY.\n", config.name); } if (config.nfacctd_pipe_size) { socklen_t l = sizeof(config.nfacctd_pipe_size); int saved = 0, obtained = 0; getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(config.sock, SOL_SOCKET, SO_RCVBUF, &config.nfacctd_pipe_size, (socklen_t) sizeof(config.nfacctd_pipe_size)); getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); if (obtained < saved) { Setsocksize(config.sock, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); } Log(LOG_INFO, "INFO ( %s/core ): nfacctd_pipe_size: obtained=%d target=%d.\n", config.name, obtained, config.nfacctd_pipe_size); } /* Multicast: memberships handling */ for (idx = 0; mcast_groups[idx].family && idx < MAX_MCAST_GROUPS; idx++) { if (mcast_groups[idx].family == AF_INET) { memset(&multi_req4, 0, sizeof(multi_req4)); multi_req4.imr_multiaddr.s_addr = mcast_groups[idx].address.ipv4.s_addr; if (setsockopt(config.sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multi_req4, (socklen_t) sizeof(multi_req4)) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): IPv4 multicast address - ADD membership failed.\n", config.name); exit_gracefully(1); } } if (mcast_groups[idx].family == AF_INET6) { memset(&multi_req6, 0, sizeof(multi_req6)); ip6_addr_cpy(&multi_req6.ipv6mr_multiaddr, &mcast_groups[idx].address.ipv6); if (setsockopt(config.sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&multi_req6, (socklen_t) sizeof(multi_req6)) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): IPv6 multicast address - ADD membership failed.\n", config.name); exit_gracefully(1); } } } memset(&tee_templates, 0, sizeof(struct tee_receiver)); } if (config.nfacctd_templates_receiver) { tee_templates.dest_len = sizeof(tee_templates.dest); ret = Tee_parse_hostport(config.nfacctd_templates_receiver, (struct sockaddr *) &tee_templates.dest, &tee_templates.dest_len, FALSE); if (ret) { Log(LOG_ERR, "ERROR ( %s/core ): Invalid nfacctd_templates_receiver: %s.\n", config.name, config.nfacctd_templates_receiver); exit_gracefully(1); } tee_templates.fd = Tee_prepare_sock((struct sockaddr *) &tee_templates.dest, tee_templates.dest_len, NULL, FALSE, TRUE, FALSE); } if (config.nfacctd_allow_file) load_allow_file(config.nfacctd_allow_file, &allow); else memset(&allow, 0, sizeof(allow)); if (config.sampling_map) { load_id_file(MAP_SAMPLING, config.sampling_map, &sampling_table, &req, &sampling_map_allocated); set_sampling_table(&pptrs, (u_char *) &sampling_table); } else set_sampling_table(&pptrs, NULL); if (config.nfacctd_flow_to_rd_map) { load_id_file(MAP_FLOW_TO_RD, config.nfacctd_flow_to_rd_map, &bitr_table, &req, &bitr_map_allocated); pptrs.v4.bitr_table = (u_char *) &bitr_table; } else pptrs.v4.bitr_table = NULL; if (config.aggregate_primitives) { req.key_value_table = (void *) &custom_primitives_registry; load_id_file(MAP_CUSTOM_PRIMITIVES, config.aggregate_primitives, NULL, &req, &custom_primitives_allocated); } else memset(&custom_primitives_registry, 0, sizeof(custom_primitives_registry)); /* fixing per plugin custom primitives pointers, offsets and lengths */ list = plugins_list; while(list) { custom_primitives_reconcile(&list->cfg.cpptrs, &custom_primitives_registry); if (custom_primitives_vlen(&list->cfg.cpptrs)) list->cfg.data_type |= PIPE_TYPE_VLEN; list = list->next; } if (config.bgp_daemon && config.bmp_daemon) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_daemon and bmp_daemon are currently mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } /* starting the ISIS threa */ if (config.nfacctd_isis) { req.bpf_filter = TRUE; nfacctd_isis_wrapper(); /* Let's give the ISIS thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } /* starting the BGP thread */ if (config.bgp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_stdcomm_pattern_to_asn && config.bgp_daemon_lrgcomm_pattern_to_asn) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_stdcomm_pattern_to_asn and bgp_lrgcomm_pattern_to_asn are mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } load_comm_patterns(&config.bgp_daemon_stdcomm_pattern, &config.bgp_daemon_extcomm_pattern, &config.bgp_daemon_lrgcomm_pattern, &config.bgp_daemon_stdcomm_pattern_to_asn, &config.bgp_daemon_lrgcomm_pattern_to_asn); if (config.bgp_daemon_peer_as_src_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_peer_as_src_map) { load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); pptrs.v4.bpas_table = (u_char *) &bpas_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_peer_as_src_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.bpas_table = NULL; if (config.bgp_daemon_src_local_pref_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_local_pref_map) { load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); pptrs.v4.blp_table = (u_char *) &blp_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_local_pref_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.blp_table = NULL; if (config.bgp_daemon_src_med_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_med_map) { load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); pptrs.v4.bmed_table = (u_char *) &bmed_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_med_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.bmed_table = NULL; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); pptrs.v4.bta_table = (u_char *) &bta_table; } else pptrs.v4.bta_table = NULL; bgp_daemon_wrapper(); /* Let's give the BGP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } /* starting the BMP thread */ if (config.bmp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); pptrs.v4.bta_table = (u_char *) &bta_table; } else pptrs.v4.bta_table = NULL; bmp_daemon_wrapper(); /* Let's give the BMP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } /* starting the telemetry thread */ if (config.telemetry_daemon) { telemetry_wrapper(); /* Let's give the telemetry thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } #if defined WITH_GEOIP if (config.geoip_ipv4_file || config.geoip_ipv6_file) { req.bpf_filter = TRUE; } #endif #if defined WITH_GEOIPV2 if (config.geoipv2_file) { req.bpf_filter = TRUE; } #endif if (!config.pcap_savefile && !config.nfacctd_kafka_broker_host && !config.nfacctd_zmq_address) { rc = bind(config.sock, (struct sockaddr *) &server, slen); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/core ): bind() to ip=%s port=%d/udp failed (errno: %d).\n", config.name, config.nfacctd_ip, config.nfacctd_port, errno); exit_gracefully(1); } #if defined WITH_EBPF if (config.nfacctd_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(config.sock, config.nfacctd_rp_ebpf_prog, config.cluster_name, "nfacctd", config.cluster_id, FALSE); } #endif if (config.nfacctd_templates_port) { rc = bind(config.nfacctd_templates_sock, (struct sockaddr *) &server_templates, slen); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/core ): bind() to ip=%s port=%d/udp failed (errno: %d).\n", config.name, config.nfacctd_ip, config.nfacctd_templates_port, errno); exit_gracefully(1); } #if defined WITH_EBPF if (config.nfacctd_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(config.nfacctd_templates_sock, config.nfacctd_rp_ebpf_prog, config.cluster_name, "nfacctd_tpl", config.cluster_id, FALSE); } #endif } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_port) { rc = bind(config.nfacctd_dtls_sock, (struct sockaddr *) &server_dtls, slen); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/core ): bind() to ip=%s port=%d/udp failed (errno: %d).\n", config.name, config.nfacctd_ip, config.nfacctd_dtls_port, errno); exit_gracefully(1); } } #endif } init_classifiers(); #if defined (WITH_NDPI) if (config.classifier_ndpi) { enable_ip_fragment_handler(); pm_ndpi_wfl = pm_ndpi_workflow_init(); pm_ndpi_export_proto_to_class(pm_ndpi_wfl); } else pm_ndpi_wfl = NULL; #endif /* plugins glue: creation */ load_plugins(&req); load_plugin_filters(1); evaluate_packet_handlers(); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); load_networks(config.networks_file, &nt, &nc); /* signals to be handled only by the core process; we set proper handlers after plugin creation */ sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); kill(getpid(), SIGCHLD); /* initializing template cache */ memset(&tpl_cache, 0, sizeof(tpl_cache)); tpl_cache.num = TEMPLATE_CACHE_ENTRIES; if (config.nfacctd_templates_file) { load_templates_from_file(config.nfacctd_templates_file); } /* arranging static pointers to dummy packet; to speed up things into the main loop we mantain two packet_ptrs structures when IPv6 is enabled: we will sync here 'pptrs6' for common tables and pointers */ memset(dummy_packet, 0, sizeof(dummy_packet)); pptrs.v4.f_agent = (u_char *) &client; pptrs.v4.packet_ptr = dummy_packet; pptrs.v4.pkthdr = &dummy_pkthdr; Assign16(((struct eth_header *)pptrs.v4.packet_ptr)->ether_type, htons(ETHERTYPE_IP)); /* 0x800 */ pptrs.v4.mac_ptr = (u_char *)((struct eth_header *)pptrs.v4.packet_ptr)->ether_dhost; pptrs.v4.iph_ptr = pptrs.v4.packet_ptr + ETHER_HDRLEN; pptrs.v4.tlh_ptr = pptrs.v4.packet_ptr + ETHER_HDRLEN + sizeof(struct pm_iphdr); Assign8(((struct pm_iphdr *)pptrs.v4.iph_ptr)->ip_vhl, 5); // pptrs.v4.pkthdr->caplen = 38; /* eth_header + pm_iphdr + pm_tlhdr */ pptrs.v4.pkthdr->caplen = 55; pptrs.v4.pkthdr->len = 100; /* fake len */ pptrs.v4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_vlan, 0, sizeof(dummy_packet_vlan)); pptrs.vlan4.f_agent = (u_char *) &client; pptrs.vlan4.packet_ptr = dummy_packet_vlan; pptrs.vlan4.pkthdr = &dummy_pkthdr_vlan; Assign16(((struct eth_header *)pptrs.vlan4.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlan4.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlan4.packet_ptr)->ether_dhost; pptrs.vlan4.vlan_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN; Assign16(*(pptrs.vlan4.vlan_ptr+2), htons(ETHERTYPE_IP)); pptrs.vlan4.iph_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; pptrs.vlan4.tlh_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN + sizeof(struct pm_iphdr); Assign8(((struct pm_iphdr *)pptrs.vlan4.iph_ptr)->ip_vhl, 5); // pptrs.vlan4.pkthdr->caplen = 42; /* eth_header + vlan + pm_iphdr + pm_tlhdr */ pptrs.vlan4.pkthdr->caplen = 59; pptrs.vlan4.pkthdr->len = 100; /* fake len */ pptrs.vlan4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_mpls, 0, sizeof(dummy_packet_mpls)); pptrs.mpls4.f_agent = (u_char *) &client; pptrs.mpls4.packet_ptr = dummy_packet_mpls; pptrs.mpls4.pkthdr = &dummy_pkthdr_mpls; Assign16(((struct eth_header *)pptrs.mpls4.packet_ptr)->ether_type, htons(ETHERTYPE_MPLS)); pptrs.mpls4.mac_ptr = (u_char *)((struct eth_header *)pptrs.mpls4.packet_ptr)->ether_dhost; pptrs.mpls4.mpls_ptr = pptrs.mpls4.packet_ptr + ETHER_HDRLEN; // pptrs.mpls4.pkthdr->caplen = 78; /* eth_header + upto 10 MPLS labels + pm_iphdr + pm_tlhdr */ pptrs.mpls4.pkthdr->caplen = 95; pptrs.mpls4.pkthdr->len = 100; /* fake len */ pptrs.mpls4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_vlan_mpls, 0, sizeof(dummy_packet_vlan_mpls)); pptrs.vlanmpls4.f_agent = (u_char *) &client; pptrs.vlanmpls4.packet_ptr = dummy_packet_vlan_mpls; pptrs.vlanmpls4.pkthdr = &dummy_pkthdr_vlan_mpls; Assign16(((struct eth_header *)pptrs.vlanmpls4.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlanmpls4.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlanmpls4.packet_ptr)->ether_dhost; pptrs.vlanmpls4.vlan_ptr = pptrs.vlanmpls4.packet_ptr + ETHER_HDRLEN; Assign16(((struct vlan_header *)pptrs.vlanmpls4.vlan_ptr)->proto, htons(ETHERTYPE_MPLS)); pptrs.vlanmpls4.mpls_ptr = pptrs.vlanmpls4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; // pptrs.vlanmpls4.pkthdr->caplen = 82; /* eth_header + vlan + upto 10 MPLS labels + pm_iphdr + pm_tlhdr */ pptrs.vlanmpls4.pkthdr->caplen = 99; pptrs.vlanmpls4.pkthdr->len = 100; /* fake len */ pptrs.vlanmpls4.l3_proto = ETHERTYPE_IP; memset(dummy_packet6, 0, sizeof(dummy_packet6)); pptrs.v6.f_agent = (u_char *) &client; pptrs.v6.packet_ptr = dummy_packet6; pptrs.v6.pkthdr = &dummy_pkthdr6; Assign16(((struct eth_header *)pptrs.v6.packet_ptr)->ether_type, htons(ETHERTYPE_IPV6)); pptrs.v6.mac_ptr = (u_char *)((struct eth_header *)pptrs.v6.packet_ptr)->ether_dhost; pptrs.v6.iph_ptr = pptrs.v6.packet_ptr + ETHER_HDRLEN; pptrs.v6.tlh_ptr = pptrs.v6.packet_ptr + ETHER_HDRLEN + sizeof(struct ip6_hdr); Assign16(((struct ip6_hdr *)pptrs.v6.iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs.v6.iph_ptr)->ip6_hlim = 64; // pptrs.v6.pkthdr->caplen = 60; /* eth_header + ip6_hdr + pm_tlhdr */ pptrs.v6.pkthdr->caplen = 77; pptrs.v6.pkthdr->len = 100; /* fake len */ pptrs.v6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_vlan6, 0, sizeof(dummy_packet_vlan6)); pptrs.vlan6.f_agent = (u_char *) &client; pptrs.vlan6.packet_ptr = dummy_packet_vlan6; pptrs.vlan6.pkthdr = &dummy_pkthdr_vlan6; Assign16(((struct eth_header *)pptrs.vlan6.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlan6.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlan6.packet_ptr)->ether_dhost; pptrs.vlan6.vlan_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN; Assign8(*(pptrs.vlan6.vlan_ptr+2), 0x86); Assign8(*(pptrs.vlan6.vlan_ptr+3), 0xDD); pptrs.vlan6.iph_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; pptrs.vlan6.tlh_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN + sizeof(struct ip6_hdr); Assign16(((struct ip6_hdr *)pptrs.vlan6.iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs.vlan6.iph_ptr)->ip6_hlim = 64; // pptrs.vlan6.pkthdr->caplen = 64; /* eth_header + vlan + ip6_hdr + pm_tlhdr */ pptrs.vlan6.pkthdr->caplen = 81; pptrs.vlan6.pkthdr->len = 100; /* fake len */ pptrs.vlan6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_mpls6, 0, sizeof(dummy_packet_mpls6)); pptrs.mpls6.f_agent = (u_char *) &client; pptrs.mpls6.packet_ptr = dummy_packet_mpls6; pptrs.mpls6.pkthdr = &dummy_pkthdr_mpls6; Assign16(((struct eth_header *)pptrs.mpls6.packet_ptr)->ether_type, htons(ETHERTYPE_MPLS)); pptrs.mpls6.mac_ptr = (u_char *)((struct eth_header *)pptrs.mpls6.packet_ptr)->ether_dhost; pptrs.mpls6.mpls_ptr = pptrs.mpls6.packet_ptr + ETHER_HDRLEN; // pptrs.mpls6.pkthdr->caplen = 100; /* eth_header + upto 10 MPLS labels + ip6_hdr + pm_tlhdr */ pptrs.mpls6.pkthdr->caplen = 117; pptrs.mpls6.pkthdr->len = 128; /* fake len */ pptrs.mpls6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_vlan_mpls6, 0, sizeof(dummy_packet_vlan_mpls6)); pptrs.vlanmpls6.f_agent = (u_char *) &client; pptrs.vlanmpls6.packet_ptr = dummy_packet_vlan_mpls6; pptrs.vlanmpls6.pkthdr = &dummy_pkthdr_vlan_mpls6; Assign16(((struct eth_header *)pptrs.vlanmpls6.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlanmpls6.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlanmpls6.packet_ptr)->ether_dhost; pptrs.vlanmpls6.vlan_ptr = pptrs.vlanmpls6.packet_ptr + ETHER_HDRLEN; Assign8(*(pptrs.vlanmpls6.vlan_ptr+2), 0x88); Assign8(*(pptrs.vlanmpls6.vlan_ptr+3), 0x47); pptrs.vlanmpls6.mpls_ptr = pptrs.vlanmpls6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; // pptrs.vlanmpls6.pkthdr->caplen = 104; /* eth_header + vlan + upto 10 MPLS labels + ip6_hdr + pm_tlhdr */ pptrs.vlanmpls6.pkthdr->caplen = 121; pptrs.vlanmpls6.pkthdr->len = 128; /* fake len */ pptrs.vlanmpls6.l3_proto = ETHERTYPE_IPV6; if (config.pcap_savefile) { Log(LOG_INFO, "INFO ( %s/core ): reading NetFlow/IPFIX data from: %s\n", config.name, config.pcap_savefile); allowed = TRUE; if (!config.pcap_sf_delay) sleep(2); else sleep(config.pcap_sf_delay); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { Log(LOG_INFO, "INFO ( %s/core ): reading NetFlow/IPFIX data from Kafka %s:%s\n", config.name, p_kafka_get_broker(&nfacctd_kafka_host), p_kafka_get_topic(&nfacctd_kafka_host)); allowed = TRUE; } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { Log(LOG_INFO, "INFO ( %s/core ): reading NetFlow/IPFIX data from ZeroMQ %s\n", config.name, p_zmq_get_address(&nfacctd_zmq_host)); allowed = TRUE; } #endif else { char srv_string[INET6_ADDRSTRLEN]; struct host_addr srv_addr; u_int16_t srv_port; sa_to_addr((struct sockaddr *)&server, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/core ): waiting for NetFlow/IPFIX data on %s:%u\n", config.name, srv_string, srv_port); allowed = TRUE; if (config.nfacctd_templates_port) { sa_to_addr((struct sockaddr *)&server_templates, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/core ): waiting for NetFlow/IPFIX templates on %s:%u\n", config.name, srv_string, srv_port); } #if WITH_GNUTLS if (config.nfacctd_dtls_port) { sa_to_addr((struct sockaddr *)&server_dtls, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/core ): waiting for DTLS NetFlow/IPFIX on %s:%u\n", config.name, srv_string, srv_port); } #endif } #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif /* fixing NetFlow v9/IPFIX template func pointers */ get_ext_db_ie_by_type = &ext_db_get_ie; sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } /* Main loop */ for (;;) { sigprocmask(SIG_BLOCK, &signal_set, NULL); if (config.pcap_savefile) { ret = recvfrom_savefile(&device, (void **) &netflow_packet, (struct sockaddr *) &client, NULL, &pm_pcap_savefile_round, &recv_pptrs); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { int kafka_reconnect = FALSE; void *kafka_msg = NULL; ret = p_kafka_consume_poller(&nfacctd_kafka_host, &kafka_msg, 1000); switch (ret) { case TRUE: /* got data */ ret = p_kafka_consume_data(&nfacctd_kafka_host, kafka_msg, netflow_packet, NETFLOW_MSG_SIZE); if (ret < 0) kafka_reconnect = TRUE; break; case FALSE: /* timeout */ continue; break; case ERR: /* error */ default: kafka_reconnect = TRUE; break; } if (kafka_reconnect) { /* Close */ p_kafka_manage_consumer(&nfacctd_kafka_host, FALSE); /* Re-open */ NF_init_kafka_host(&nfacctd_kafka_host); continue; } ret = recvfrom_rawip(netflow_packet, ret, (struct sockaddr *) &client, &recv_pptrs); } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { ret = p_zmq_recv_poll(&nfacctd_zmq_host.sock, 1000); switch (ret) { case TRUE: /* got data */ ret = p_zmq_recv_bin(&nfacctd_zmq_host.sock, netflow_packet, NETFLOW_MSG_SIZE); if (ret < 0) continue; /* ZMQ_RECONNECT_IVL */ break; case FALSE: /* timeout */ continue; break; case ERR: /* error */ default: continue; /* ZMQ_RECONNECT_IVL */ break; } ret = recvfrom_rawip(netflow_packet, ret, (struct sockaddr *) &client, &recv_pptrs); } #endif else { if (!config.nfacctd_templates_port && !config.nfacctd_dtls_port) { ret = recvfrom(config.sock, (unsigned char *)netflow_packet, NETFLOW_MSG_SIZE, 0, (struct sockaddr *) &client, &clen); } else { select_func_again: select_fd = bkp_select_fd; memcpy(&read_descs, &bkp_read_descs, sizeof(bkp_read_descs)); num_descs = select(select_fd, &read_descs, NULL, NULL, NULL); select_read_again: if (num_descs > 0) { if (FD_ISSET(config.sock, &read_descs)) { ret = recvfrom(config.sock, (unsigned char *)netflow_packet, NETFLOW_MSG_SIZE, 0, (struct sockaddr *) &client, &clen); FD_CLR(config.sock, &read_descs); num_descs--; templates_sock = FALSE; #ifdef WITH_GNUTLS dtls_sock = FALSE; #endif collector_port = config.nfacctd_port; } else if (FD_ISSET(config.nfacctd_templates_sock, &read_descs)) { ret = recvfrom(config.nfacctd_templates_sock, (unsigned char *)netflow_packet, NETFLOW_MSG_SIZE, 0, (struct sockaddr *) &client, &clen); FD_CLR(config.nfacctd_templates_sock, &read_descs); num_descs--; templates_sock = TRUE; #ifdef WITH_GNUTLS dtls_sock = FALSE; #endif collector_port = config.nfacctd_templates_port; } #ifdef WITH_GNUTLS else if (FD_ISSET(config.nfacctd_dtls_sock, &read_descs)) { /* Peek only here since gnutls wants to consume on its own */ ret = recvfrom(config.nfacctd_dtls_sock, (unsigned char *)netflow_packet, NETFLOW_MSG_SIZE, MSG_PEEK, (struct sockaddr *) &client, &clen); FD_CLR(config.nfacctd_dtls_sock, &read_descs); num_descs--; templates_sock = FALSE; dtls_sock = TRUE; collector_port = config.nfacctd_dtls_port; } #endif } else goto select_func_again; } } /* we have no data or not not enough data to decode the version */ if (!netflow_packet || ret < 2) continue; pptrs.v4.f_len = ret; ipv4_mapped_to_ipv4(&client); /* check if Hosts Allow Table is loaded; if it is, we will enforce rules */ if (allow.num) allowed = check_allow(&allow, (struct sockaddr *)&client); if (!allowed) continue; if (reload_map) { bta_map_caching = TRUE; sampling_map_caching = TRUE; req.key_value_table = NULL; if (config.nfacctd_allow_file) load_allow_file(config.nfacctd_allow_file, &allow); load_networks(config.networks_file, &nt, &nc); if (config.bgp_daemon && config.bgp_daemon_peer_as_src_map) load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_local_pref_map) load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_med_map) load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); if (config.bgp_daemon && config.bgp_daemon_to_xflow_agent_map) load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); if (config.nfacctd_flow_to_rd_map) load_id_file(MAP_FLOW_TO_RD, config.nfacctd_flow_to_rd_map, &bitr_table, &req, &bitr_map_allocated); if (config.sampling_map) { load_id_file(MAP_SAMPLING, config.sampling_map, &sampling_table, &req, &sampling_map_allocated); set_sampling_table(&pptrs, (u_char *) &sampling_table); } reload_map = FALSE; gettimeofday(&reload_map_tstamp, NULL); } if (reload_log) { reload_logs(NFACCTD_USAGE_HEADER); reload_log = FALSE; } if (print_stats) { time_t now = time(NULL); print_status_table(&xflow_status_table, now, XFLOW_STATUS_TABLE_SZ); print_stats = FALSE; } #ifdef WITH_GNUTLS if (dtls_sock) { ret = pm_dtls_server_process(config.nfacctd_dtls_sock, &client, clen, netflow_packet, ret, &dtls_status_table); if (!ret) { continue; } } #endif if (data_plugins) { int has_templates = 0; u_int16_t nfv; /* We will change byte ordering in order to avoid a bunch of ntohs() calls */ nfv = ((struct struct_header_v5 *)netflow_packet)->version = ntohs(((struct struct_header_v5 *)netflow_packet)->version); reset_tag_label_status(&pptrs); reset_shadow_status(&pptrs); switch (nfv) { case 5: process_v5_packet(netflow_packet, ret, &pptrs.v4, &req, nfv, NULL); break; /* NetFlow v9 + IPFIX */ case 9: case 10: process_v9_packet(netflow_packet, ret, &pptrs, &req, nfv, NULL, &has_templates); /* Let's replicate templates only if not received on nfacctd_templates_port in order to prevent infinite looping */ if (config.nfacctd_templates_receiver && has_templates && !templates_sock) { int netflow_templates_len = 0; struct pkt_msg tee_msg; memset(&tee_msg, 0, sizeof(tee_msg)); memcpy(&tee_msg.agent, &client, sizeof(client)); /* fix version before sending */ ((struct struct_header_v5 *)netflow_packet)->version = ntohs(((struct struct_header_v5 *)netflow_packet)->version); Tee_select_templates(netflow_packet, ret, nfv, netflow_templates_packet, &netflow_templates_len); tee_msg.payload = netflow_templates_packet; tee_msg.len = netflow_templates_len; if (tee_msg.len) { Tee_send(&tee_msg, (struct sockaddr *) &tee_templates.dest, tee_templates.fd, TRUE); } } break; default: if (!config.nfacctd_disable_checks) { notify_malf_packet(LOG_INFO, "INFO", "discarding unknown packet", (struct sockaddr *) pptrs.v4.f_agent, 0); xflow_status_table.tot_bad_datagrams++; } break; } } else if (tee_plugins) { if (req.ptm_c.exec_ptm_dissect) { reset_tag_label_status(&pptrs); /* We will change byte ordering in order to avoid a bunch of ntohs() calls */ ((struct struct_header_v5 *)netflow_packet)->version = ntohs(((struct struct_header_v5 *)netflow_packet)->version); } process_raw_packet(netflow_packet, ret, &pptrs, &req); } if (num_descs > 0) goto select_read_again; sigprocmask(SIG_UNBLOCK, &signal_set, NULL); } } void process_v5_packet(unsigned char *pkt, u_int16_t len, struct packet_ptrs *pptrs, struct plugin_requests *req, u_int16_t version, struct NF_dissect *tee_dissect) { struct struct_header_v5 *hdr_v5 = (struct struct_header_v5 *)pkt; struct struct_export_v5 *exp_v5; unsigned short int count = ntohs(hdr_v5->count); if (len < NfHdrV5Sz) { notify_malf_packet(LOG_INFO, "INFO", "discarding short NetFlow v5 packet", (struct sockaddr *) pptrs->f_agent, 0); xflow_status_table.tot_bad_datagrams++; return; } pptrs->f_header = pkt; pkt += NfHdrV5Sz; exp_v5 = (struct struct_export_v5 *)pkt; pptrs->f_status = (u_char *) nfv5_check_status(pptrs); pptrs->f_status_g = NULL; reset_mac(pptrs); pptrs->flow_type.traffic_type = PM_FTYPE_TRAFFIC; if (tee_dissect) { tee_dissect->hdrVersion = version; tee_dissect->hdrCount = 1; tee_dissect->hdrBasePtr = (u_char *) hdr_v5; tee_dissect->hdrEndPtr = (u_char *) (hdr_v5 + NfHdrV5Sz); tee_dissect->hdrLen = NfHdrV5Sz; /* no flowset in NetFlow v5 */ tee_dissect->flowSetBasePtr = NULL; tee_dissect->flowSetEndPtr = NULL; tee_dissect->flowSetLen = 0; } if ((count <= V5_MAXFLOWS) && ((count*NfDataV5Sz)+NfHdrV5Sz == len)) { if (config.debug) { sa_to_addr((struct sockaddr *)pptrs->f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received NetFlow packet from [%s:%u] version [%u] seqno [%u]\n", config.name, debug_agent_addr, debug_agent_port, version, ntohl(hdr_v5->flow_sequence)); } while (count) { reset_net_status(pptrs); pptrs->f_data = (unsigned char *) exp_v5; if (tee_dissect) { tee_dissect->elemBasePtr = pptrs->f_data; tee_dissect->elemEndPtr = (u_char *) (pptrs->f_data + NfDataV5Sz); tee_dissect->elemLen = NfDataV5Sz; pptrs->tee_dissect_bcast = FALSE; exec_plugins(pptrs, req); goto finalize_record; } if (req->bpf_filter) { Assign32(((struct pm_iphdr *)pptrs->iph_ptr)->ip_src.s_addr, exp_v5->srcaddr.s_addr); Assign32(((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst.s_addr, exp_v5->dstaddr.s_addr); Assign8(((struct pm_iphdr *)pptrs->iph_ptr)->ip_p, exp_v5->prot); Assign8(((struct pm_iphdr *)pptrs->iph_ptr)->ip_tos, exp_v5->tos); Assign16(((struct pm_tlhdr *)pptrs->tlh_ptr)->src_port, exp_v5->srcport); Assign16(((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port, exp_v5->dstport); Assign8(((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags, exp_v5->tcp_flags); } pptrs->lm_mask_src = exp_v5->src_mask; pptrs->lm_mask_dst = exp_v5->dst_mask; pptrs->lm_method_src = NF_NET_KEEP; pptrs->lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrs->l4_proto = exp_v5->prot; /* IP header's id field is unused; we will use it to transport our id */ if (config.nfacctd_isis) isis_srcdst_lookup(pptrs); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, pptrs, &pptrs->bta, &pptrs->bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, pptrs, &pptrs->bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(pptrs, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, pptrs, &pptrs->bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, pptrs, &pptrs->blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, pptrs, &pptrs->bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(pptrs); exec_plugins(pptrs, req); finalize_record: exp_v5++; count--; } } else { notify_malf_packet(LOG_INFO, "INFO", "discarding malformed NetFlow v5 packet", (struct sockaddr *) pptrs->f_agent, 0); xflow_status_table.tot_bad_datagrams++; return; } } void process_v9_packet(unsigned char *pkt, u_int16_t len, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req, u_int16_t version, struct NF_dissect *tee_dissect, int *has_templates) { struct struct_header_v9 *hdr_v9 = (struct struct_header_v9 *)pkt; struct struct_header_ipfix *hdr_v10 = (struct struct_header_ipfix *)pkt; struct template_hdr_v9 *template_hdr = NULL; struct options_template_hdr_v9 *opt_template_hdr = NULL; struct template_cache_entry *tpl = NULL; struct data_hdr_v9 *data_hdr = NULL; struct packet_ptrs *pptrs = &pptrsv->v4; u_int16_t fid, off = 0, flowoff = 0, flowsetlen = 0, flowsetNo = 0; u_int16_t flowsetCount = 0, direction = 0, FlowSeqInc = 0; u_int32_t HdrSz = 0, SourceId = 0, FlowSeq = 0; u_char *dummy_packet_ptr = NULL; int ret; if (version == 9) { HdrSz = NfHdrV9Sz; if (len >= HdrSz) { SourceId = ntohl(hdr_v9->source_id); FlowSeq = ntohl(hdr_v9->flow_sequence); flowsetNo = htons(hdr_v9->count); flowsetCount = 0; } } else if (version == 10) { HdrSz = IpFixHdrSz; if (len >= HdrSz) { SourceId = ntohl(hdr_v10->source_id); FlowSeq = ntohl(hdr_v10->flow_sequence); } flowsetNo = 0; flowsetCount = 0; } if (tee_dissect) { tee_dissect->hdrVersion = version; if (version == 9) tee_dissect->hdrCount = flowsetNo; /* imprecise .. */ else if (version == 10) tee_dissect->hdrCount = 0; tee_dissect->hdrBasePtr = pkt; tee_dissect->hdrEndPtr = (u_char *) (pkt + HdrSz); tee_dissect->hdrLen = HdrSz; } if (config.debug) { sa_to_addr((struct sockaddr *)pptrs->f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received NetFlow/IPFIX packet from [%s:%u] version [%u] seqno [%u]\n", config.name, debug_agent_addr, debug_agent_port, version, FlowSeq); } if (len < HdrSz) { notify_malf_packet(LOG_INFO, "INFO", "discarding short NetFlow v9/IPFIX packet", (struct sockaddr *) pptrsv->v4.f_agent, 0); xflow_status_table.tot_bad_datagrams++; return; } pptrs->f_header = pkt; pkt += HdrSz; off += HdrSz; pptrsv->v4.f_status = (u_char *) nfv9_check_status(pptrs, SourceId, 0, FlowSeq, TRUE); set_vector_f_status(pptrsv); pptrsv->v4.f_status_g = (u_char *) nfv9_check_status(pptrs, 0, NF9_OPT_SCOPE_SYSTEM, 0, FALSE); set_vector_f_status_g(pptrsv); process_flowset: if (off+NfDataHdrV9Sz >= len) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Flowset (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } data_hdr = (struct data_hdr_v9 *)pkt; if (data_hdr->flow_len == 0) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Flowset (NetFlow v9/IPFIX packet claiming flow_len 0!)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } fid = ntohs(data_hdr->flow_id); flowsetlen = ntohs(data_hdr->flow_len); if (flowsetlen < NfDataHdrV9Sz) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Flowset (NetFlow v9/IPFIX packet (flowsetlen < NfDataHdrV9Sz)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } if (tee_dissect) { tee_dissect->flowSetBasePtr = pkt; tee_dissect->flowSetEndPtr = (u_char *) (pkt + NfDataHdrV9Sz); tee_dissect->flowSetLen = NfDataHdrV9Sz; /* updated later */ } if (config.debug) { sa_to_addr((struct sockaddr *)pptrs->f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Processing NetFlow/IPFIX flowset [%d] from [%s:%u] seqno [%u]\n", config.name, fid, debug_agent_addr, debug_agent_port, FlowSeq); } if (fid == 0 || fid == 2) { /* template: 0 NetFlow v9, 2 IPFIX */ unsigned char *tpl_ptr = pkt; u_int16_t pens = 0; if (has_templates) (*has_templates) = TRUE; flowoff = 0; tpl_ptr += NfDataHdrV9Sz; flowoff += NfDataHdrV9Sz; /* broadcast the whole flowset over */ if (tee_dissect) { tee_dissect->elemBasePtr = NULL; tee_dissect->elemEndPtr = NULL; tee_dissect->elemLen = 0; tee_dissect->flowSetEndPtr = (u_char *) (tee_dissect->flowSetBasePtr + ntohs(data_hdr->flow_len)); tee_dissect->flowSetLen = ntohs(data_hdr->flow_len); pptrs->tee_dissect_bcast = TRUE; exec_plugins(pptrs, req); } while (flowoff < flowsetlen) { u_int32_t tpl_len = 0; template_hdr = (struct template_hdr_v9 *) tpl_ptr; if ((off + flowsetlen) > len) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Template Flowset (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } if ((flowsetlen - flowoff) < sizeof(struct template_hdr_v9)) { /* skip padding */ break; } tpl = handle_template(template_hdr, pptrs, fid, SourceId, &pens, flowsetlen-flowoff, FlowSeq); if (!tpl) return; tpl_len = sizeof(struct template_hdr_v9)+(ntohs(template_hdr->num)*sizeof(struct template_field_v9))+(pens*sizeof(u_int32_t)); tpl_ptr += tpl_len; flowoff += tpl_len; } pkt += flowsetlen; off += flowsetlen; } else if (fid == 1 || fid == 3) { /* options template: 1 NetFlow v9, 3 IPFIX */ unsigned char *tpl_ptr = pkt; u_int16_t pens = 0; if (has_templates) (*has_templates) = TRUE; flowoff = 0; tpl_ptr += NfDataHdrV9Sz; flowoff += NfDataHdrV9Sz; /* broadcast the whole flowset over */ if (tee_dissect) { tee_dissect->elemBasePtr = NULL; tee_dissect->elemEndPtr = NULL; tee_dissect->elemLen = 0; tee_dissect->flowSetEndPtr = (u_char *) (tee_dissect->flowSetBasePtr + ntohs(data_hdr->flow_len)); tee_dissect->flowSetLen = ntohs(data_hdr->flow_len); exec_plugins(pptrs, req); } while (flowoff < flowsetlen) { u_int32_t tpl_len = 0; opt_template_hdr = (struct options_template_hdr_v9 *) tpl_ptr; if ((off + flowsetlen) > len) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Options Template Flowset (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } if ((flowsetlen - flowoff) < sizeof(struct options_template_hdr_v9)) { /* skip padding */ break; } tpl = handle_template((struct template_hdr_v9 *)opt_template_hdr, pptrs, fid, SourceId, &pens, flowsetlen-flowoff, FlowSeq); if (!tpl) return; if (fid == 3 /* IPFIX */) { tpl_len = sizeof(struct options_template_hdr_v9) + (((ntohs(opt_template_hdr->scope_len) + ntohs(opt_template_hdr->option_len)) * sizeof(struct template_field_v9)) + (pens * sizeof(u_int32_t))); } else if (fid == 1 /* NetFlow v9 */) { tpl_len = sizeof(struct options_template_hdr_v9) + ((ntohs(opt_template_hdr->scope_len) + ntohs(opt_template_hdr->option_len)) + (pens * sizeof(u_int32_t))); } tpl_ptr += tpl_len; flowoff += tpl_len; } pkt += flowsetlen; off += flowsetlen; } else if (fid >= 256) { /* data */ if (off+flowsetlen > len) { notify_malf_packet(LOG_INFO, "INFO", "unable to read next Data Flowset (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } flowoff = 0; pkt += NfDataHdrV9Sz; flowoff += NfDataHdrV9Sz; tpl = find_template(data_hdr->flow_id, (struct sockaddr *) pptrs->f_agent, fid, SourceId); if (!tpl) { sa_to_addr((struct sockaddr *)pptrs->f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Discarded NetFlow v9/IPFIX packet (R: unknown template %u [%s:%u])\n", config.name, fid, debug_agent_addr, SourceId); pkt += (flowsetlen-NfDataHdrV9Sz); off += flowsetlen; } else if (tpl->template_type == 1) { /* Options coming */ struct xflow_status_entry *entry; struct xflow_status_entry_sampling *sentry, *ssaved; struct xflow_status_entry_class *centry, *csaved; /* broadcast the whole flowset over */ if (tee_dissect) { tee_dissect->elemBasePtr = NULL; tee_dissect->elemEndPtr = NULL; tee_dissect->elemLen = 0; tee_dissect->flowSetEndPtr = (u_char *) (tee_dissect->flowSetBasePtr + ntohs(data_hdr->flow_len)); tee_dissect->flowSetLen = ntohs(data_hdr->flow_len); pptrs->tee_dissect_bcast = TRUE; exec_plugins(pptrs, req); /* goto finalize_opt_record later */ } while (flowoff+tpl->len <= flowsetlen) { entry = (struct xflow_status_entry *) pptrs->f_status; sentry = NULL, ssaved = NULL; centry = NULL, csaved = NULL; if (tee_dissect) goto finalize_opt_record; /* Is this option about sampling? */ if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len || tpl->tpl[NF9_SAMPLING_INTERVAL].len == 4 || tpl->tpl[NF9_SAMPLING_PKT_INTERVAL].len == 4) { u_int8_t t8 = 0; u_int16_t t16 = 0; u_int32_t sampler_id = 0, t32 = 0, t32_2 = 0; u_int64_t t64 = 0; /* Handling the global option scoping case */ if (!config.nfacctd_disable_opt_scope_check) { if (tpl->tpl[NF9_OPT_SCOPE_SYSTEM].len) entry = (struct xflow_status_entry *) pptrs->f_status_g; else { if (version == 10) { if (tpl->tpl[IPFIX_SCOPE_TEMPLATE_ID].len) { entry = (struct xflow_status_entry *) pptrs->f_status; memcpy(&t16, pkt+tpl->tpl[IPFIX_SCOPE_TEMPLATE_ID].off, 2); sampler_id = ntohs(t16); } } } } else entry = (struct xflow_status_entry *) pptrs->f_status_g; if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 1) { memcpy(&t8, pkt+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 1); sampler_id = t8; } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 2) { memcpy(&t16, pkt+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 2); sampler_id = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 4) { memcpy(&t32, pkt+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 4); sampler_id = ntohl(t32); } else if (tpl->tpl[NF9_SELECTOR_ID].len == 8) { memcpy(&t64, pkt+tpl->tpl[NF9_SELECTOR_ID].off, 8); sampler_id = pm_ntohll(t64); /* XXX: sampler_id to be moved to 64 bit */ } if (entry) sentry = search_smp_id_status_table(entry->sampling, sampler_id, FALSE); if (!sentry) sentry = create_smp_entry_status_table(&xflow_status_table, entry); else ssaved = sentry->next; if (sentry) { memset(sentry, 0, sizeof(struct xflow_status_entry_sampling)); if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 1) { memcpy(&t8, pkt+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 1); sentry->sample_pool = t8; } if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 2) { memcpy(&t16, pkt+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 2); sentry->sample_pool = ntohs(t16); } if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 4) { memcpy(&t32, pkt+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 4); sentry->sample_pool = ntohl(t32); } if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 1) { memcpy(&t8, pkt+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 1); sentry->sample_pool = t8; } else if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 2) { memcpy(&t16, pkt+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 2); sentry->sample_pool = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 4) { memcpy(&t32, pkt+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 4); sentry->sample_pool = ntohl(t32); } else if (tpl->tpl[NF9_SAMPLING_PKT_INTERVAL].len == 4 && tpl->tpl[NF9_SAMPLING_PKT_SPACE].len == 4) { u_int32_t pkt_interval = 0, pkt_space = 0; memcpy(&t32, pkt+tpl->tpl[NF9_SAMPLING_PKT_INTERVAL].off, 4); memcpy(&t32_2, pkt+tpl->tpl[NF9_SAMPLING_PKT_SPACE].off, 4); pkt_interval = ntohl(t32); pkt_space = ntohl(t32_2); if (pkt_interval) sentry->sample_pool = ((pkt_interval + pkt_space) / pkt_interval); } sentry->sampler_id = sampler_id; if (ssaved) sentry->next = ssaved; } } if ((tpl->tpl[NF9_APPLICATION_ID].len == 2 || tpl->tpl[NF9_APPLICATION_ID].len == 3 || tpl->tpl[NF9_APPLICATION_ID].len == 5) && tpl->tpl[NF9_APPLICATION_NAME].len > 0) { struct pkt_classifier css; pm_class_t class_id = 0, class_int_id = 0; /* Handling the global option scoping case */ if (!config.nfacctd_disable_opt_scope_check) { if (tpl->tpl[NF9_OPT_SCOPE_SYSTEM].len) entry = (struct xflow_status_entry *) pptrs->f_status_g; } else entry = (struct xflow_status_entry *) pptrs->f_status_g; memcpy(&class_id, (pkt + tpl->tpl[NF9_APPLICATION_ID].off + 1), (tpl->tpl[NF9_APPLICATION_ID].len - 1)); if (entry) centry = search_class_id_status_table(entry->class, class_id); if (!centry) { centry = create_class_entry_status_table(&xflow_status_table, entry); class_int_id = pmct_find_first_free(); } else { csaved = centry->next; class_int_id = centry->class_int_id; pmct_unregister(centry->class_int_id); } if (centry) { memset(centry, 0, sizeof(struct xflow_status_entry_class)); memset(&css, 0, sizeof(struct pkt_classifier)); memcpy(¢ry->class_name, pkt+tpl->tpl[NF9_APPLICATION_NAME].off, MIN((MAX_PROTOCOL_LEN-1), tpl->tpl[NF9_APPLICATION_NAME].len)); centry->class_id = class_id; centry->class_int_id = class_int_id; if (csaved) centry->next = csaved; css.id = centry->class_int_id; strlcpy(css.protocol, centry->class_name, MAX_PROTOCOL_LEN); #if defined (WITH_NDPI) css.category = FALSE; /* unused */ #endif pmct_register(&css); } } if (tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].len == 4 || tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].len == 16) { /* Handling the global option scoping case */ if (!config.nfacctd_disable_opt_scope_check) { if (tpl->tpl[NF9_OPT_SCOPE_SYSTEM].len) entry = (struct xflow_status_entry *) pptrs->f_status_g; } else entry = (struct xflow_status_entry *) pptrs->f_status_g; if (entry) { int got_v4 = FALSE; if (tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].len) { raw_to_addr(&entry->exp_addr, pkt+tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].off, AF_INET); raw_to_sa(&entry->exp_sa, pkt+tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].off, 0, AF_INET); if (!is_any(&entry->exp_addr)) { got_v4 = TRUE; } } if (!got_v4 && tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].len) { raw_to_addr(&entry->exp_addr, pkt+tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].off, AF_INET6); raw_to_sa(&entry->exp_sa, pkt+tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].off, 0, AF_INET6); } } } if (tpl->tpl[NF9_INGRESS_VRFID].len == 4 && tpl->tpl[NF9_MPLS_VPN_RD].len == 8) { /* Handling the global option scoping case */ if (!config.nfacctd_disable_opt_scope_check) { if (tpl->tpl[NF9_OPT_SCOPE_SYSTEM].len) entry = (struct xflow_status_entry *) pptrs->f_status_g; } else entry = (struct xflow_status_entry *) pptrs->f_status_g; if (entry) { u_int32_t ingress_vrfid, egress_vrfid; rd_t *mpls_vpn_rd; if (!entry->in_rd_map) { entry->in_rd_map = cdada_map_create(u_int32_t); /* size of vrfid */ if (!entry->in_rd_map) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to allocate entry->in_rd_map. Exiting.\n", config.name); exit_gracefully(1); } } if (!entry->out_rd_map) { entry->out_rd_map = cdada_map_create(u_int32_t); /* size of vrfid */ if (!entry->out_rd_map) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to allocate entry->out_rd_map. Exiting.\n", config.name); exit_gracefully(1); } } memcpy(&ingress_vrfid, pkt+tpl->tpl[NF9_INGRESS_VRFID].off, tpl->tpl[NF9_INGRESS_VRFID].len); ingress_vrfid = ntohl(ingress_vrfid); memcpy(&egress_vrfid, pkt+tpl->tpl[NF9_EGRESS_VRFID].off, tpl->tpl[NF9_EGRESS_VRFID].len); egress_vrfid = ntohl(egress_vrfid); if (ingress_vrfid || egress_vrfid) { mpls_vpn_rd = malloc(sizeof(rd_t)); memcpy(mpls_vpn_rd, pkt+tpl->tpl[NF9_MPLS_VPN_RD].off, tpl->tpl[NF9_MPLS_VPN_RD].len); bgp_rd_ntoh(mpls_vpn_rd); if (ingress_vrfid) { ret = cdada_map_insert(entry->in_rd_map, &ingress_vrfid, mpls_vpn_rd); if (ret != CDADA_SUCCESS && ret != CDADA_E_EXISTS){ Log(LOG_ERR, "ERROR ( %s/core ): Unable to insert in entry->in_rd_map. Exiting.\n", config.name); exit_gracefully(1); } } if (egress_vrfid) { ret = cdada_map_insert(entry->out_rd_map, &egress_vrfid, mpls_vpn_rd); if (ret != CDADA_SUCCESS && ret != CDADA_E_EXISTS){ Log(LOG_ERR, "ERROR ( %s/core ): Unable to insert in entry->out_rd_map. Exiting.\n", config.name); exit_gracefully(1); } } } } } if (config.nfacctd_account_options) { pptrs->f_data = pkt; pptrs->f_tpl = (u_char *) tpl; reset_net_status_v(pptrsv); NF_evaluate_flow_type(&pptrs->flow_type, tpl, pptrs); exec_plugins(pptrs, req); } finalize_opt_record: pkt += tpl->len; flowoff += tpl->len; FlowSeqInc++; } /* last pre-flight check for the subsequent subtraction */ if (flowoff > flowsetlen) { notify_malf_packet(LOG_INFO, "INFO", "aborting malformed Options Data element (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } pkt += (flowsetlen-flowoff); /* handling padding */ off += flowsetlen; } else { while (flowoff+tpl->len <= flowsetlen) { /* Let's bake offsets and lengths if we have variable-length fields */ if (tpl->vlen) { int ret; ret = resolve_vlen_template(pkt, (flowsetlen - flowoff), tpl); if (ret == ERR) break; } pptrs->f_data = pkt; pptrs->f_tpl = (u_char *) tpl; reset_net_status_v(pptrsv); if (tee_dissect) { tee_dissect->elemBasePtr = pkt; tee_dissect->elemEndPtr = (u_char *) (pkt + tpl->len); tee_dissect->elemLen = tpl->len; pptrs->tee_dissect_bcast = FALSE; exec_plugins(pptrs, req); goto finalize_record; } NF_evaluate_flow_type(&pptrs->flow_type, tpl, pptrs); direction = NF_evaluate_direction(tpl, pptrs); /* we need to understand the IP protocol version in order to build the fake packet */ switch (pptrs->flow_type.traffic_type) { case PM_FTYPE_IPV4: if (req->bpf_filter) { reset_mac(pptrs); reset_ip4(pptrs); if (direction == DIRECTION_IN) { memcpy(pptrs->mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrs->mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrs->mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrs->mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); } ((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, pkt+tpl->tpl[NF9_IPV4_SRC_ADDR].off, tpl->tpl[NF9_IPV4_SRC_ADDR].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, pkt+tpl->tpl[NF9_IPV4_DST_ADDR].off, tpl->tpl[NF9_IPV4_DST_ADDR].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_p, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_tos, pkt+tpl->tpl[NF9_SRC_TOS].off, tpl->tpl[NF9_SRC_TOS].len); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrs->lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrs->lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrs->lm_method_src = NF_NET_KEEP; pptrs->lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrs->l4_proto = 0; memcpy(&pptrs->l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, pptrs, pkt, tpl); NF_mpls_vpn_rd_fromie90(pptrs); if (config.nfacctd_isis) isis_srcdst_lookup(pptrs); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, pptrs, &pptrs->bta, &pptrs->bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, pptrs, &pptrs->bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(pptrs, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, pptrs, &pptrs->bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, pptrs, &pptrs->blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, pptrs, &pptrs->bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(pptrs); exec_plugins(pptrs, req); break; case PM_FTYPE_IPV6: pptrsv->v6.f_header = pptrs->f_header; pptrsv->v6.f_data = pptrs->f_data; pptrsv->v6.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->v6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac(&pptrsv->v6); reset_ip6(&pptrsv->v6); if (direction == DIRECTION_IN) { memcpy(pptrsv->v6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->v6.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->v6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->v6.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); } ((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_src, pkt+tpl->tpl[NF9_IPV6_SRC_ADDR].off, tpl->tpl[NF9_IPV6_SRC_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_dst, pkt+tpl->tpl[NF9_IPV6_DST_ADDR].off, tpl->tpl[NF9_IPV6_DST_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_nxt, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->v6.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->v6.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->v6.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->v6.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->v6.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->v6.lm_method_src = NF_NET_KEEP; pptrsv->v6.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->v6.l4_proto = 0; memcpy(&pptrsv->v6.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->v6, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->v6); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->v6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->v6, &pptrsv->v6.bta, &pptrsv->v6.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->v6, &pptrsv->v6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->v6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->v6, &pptrsv->v6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->v6, &pptrsv->v6.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->v6, &pptrsv->v6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->v6); exec_plugins(&pptrsv->v6, req); break; case PM_FTYPE_VLAN_IPV4: pptrsv->vlan4.f_header = pptrs->f_header; pptrsv->vlan4.f_data = pptrs->f_data; pptrsv->vlan4.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->vlan4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac_vlan(&pptrsv->vlan4); reset_ip4(&pptrsv->vlan4); if (direction == DIRECTION_IN) { memcpy(pptrsv->vlan4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->vlan4.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); memcpy(pptrsv->vlan4.vlan_ptr, pkt+tpl->tpl[NF9_IN_VLAN].off, tpl->tpl[NF9_IN_VLAN].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->vlan4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->vlan4.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); memcpy(pptrsv->vlan4.vlan_ptr, pkt+tpl->tpl[NF9_OUT_VLAN].off, tpl->tpl[NF9_OUT_VLAN].len); } ((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_src, pkt+tpl->tpl[NF9_IPV4_SRC_ADDR].off, tpl->tpl[NF9_IPV4_SRC_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_dst, pkt+tpl->tpl[NF9_IPV4_DST_ADDR].off, tpl->tpl[NF9_IPV4_DST_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_p, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_tos, pkt+tpl->tpl[NF9_SRC_TOS].off, tpl->tpl[NF9_SRC_TOS].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlan4.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlan4.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->vlan4.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->vlan4.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->vlan4.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->vlan4.lm_method_src = NF_NET_KEEP; pptrsv->vlan4.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->vlan4.l4_proto = 0; memcpy(&pptrsv->vlan4.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->vlan4, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->vlan4); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlan4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlan4, &pptrsv->vlan4.bta, &pptrsv->vlan4.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlan4, &pptrsv->vlan4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlan4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlan4, &pptrsv->vlan4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlan4, &pptrsv->vlan4.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlan4, &pptrsv->vlan4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlan4); exec_plugins(&pptrsv->vlan4, req); break; case PM_FTYPE_VLAN_IPV6: pptrsv->vlan6.f_header = pptrs->f_header; pptrsv->vlan6.f_data = pptrs->f_data; pptrsv->vlan6.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->vlan6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac_vlan(&pptrsv->vlan6); reset_ip6(&pptrsv->vlan6); if (direction == DIRECTION_IN) { memcpy(pptrsv->vlan6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->vlan6.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); memcpy(pptrsv->vlan6.vlan_ptr, pkt+tpl->tpl[NF9_IN_VLAN].off, tpl->tpl[NF9_IN_VLAN].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->vlan6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->vlan6.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); memcpy(pptrsv->vlan6.vlan_ptr, pkt+tpl->tpl[NF9_OUT_VLAN].off, tpl->tpl[NF9_OUT_VLAN].len); } ((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_src, pkt+tpl->tpl[NF9_IPV6_SRC_ADDR].off, tpl->tpl[NF9_IPV6_SRC_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_dst, pkt+tpl->tpl[NF9_IPV6_DST_ADDR].off, tpl->tpl[NF9_IPV6_DST_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_nxt, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->vlan6.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlan6.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->vlan6.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->vlan6.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->vlan6.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->vlan6.lm_method_src = NF_NET_KEEP; pptrsv->vlan6.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->vlan6.l4_proto = 0; memcpy(&pptrsv->vlan6.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->vlan6, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->vlan6); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlan6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlan6, &pptrsv->vlan6.bta, &pptrsv->vlan6.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlan6, &pptrsv->vlan6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlan6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlan6, &pptrsv->vlan6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlan6, &pptrsv->vlan6.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlan6, &pptrsv->vlan6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlan6); exec_plugins(&pptrsv->vlan6, req); break; case PM_FTYPE_MPLS_IPV4: pptrsv->mpls4.f_header = pptrs->f_header; pptrsv->mpls4.f_data = pptrs->f_data; pptrsv->mpls4.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->mpls4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->mpls4.mpls_ptr; u_int32_t idx; /* XXX: fix caplen */ reset_mac(&pptrsv->mpls4); if (direction == DIRECTION_IN) { memcpy(pptrsv->mpls4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->mpls4.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->mpls4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->mpls4.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); } for (idx = NF9_MPLS_LABEL_1; idx <= NF9_MPLS_LABEL_10 && tpl->tpl[idx].len; idx++, ptr += 4) { memset(ptr, 0, 4); memcpy(ptr, pkt+tpl->tpl[idx].off, tpl->tpl[idx].len); } stick_bosbit(ptr-4); pptrsv->mpls4.iph_ptr = ptr; pptrsv->mpls4.tlh_ptr = ptr + IP4HdrSz; reset_ip4(&pptrsv->mpls4); ((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_src, pkt+tpl->tpl[NF9_IPV4_SRC_ADDR].off, tpl->tpl[NF9_IPV4_SRC_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_dst, pkt+tpl->tpl[NF9_IPV4_DST_ADDR].off, tpl->tpl[NF9_IPV4_DST_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_p, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_tos, pkt+tpl->tpl[NF9_SRC_TOS].off, tpl->tpl[NF9_SRC_TOS].len); memcpy(&((struct pm_tlhdr *)pptrsv->mpls4.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->mpls4.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->mpls4.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->mpls4.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->mpls4.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->mpls4.lm_method_src = NF_NET_KEEP; pptrsv->mpls4.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->mpls4.l4_proto = 0; memcpy(&pptrsv->mpls4.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->mpls4, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->mpls4); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->mpls4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->mpls4, &pptrsv->mpls4.bta, &pptrsv->mpls4.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->mpls4, &pptrsv->mpls4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->mpls4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->mpls4, &pptrsv->mpls4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->mpls4, &pptrsv->mpls4.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->mpls4, &pptrsv->mpls4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->mpls4); exec_plugins(&pptrsv->mpls4, req); break; case PM_FTYPE_MPLS_IPV6: pptrsv->mpls6.f_header = pptrs->f_header; pptrsv->mpls6.f_data = pptrs->f_data; pptrsv->mpls6.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->mpls6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->mpls6.mpls_ptr; u_int32_t idx; /* XXX: fix caplen */ reset_mac(&pptrsv->mpls6); if (direction == DIRECTION_IN) { memcpy(pptrsv->mpls6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->mpls6.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->mpls6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->mpls6.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); } for (idx = NF9_MPLS_LABEL_1; idx <= NF9_MPLS_LABEL_10 && tpl->tpl[idx].len; idx++, ptr += 4) { memset(ptr, 0, 4); memcpy(ptr, pkt+tpl->tpl[idx].off, tpl->tpl[idx].len); } stick_bosbit(ptr-4); pptrsv->mpls6.iph_ptr = ptr; pptrsv->mpls6.tlh_ptr = ptr + IP6HdrSz; reset_ip6(&pptrsv->mpls6); ((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_src, pkt+tpl->tpl[NF9_IPV6_SRC_ADDR].off, tpl->tpl[NF9_IPV6_SRC_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_dst, pkt+tpl->tpl[NF9_IPV6_DST_ADDR].off, tpl->tpl[NF9_IPV6_DST_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_nxt, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->mpls6.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->mpls6.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->mpls6.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->mpls6.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->mpls6.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->mpls6.lm_method_src = NF_NET_KEEP; pptrsv->mpls6.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->mpls6.l4_proto = 0; memcpy(&pptrsv->mpls6.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->mpls6, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->mpls6); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->mpls6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->mpls6, &pptrsv->mpls6.bta, &pptrsv->mpls6.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->mpls6, &pptrsv->mpls6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->mpls6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->mpls6, &pptrsv->mpls6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->mpls6, &pptrsv->mpls6.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->mpls6, &pptrsv->mpls6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->mpls6); exec_plugins(&pptrsv->mpls6, req); break; case PM_FTYPE_VLAN_MPLS_IPV4: pptrsv->vlanmpls4.f_header = pptrs->f_header; pptrsv->vlanmpls4.f_data = pptrs->f_data; pptrsv->vlanmpls4.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->vlanmpls4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->vlanmpls4.mpls_ptr; u_int32_t idx; /* XXX: fix caplen */ reset_mac_vlan(&pptrsv->vlanmpls4); if (direction == DIRECTION_IN) { memcpy(pptrsv->vlanmpls4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->vlanmpls4.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); memcpy(pptrsv->vlanmpls4.vlan_ptr, pkt+tpl->tpl[NF9_IN_VLAN].off, tpl->tpl[NF9_IN_VLAN].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->vlanmpls4.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->vlanmpls4.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); memcpy(pptrsv->vlanmpls4.vlan_ptr, pkt+tpl->tpl[NF9_OUT_VLAN].off, tpl->tpl[NF9_OUT_VLAN].len); } for (idx = NF9_MPLS_LABEL_1; idx <= NF9_MPLS_LABEL_10 && tpl->tpl[idx].len; idx++, ptr += 4) { memset(ptr, 0, 4); memcpy(ptr, pkt+tpl->tpl[idx].off, tpl->tpl[idx].len); } stick_bosbit(ptr-4); pptrsv->vlanmpls4.iph_ptr = ptr; pptrsv->vlanmpls4.tlh_ptr = ptr + IP4HdrSz; reset_ip4(&pptrsv->vlanmpls4); ((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_src, pkt+tpl->tpl[NF9_IPV4_SRC_ADDR].off, tpl->tpl[NF9_IPV4_SRC_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_dst, pkt+tpl->tpl[NF9_IPV4_DST_ADDR].off, tpl->tpl[NF9_IPV4_DST_ADDR].len); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_p, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_tos, pkt+tpl->tpl[NF9_SRC_TOS].off, tpl->tpl[NF9_SRC_TOS].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls4.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls4.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->vlanmpls4.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->vlanmpls4.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->vlanmpls4.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->vlanmpls4.lm_method_src = NF_NET_KEEP; pptrsv->vlanmpls4.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->vlanmpls4.l4_proto = 0; memcpy(&pptrsv->vlanmpls4.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->vlanmpls4, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->vlanmpls4); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlanmpls4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bta, &pptrsv->vlanmpls4.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlanmpls4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlanmpls4); exec_plugins(&pptrsv->vlanmpls4, req); break; case PM_FTYPE_VLAN_MPLS_IPV6: pptrsv->vlanmpls6.f_header = pptrs->f_header; pptrsv->vlanmpls6.f_data = pptrs->f_data; pptrsv->vlanmpls6.f_tpl = pptrs->f_tpl; memcpy(&pptrsv->vlanmpls6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->vlanmpls6.mpls_ptr; u_int32_t idx; /* XXX: fix caplen */ reset_mac_vlan(&pptrsv->vlanmpls6); if (direction == DIRECTION_IN) { memcpy(pptrsv->vlanmpls6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrsv->vlanmpls6.mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); memcpy(pptrsv->vlanmpls6.vlan_ptr, pkt+tpl->tpl[NF9_IN_VLAN].off, tpl->tpl[NF9_IN_VLAN].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrsv->vlanmpls6.mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrsv->vlanmpls6.mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); memcpy(pptrsv->vlanmpls6.vlan_ptr, pkt+tpl->tpl[NF9_OUT_VLAN].off, tpl->tpl[NF9_OUT_VLAN].len); } for (idx = NF9_MPLS_LABEL_1; idx <= NF9_MPLS_LABEL_10 && tpl->tpl[idx].len; idx++, ptr += 4) { memset(ptr, 0, 4); memcpy(ptr, pkt+tpl->tpl[idx].off, tpl->tpl[idx].len); } stick_bosbit(ptr-4); pptrsv->vlanmpls6.iph_ptr = ptr; pptrsv->vlanmpls6.tlh_ptr = ptr + IP6HdrSz; reset_ip6(&pptrsv->vlanmpls6); ((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_src, pkt+tpl->tpl[NF9_IPV6_SRC_ADDR].off, tpl->tpl[NF9_IPV6_SRC_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_dst, pkt+tpl->tpl[NF9_IPV6_DST_ADDR].off, tpl->tpl[NF9_IPV6_DST_ADDR].len); memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_nxt, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls6.tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls6.tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrsv->vlanmpls6.tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrsv->vlanmpls6.lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrsv->vlanmpls6.lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrsv->vlanmpls6.lm_method_src = NF_NET_KEEP; pptrsv->vlanmpls6.lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrsv->vlanmpls6.l4_proto = 0; memcpy(&pptrsv->vlanmpls6.l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); NF_process_classifiers(pptrs, &pptrsv->vlanmpls6, pkt, tpl); NF_mpls_vpn_rd_fromie90(&pptrsv->vlanmpls6); if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlanmpls6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bta, &pptrsv->vlanmpls6.bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlanmpls6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlanmpls6); exec_plugins(&pptrsv->vlanmpls6, req); break; case NF9_FTYPE_NAT_EVENT: /* XXX: aggregate_filter & NAT64 case */ if (req->bpf_filter) { reset_mac(pptrs); reset_ip4(pptrs); if (direction == DIRECTION_IN) { memcpy(pptrs->mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_IN_SRC_MAC].off, tpl->tpl[NF9_IN_SRC_MAC].len); memcpy(pptrs->mac_ptr, pkt+tpl->tpl[NF9_IN_DST_MAC].off, tpl->tpl[NF9_IN_DST_MAC].len); } else if (direction == DIRECTION_OUT) { memcpy(pptrs->mac_ptr+ETH_ADDR_LEN, pkt+tpl->tpl[NF9_OUT_SRC_MAC].off, tpl->tpl[NF9_OUT_SRC_MAC].len); memcpy(pptrs->mac_ptr, pkt+tpl->tpl[NF9_OUT_DST_MAC].off, tpl->tpl[NF9_OUT_DST_MAC].len); } ((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, pkt+tpl->tpl[NF9_IPV4_SRC_ADDR].off, tpl->tpl[NF9_IPV4_SRC_ADDR].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, pkt+tpl->tpl[NF9_IPV4_DST_ADDR].off, tpl->tpl[NF9_IPV4_DST_ADDR].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_p, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_tos, pkt+tpl->tpl[NF9_SRC_TOS].off, tpl->tpl[NF9_SRC_TOS].len); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->src_port, pkt+tpl->tpl[NF9_L4_SRC_PORT].off, tpl->tpl[NF9_L4_SRC_PORT].len); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port, pkt+tpl->tpl[NF9_L4_DST_PORT].off, tpl->tpl[NF9_L4_DST_PORT].len); memcpy(&((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags, pkt+tpl->tpl[NF9_TCP_FLAGS].off, tpl->tpl[NF9_TCP_FLAGS].len); } memcpy(&pptrs->lm_mask_src, pkt+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); memcpy(&pptrs->lm_mask_dst, pkt+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); pptrs->lm_method_src = NF_NET_KEEP; pptrs->lm_method_dst = NF_NET_KEEP; /* Let's copy some relevant field */ pptrs->l4_proto = 0; memcpy(&pptrs->l4_proto, pkt+tpl->tpl[NF9_L4_PROTOCOL].off, tpl->tpl[NF9_L4_PROTOCOL].len); if (config.nfacctd_isis) isis_srcdst_lookup(pptrs); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, pptrs, &pptrs->bta, &pptrs->bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, pptrs, &pptrs->bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(pptrs, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, pptrs, &pptrs->bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, pptrs, &pptrs->blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, pptrs, &pptrs->bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(pptrs); exec_plugins(pptrs, req); break; case NF9_FTYPE_DLFS: dummy_packet_ptr = pptrs->packet_ptr; nfv9_datalink_frame_section_handler(pptrs); if (config.nfacctd_isis) isis_srcdst_lookup(pptrs); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, pptrs, &pptrs->bta, &pptrs->bta2); if (config.nfacctd_flow_to_rd_map) NF_find_id((struct id_table *)pptrs->bitr_table, pptrs, &pptrs->bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(pptrs, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) NF_find_id((struct id_table *)pptrs->bpas_table, pptrs, &pptrs->bpas, NULL); if (config.bgp_daemon_src_local_pref_map) NF_find_id((struct id_table *)pptrs->blp_table, pptrs, &pptrs->blp, NULL); if (config.bgp_daemon_src_med_map) NF_find_id((struct id_table *)pptrs->bmed_table, pptrs, &pptrs->bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(pptrs); exec_plugins(pptrs, req); reset_dummy_v4(pptrs, dummy_packet_ptr); break; default: break; } finalize_record: pkt += tpl->len; flowoff += tpl->len; /* we have to reset; let's not do to zero to short-circuit the case of the last record in a flowset; we can save a round through resolve_vlen_template() */ if (tpl->vlen) tpl->len = 1; FlowSeqInc++; } /* last pre-flight check for the subsequent subtraction */ if (flowoff > flowsetlen) { notify_malf_packet(LOG_INFO, "INFO", "aborting malformed Data element (incomplete NetFlow v9/IPFIX packet)", (struct sockaddr *) pptrsv->v4.f_agent, FlowSeq); xflow_status_table.tot_bad_datagrams++; return; } pkt += (flowsetlen-flowoff); /* handling padding */ off += flowsetlen; } } else { /* unsupported flowset */ if (off+flowsetlen > len) { Log(LOG_DEBUG, "DEBUG ( %s/core ): unable to read unsupported Flowset (ID: '%u').\n", config.name, fid); return; } pkt += flowsetlen; off += flowsetlen; } if ((version == 9 && (flowsetCount + 1) < flowsetNo && off < len) || (version == 10 && off < len)) { flowsetCount++; goto process_flowset; } /* Set IPFIX Sequence number increment */ if (version == 10) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrsv->v4.f_status; if (entry) entry->inc = FlowSeqInc; } } void process_raw_packet(unsigned char *pkt, u_int16_t len, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req) { struct packet_ptrs *pptrs = &pptrsv->v4; u_int16_t nfv; /* basic length check against longest NetFlow header */ if (len < NfHdrV5Sz) { notify_malf_packet(LOG_INFO, "INFO", "discarding short NetFlow packet", (struct sockaddr *) pptrs->f_agent, 0); xflow_status_table.tot_bad_datagrams++; return; } if (req->ptm_c.exec_ptm_dissect) nfv = ((struct struct_header_v5 *)pkt)->version; else nfv = ntohs(((struct struct_header_v5 *)pkt)->version); if (nfv != 5 && nfv != 9 && nfv != 10) { if (!config.nfacctd_disable_checks) { notify_malf_packet(LOG_INFO, "INFO", "discarding unknown NetFlow packet", (struct sockaddr *) pptrs->f_agent, 0); xflow_status_table.tot_bad_datagrams++; } return; } pptrs->f_header = pkt; switch (nfv) { case 5: pptrs->seqno = ntohl(((struct struct_header_v5 *)pkt)->flow_sequence); if (!req->ptm_c.exec_ptm_dissect) nfv5_check_status(pptrs); /* stats collection */ break; case 9: pptrs->seqno = ntohl(((struct struct_header_v9 *)pkt)->flow_sequence); if (!req->ptm_c.exec_ptm_dissect) { u_int32_t SourceId = ntohl(((struct struct_header_v9 *)pkt)->source_id); nfv9_check_status(pptrs, SourceId, 0, pptrs->seqno, TRUE); /* stats collection */ } break; case 10: pptrs->seqno = ntohl(((struct struct_header_ipfix *)pkt)->flow_sequence); if (!req->ptm_c.exec_ptm_dissect) { u_int32_t SourceId = ntohl(((struct struct_header_ipfix *)pkt)->source_id); nfv9_check_status(pptrs, SourceId, 0, pptrs->seqno, TRUE); /* stats collection */ } break; default: pptrs->seqno = 0; break; } if (!req->ptm_c.exec_ptm_dissect && config.debug) { sa_to_addr((struct sockaddr *)pptrs->f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received NetFlow/IPFIX packet from [%s:%u] version [%u] seqno [%u]\n", config.name, debug_agent_addr, debug_agent_port, nfv, pptrs->seqno); } if (req->ptm_c.exec_ptm_dissect) { struct NF_dissect tee_dissect; memset(&tee_dissect, 0, sizeof(tee_dissect)); pptrsv->v4.tee_dissect = (char *) &tee_dissect; req->ptm_c.exec_ptm_res = TRUE; switch(nfv) { case 5: process_v5_packet(pkt, len, &pptrsv->v4, req, nfv, &tee_dissect); break; /* NetFlow v9 + IPFIX */ case 9: case 10: process_v9_packet(pkt, len, pptrsv, req, nfv, &tee_dissect, NULL); break; default: break; } } /* If dissecting, we also send the full original packet */ if (req->ptm_c.exec_ptm_dissect) ((struct struct_header_v5 *)pkt)->version = htons(((struct struct_header_v5 *)pkt)->version); pptrs->tee_dissect = NULL; pptrs->f_data = NULL; pptrs->f_tpl = NULL; req->ptm_c.exec_ptm_res = FALSE; exec_plugins(pptrs, req); } void NF_compute_once() { struct pkt_data dummy; CounterSz = sizeof(dummy.pkt_len); PdataSz = sizeof(struct pkt_data); PpayloadSz = sizeof(struct pkt_payload); PmsgSz = sizeof(struct pkt_msg); PextrasSz = sizeof(struct pkt_extras); PbgpSz = sizeof(struct pkt_bgp_primitives); PlbgpSz = sizeof(struct pkt_legacy_bgp_primitives); PnatSz = sizeof(struct pkt_nat_primitives); PmplsSz = sizeof(struct pkt_mpls_primitives); PtunSz = sizeof(struct pkt_tunnel_primitives); PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); ChBufHdrSz = sizeof(struct ch_buf_hdr); CharPtrSz = sizeof(char *); NfHdrV5Sz = sizeof(struct struct_header_v5); NfHdrV9Sz = sizeof(struct struct_header_v9); NfDataHdrV9Sz = sizeof(struct data_hdr_v9); NfTplHdrV9Sz = sizeof(struct template_hdr_v9); NfTplFieldV9Sz = sizeof(struct template_field_v9); NfOptTplHdrV9Sz = sizeof(struct options_template_hdr_v9); NfDataV5Sz = sizeof(struct struct_export_v5); IP4HdrSz = sizeof(struct pm_iphdr); IP4TlSz = sizeof(struct pm_iphdr)+sizeof(struct pm_tlhdr); PptrsSz = sizeof(struct packet_ptrs); HostAddrSz = sizeof(struct host_addr); UDPHdrSz = sizeof(struct pm_udphdr); IpFixHdrSz = sizeof(struct struct_header_ipfix); IP6HdrSz = sizeof(struct ip6_hdr); IP6AddrSz = sizeof(struct in6_addr); IP6TlSz = sizeof(struct ip6_hdr)+sizeof(struct pm_tlhdr); } void NF_evaluate_flow_type(struct flow_chars *flow_type, struct template_cache_entry *tpl, struct packet_ptrs *pptrs) { u_int8_t ret = FALSE; u_int8_t have_ip_proto = FALSE; memset(flow_type, 0, sizeof(struct flow_chars)); /* first round: event vs traffic */ if (!tpl->tpl[NF9_IN_BYTES].len && !tpl->tpl[NF9_OUT_BYTES].len && !tpl->tpl[NF9_FLOW_BYTES].len && !tpl->tpl[NF9_INITIATOR_OCTETS].len && !tpl->tpl[NF9_RESPONDER_OCTETS].len && /* packets? && */ !tpl->tpl[NF9_DATALINK_FRAME_SECTION].len && !tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len && !tpl->tpl[NF9_LAYER2OCTETDELTACOUNT].len) { ret = NF9_FTYPE_EVENT; } else { if ((tpl->tpl[NF9_IN_VLAN].len && *(pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off) > 0) || (tpl->tpl[NF9_OUT_VLAN].len && *(pptrs->f_data+tpl->tpl[NF9_OUT_VLAN].off) > 0)) { ret += PM_FTYPE_VLAN; } if (tpl->tpl[NF9_MPLS_LABEL_1].len /* check: value > 0 ? */) { ret += PM_FTYPE_MPLS; } /* Explicit IP protocol definition first; a bit of heuristics as fallback */ if (tpl->tpl[NF9_IP_PROTOCOL_VERSION].len) { if (*(pptrs->f_data+tpl->tpl[NF9_IP_PROTOCOL_VERSION].off) == 4) { ret += PM_FTYPE_IPV4; have_ip_proto = TRUE; } else if (*(pptrs->f_data+tpl->tpl[NF9_IP_PROTOCOL_VERSION].off) == 6) { ret += PM_FTYPE_IPV6; have_ip_proto = TRUE; } } if (!have_ip_proto) { /* If we have both v4 and v6 as part of the same flow, let's run the cheapest check possible to try to determine which one is non-zero */ if ((tpl->tpl[NF9_IPV4_SRC_ADDR].len || tpl->tpl[NF9_IPV4_DST_ADDR].len) && (tpl->tpl[NF9_IPV6_SRC_ADDR].len || tpl->tpl[NF9_IPV6_DST_ADDR].len)) { if (*(pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_ADDR].off) != 0) { ret += PM_FTYPE_IPV4; have_ip_proto = TRUE; } else { ret += PM_FTYPE_IPV6; have_ip_proto = TRUE; } } else if (tpl->tpl[NF9_IPV4_SRC_ADDR].len || tpl->tpl[NF9_IPV4_DST_ADDR].len) { ret += PM_FTYPE_IPV4; have_ip_proto = TRUE; } else if (tpl->tpl[NF9_IPV6_SRC_ADDR].len || tpl->tpl[NF9_IPV6_DST_ADDR].len) { ret += PM_FTYPE_IPV6; have_ip_proto = TRUE; } } if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { ret = NF9_FTYPE_DLFS; } if (tpl->tpl[NF9_INITIATOR_OCTETS].len && tpl->tpl[NF9_RESPONDER_OCTETS].len) { flow_type->is_bi = TRUE; } } /* second round: overrides */ /* NetFlow Event Logging (NEL): generic NAT event support */ if (tpl->tpl[NF9_NAT_EVENT].len) ret = NF9_FTYPE_NAT_EVENT; /* NetFlow/IPFIX option final override */ if (tpl->template_type == 1) ret = NF9_FTYPE_OPTION; flow_type->traffic_type = ret; } u_int16_t NF_evaluate_direction(struct template_cache_entry *tpl, struct packet_ptrs *pptrs) { u_int16_t ret = DIRECTION_IN; if (tpl->tpl[NF9_DIRECTION].len && *(pptrs->f_data+tpl->tpl[NF9_DIRECTION].off) == 1) ret = DIRECTION_OUT; return ret; } void reset_mac(struct packet_ptrs *pptrs) { memset(pptrs->mac_ptr, 0, 2*ETH_ADDR_LEN); } void reset_mac_vlan(struct packet_ptrs *pptrs) { memset(pptrs->mac_ptr, 0, 2*ETH_ADDR_LEN); memset(pptrs->vlan_ptr, 0, 2); } void reset_ip4(struct packet_ptrs *pptrs) { memset(pptrs->iph_ptr, 0, IP4TlSz); Assign8(((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl, 5); } void reset_ip6(struct packet_ptrs *pptrs) { memset(pptrs->iph_ptr, 0, IP6TlSz); Assign16(((struct ip6_hdr *)pptrs->iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_hlim = 64; } void reset_dummy_v4(struct packet_ptrs *pptrs, u_char *dummy_packet) { pptrs->packet_ptr = dummy_packet; /* pptrs->pkthdr = dummy_pkthdr; */ Assign16(((struct eth_header *)pptrs->packet_ptr)->ether_type, htons(ETHERTYPE_IP)); pptrs->mac_ptr = (u_char *)((struct eth_header *)pptrs->packet_ptr)->ether_dhost; pptrs->iph_ptr = pptrs->packet_ptr + ETHER_HDRLEN; pptrs->tlh_ptr = pptrs->packet_ptr + ETHER_HDRLEN + sizeof(struct pm_iphdr); Assign8(((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl, 5); pptrs->pkthdr->caplen = 55; pptrs->pkthdr->len = 100; pptrs->l3_proto = ETHERTYPE_IP; } void notify_malf_packet(short int severity, char *severity_str, char *ostr, struct sockaddr *sa, u_int32_t seq) { struct host_addr a; char errstr[SRVBUFLEN]; char agent_addr[50] /* able to fit an IPv6 string aswell */, any[] = "0.0.0.0"; u_int16_t agent_port; sa_to_addr((struct sockaddr *)sa, &a, &agent_port); addr_to_str(agent_addr, &a); if (seq) snprintf(errstr, SRVBUFLEN, "%s ( %s/core ): %s: nfacctd=%s:%u agent=%s:%u seq=%u\n", severity_str, config.name, ostr, ((config.nfacctd_ip) ? config.nfacctd_ip : any), collector_port, agent_addr, agent_port, seq); else snprintf(errstr, SRVBUFLEN, "%s ( %s/core ): %s: nfacctd=%s:%u agent=%s:%u\n", severity_str, config.name, ostr, ((config.nfacctd_ip) ? config.nfacctd_ip : any), collector_port, agent_addr, agent_port); Log(severity, "%s", errstr); } int NF_find_id(struct id_table *t, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status; struct sockaddr *sa = NULL; u_char *saved_f_agent = NULL; int x, begin = 0, end = 0; pm_id_t ret = 0; if (!t) return 0; /* if NF9_EXPORTER_IPV[46]_ADDRESS from NetFlow v9/IPFIX options, use it */ if (entry && entry->exp_sa.sa_family) { saved_f_agent = pptrs->f_agent; pptrs->f_agent = (u_char *) &entry->exp_sa; } sa = (struct sockaddr *) pptrs->f_agent; /* The id_table is shared between by IPv4 and IPv6 NetFlow agents. IPv4 ones are in the lower part (0..x), IPv6 ones are in the upper part (x+1..end) */ pretag_init_vars(pptrs, t); if (tag) *tag = 0; if (tag2) *tag2 = 0; if (pptrs) { pptrs->have_tag = FALSE; pptrs->have_tag2 = FALSE; } /* If we have any index defined, let's use it */ if (config.maps_index && pretag_index_have_one(t)) { struct id_entry *index_results[ID_TABLE_INDEX_RESULTS]; u_int32_t iterator, num_results; num_results = pretag_index_lookup(t, pptrs, index_results, ID_TABLE_INDEX_RESULTS); for (iterator = 0; index_results[iterator] && iterator < num_results; iterator++) { ret = pretag_entry_process(index_results[iterator], pptrs, tag, tag2); if (!(ret & PRETAG_MAP_RCODE_JEQ)) goto exit_lane; } /* done */ goto exit_lane; } if (sa->sa_family == AF_INET) { begin = 0; end = t->ipv4_num; } else if (sa->sa_family == AF_INET6) { begin = t->num-t->ipv6_num; end = t->num; } for (x = begin; x < end; x++) { if (host_addr_mask_sa_cmp(&t->e[x].key.agent_ip.a, &t->e[x].key.agent_mask, sa) == 0) { ret = pretag_entry_process(&t->e[x], pptrs, tag, tag2); if (!ret || ret > TRUE) { if (ret & PRETAG_MAP_RCODE_JEQ) { x = t->e[x].jeq.ptr->pos; x--; // yes, it will be automagically incremented by the for() cycle } else break; } } } exit_lane: if (entry && entry->exp_sa.sa_family) pptrs->f_agent = saved_f_agent; return ret; } struct xflow_status_entry *nfv5_check_status(struct packet_ptrs *pptrs) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent; u_int32_t aux1 = (hdr->engine_id << 8 | hdr->engine_type); int hash = hash_status_table(aux1, sa, XFLOW_STATUS_TABLE_SZ); struct xflow_status_entry *entry = NULL; if (hash >= 0) { entry = search_status_table(&xflow_status_table, sa, aux1, 0, hash, XFLOW_STATUS_TABLE_MAX_ENTRIES); if (entry) { update_status_table(entry, ntohl(hdr->flow_sequence), pptrs->f_len); entry->inc = ntohs(hdr->count); } } return entry; } struct xflow_status_entry *nfv9_check_status(struct packet_ptrs *pptrs, u_int32_t sid, u_int32_t flags, u_int32_t seq, u_int8_t update) { struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent; int hash = hash_status_table(sid, sa, XFLOW_STATUS_TABLE_SZ); struct xflow_status_entry *entry = NULL; if (hash >= 0) { entry = search_status_table(&xflow_status_table, sa, sid, flags, hash, XFLOW_STATUS_TABLE_MAX_ENTRIES); if (entry && update) { update_status_table(entry, seq, pptrs->f_len); entry->inc = 1; } } return entry; } void NF_process_classifiers(struct packet_ptrs *pptrs_main, struct packet_ptrs *pptrs, unsigned char *pkt, struct template_cache_entry *tpl) { if (tpl->tpl[NF9_APPLICATION_ID].len == 2 || tpl->tpl[NF9_APPLICATION_ID].len == 3 || tpl->tpl[NF9_APPLICATION_ID].len == 5) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs_main->f_status; struct xflow_status_entry *gentry = (struct xflow_status_entry *) pptrs_main->f_status_g; pm_class_t class_id = 0; memcpy(&class_id, (pkt + tpl->tpl[NF9_APPLICATION_ID].off + 1), (tpl->tpl[NF9_APPLICATION_ID].len - 1)); if (entry) pptrs->class = NF_evaluate_classifiers(entry->class, &class_id, gentry); } } pm_class_t NF_evaluate_classifiers(struct xflow_status_entry_class *entry, pm_class_t *class_id, struct xflow_status_entry *gentry) { struct xflow_status_entry_class *centry; /* Try #1: let's see if we have a matching class for the given SourceId/ObservedDomainId */ centry = search_class_id_status_table(entry, *class_id); if (centry) { return centry->class_int_id; } /* Try #2: let's chance if we have a global option */ if (gentry) { centry = search_class_id_status_table(gentry->class, *class_id); if (centry) { return centry->class_int_id; } } return 0; } void nfv9_datalink_frame_section_handler(struct packet_ptrs *pptrs) { struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct utpl_field *utpl = NULL; u_int16_t frame_type = NF9_DL_F_TYPE_UNKNOWN, t16, idx; /* cleanups */ reset_index_pkt_ptrs(pptrs); pptrs->packet_ptr = pptrs->mac_ptr = pptrs->vlan_ptr = pptrs->mpls_ptr = NULL; pptrs->iph_ptr = pptrs->tlh_ptr = pptrs->payload_ptr = NULL; pptrs->l3_proto = pptrs->l4_proto = FALSE; #if defined (WITH_NDPI) memset(&pptrs->ndpi_class, 0, sizeof(pm_class2_t)); #endif if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_DATALINK_FRAME_TYPE, FALSE))) { memcpy(&t16, pptrs->f_data+utpl->off, MIN(utpl->len, 2)); frame_type = ntohs(t16); } /* XXX: in case of no NF9_DATALINK_FRAME_TYPE, let's assume Ethernet */ else frame_type = NF9_DL_F_TYPE_ETHERNET; if (tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { idx = NF9_LAYER2_PKT_SECTION_DATA; } else { idx = NF9_DATALINK_FRAME_SECTION; } if (tpl->tpl[idx].len) { pptrs->pkthdr->caplen = tpl->tpl[idx].len; pptrs->packet_ptr = (u_char *) pptrs->f_data+tpl->tpl[idx].off; if (frame_type == NF9_DL_F_TYPE_ETHERNET) { eth_handler(pptrs->pkthdr, pptrs); if (pptrs->iph_ptr) { if ((*pptrs->l3_handler)(pptrs)) { #if defined (WITH_NDPI) if (config.classifier_ndpi && pm_ndpi_wfl) { pptrs->ndpi_class = pm_ndpi_workflow_process_packet(pm_ndpi_wfl, pptrs); } #endif set_index_pkt_ptrs(pptrs); } } } } } #ifdef WITH_KAFKA void NF_init_kafka_host(void *kh) { struct p_kafka_host *kafka_host = kh; p_kafka_init_host(kafka_host, config.nfacctd_kafka_config_file); p_kafka_connect_to_consume(kafka_host); p_kafka_set_broker(kafka_host, config.nfacctd_kafka_broker_host, config.nfacctd_kafka_broker_port); p_kafka_set_topic(kafka_host, config.nfacctd_kafka_topic); p_kafka_set_content_type(kafka_host, PM_KAFKA_CNT_TYPE_BIN); p_kafka_manage_consumer(kafka_host, TRUE); } #endif #ifdef WITH_ZMQ void NF_init_zmq_host(void *zh, int *pipe_fd) { struct p_zmq_host *zmq_host = zh; char log_id[SHORTBUFLEN]; p_zmq_init_pull(zmq_host); snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_zmq_set_log_id(zmq_host, log_id); p_zmq_set_address(zmq_host, config.nfacctd_zmq_address); p_zmq_set_hwm(zmq_host, PM_ZMQ_DEFAULT_FLOW_HWM); p_zmq_pull_setup(zmq_host); p_zmq_set_retry_timeout(zmq_host, PM_ZMQ_DEFAULT_RETRY); if (pipe_fd) (*pipe_fd) = p_zmq_get_fd(zmq_host); } #endif void NF_mpls_vpn_rd_fromie90(struct packet_ptrs *pptrs) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_MPLS_VPN_RD].len) { memcpy(&pptrs->bitr, pptrs->f_data+tpl->tpl[NF9_MPLS_VPN_RD].off, MIN(tpl->tpl[NF9_MPLS_VPN_RD].len, 8)); bgp_rd_ntoh((rd_t *)&pptrs->bitr); bgp_rd_origin_set((rd_t *)&pptrs->bitr, RD_ORIGIN_FLOW); } break; default: break; } } pmacct-1.7.8/src/pmsearch.h0000644000175000017500000000771014354105275014561 0ustar paolopaolo/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is based on the GNU C Library and contains: * Declarations for System V style searching functions * Declarations for hash hash table management functions The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #ifndef PMSEARCH_H #define PMSEARCH_H /* includes */ #include #include /* definitions */ typedef struct pm_node_t { /* Callers expect this to be the first element in the structure - do not move! */ const void *key; uintptr_t left_node; /* Includes whether the node is red in low-bit. */ uintptr_t right_node; } *pm_node; #define RED(N) (pm_node)((N)->left_node & ((uintptr_t) 0x1)) #define SETRED(N) (N)->left_node |= ((uintptr_t) 0x1) #define SETBLACK(N) (N)->left_node &= ~((uintptr_t) 0x1) #define SETNODEPTR(NP,P) (*NP) = (pm_node)((((uintptr_t)(*NP)) \ & (uintptr_t) 0x1) | (uintptr_t)(P)) #define LEFT(N) (pm_node)((N)->left_node & ~((uintptr_t) 0x1)) #define LEFTPTR(N) (pm_node *)(&(N)->left_node) #define SETLEFT(N,L) (N)->left_node = (((N)->left_node & (uintptr_t) 0x1) \ | (uintptr_t)(L)) #define RIGHT(N) (pm_node)((N)->right_node) #define RIGHTPTR(N) (pm_node *)(&(N)->right_node) #define SETRIGHT(N,R) (N)->right_node = (uintptr_t)(R) #define DEREFNODEPTR(NP) (pm_node)((uintptr_t)(*(NP)) & ~((uintptr_t) 0x1)) typedef const struct pm_node_t *pm_const_node; /* The tsearch routines are very interesting. They make many assumptions about the compiler. It assumes that the first field in node must be the "key" field, which points to the datum. Everything depends on that. */ typedef enum { preorder, postorder, endorder, leaf } pm_VISIT; typedef int (*pm_compar_fn_t) (const void *, const void *); typedef int (*pm_action_fn_t) (const void *, pm_VISIT, int, void *); typedef void (*pm_free_fn_t) (void *); typedef enum { FIND, INSERT, DELETE } pm_ACTION; typedef struct pm_hentry_t { void *key; unsigned int keylen; void *data; } pm_HENTRY; typedef struct _pm_hentry_t { unsigned int used; pm_HENTRY entry; } _pm_HENTRY; struct pm_htable { _pm_HENTRY *table; unsigned int size; unsigned int filled; }; /* prototypes */ /* Search for an entry matching the given KEY in the tree pointed to by *ROOTP and insert a new element if not found. */ extern void *__pm_tsearch (const void *, void **, pm_compar_fn_t); /* Search for an entry matching the given KEY in the tree pointed to by *ROOTP. If no matching entry is available return NULL. */ extern void *pm_tfind (const void *, void **, pm_compar_fn_t); /* Remove the element matching KEY from the tree pointed to by *ROOTP. */ extern void *pm_tdelete (const void *, void **, pm_compar_fn_t); /* Walk through the whole tree and call the ACTION callback for every node or leaf. */ extern void pm_twalk (const void *, pm_action_fn_t, void *); /* Destroy the whole tree, call FREEFCT for each node or leaf. */ extern void __pm_tdestroy (void *, pm_free_fn_t); extern int pm_hcreate(size_t, struct pm_htable *); extern void pm_hdestroy(struct pm_htable *); extern int pm_hsearch(pm_HENTRY, pm_ACTION, pm_HENTRY **, struct pm_htable *); extern void pm_hmove(struct pm_htable *, struct pm_htable *, struct pm_htable *); extern void __pm_hdelete(_pm_HENTRY *); #endif //PMSEARCH_H pmacct-1.7.8/src/sqlite3_plugin.h0000644000175000017500000000365114354105275015721 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include #include "plugin_common.h" /* prototypes */ void sqlite3_plugin(int, struct configuration *, void *); int SQLI_cache_dbop(struct DBdesc *, struct db_cache *, struct insert_data *); void SQLI_cache_purge(struct db_cache *[], int, struct insert_data *); int SQLI_evaluate_history(int); int SQLI_compose_static_queries(); void SQLI_Lock(struct DBdesc *); void SQLI_Unlock(struct BE_descs *); void SQLI_DB_Connect(struct DBdesc *, char *); void SQLI_DB_Close(struct BE_descs *); void SQLI_create_dyn_table(struct DBdesc *, char *); void SQLI_get_errmsg(struct DBdesc *); void SQLI_create_backend(struct DBdesc *); void SQLI_set_callbacks(struct sqlfunc_cb_registry *); void SQLI_init_default_values(struct insert_data *); void SQLI_sqlite3_get_version(); /* variables */ extern char sqlite3_db[]; extern char sqlite3_table[]; extern char sqlite3_table_v2[]; extern char sqlite3_table_v3[]; extern char sqlite3_table_v4[]; extern char sqlite3_table_v5[]; extern char sqlite3_table_v6[]; extern char sqlite3_table_v7[]; extern char sqlite3_table_v8[]; extern char sqlite3_table_bgp[]; pmacct-1.7.8/src/print_plugin.h0000644000175000017500000000253314354105275015467 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PRINT_PLUGIN_H #define PRINT_PLUGIN_H /* includes */ #include /* prototypes */ extern void print_plugin(int, struct configuration *, void *); extern void P_cache_purge(struct chained_cache *[], int, int); extern void P_write_stats_header_formatted(FILE *, int); extern void P_write_stats_header_csv(FILE *, int); extern void P_fprintf_csv_string(FILE *, struct pkt_vlen_hdr_primitives *, pm_cfgreg_t, char *, char *); /* global variables */ extern int print_output_stdout_header; #endif //PRINT_PLUGIN_H pmacct-1.7.8/src/pmtelemetryd.c0000644000175000017500000002416614354105275015471 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "telemetry/telemetry.h" #include "pmtelemetryd.h" #include "pretag_handlers.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_flow.h" #include "net_aggr.h" /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", PMTELEMETRYD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -L IP address ] [ -u port | -t port ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -L \tBind to the specified IP address\n"); printf(" -u \tListen on the specified UDP port\n"); printf(" -t \tListen on the specified TCP port\n"); #ifdef WITH_ZMQ printf(" -Z \tConnect to the specified ZeroMQ queue address\n"); #endif printf(" -f \tLoad configuration from the specified file\n"); printf(" -D \tDaemonize\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -o \tOutput file to log real-time Streaming Telemetry data\n"); printf(" -O \tOutput file to dump Streaming Telemetry data at regular time intervals\n"); printf(" -i \tInterval, in secs, to write to the dump output file (supplied by -O)\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { struct telemetry_data t_data; struct plugins_list_entry *list; char config_file[SRVBUFLEN]; int logf; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); log_notifications_init(&log_notifications); config.acct_type = ACCT_PMTELE; config.progname = pmtele_globstr; find_id_func = NULL; plugins_list = NULL; errflag = 0; rows = 0; /* needed for pre_tag_map support */ PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_PMTELEMETRYD)) != -1)) { cfg_cmdline[rows] = malloc(SRVBUFLEN); switch (cp) { case 'L': strlcpy(cfg_cmdline[rows], "telemetry_daemon_ip: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'u': strlcpy(cfg_cmdline[rows], "telemetry_daemon_port_udp: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 't': strlcpy(cfg_cmdline[rows], "telemetry_daemon_port_tcp: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Z': strlcpy(cfg_cmdline[rows], "telemetry_daemon_zmq_address: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "telemetry_daemon_msglog_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "telemetry_dump_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'i': strlcpy(cfg_cmdline[rows], "telemetry_dump_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, PMTELEMETRYD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } list = plugins_list; while (list) { list->cfg.acct_type = ACCT_PMTELE; list->cfg.progname = pmtele_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, PMTELEMETRYD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif telemetry_prepare_daemon(&t_data); telemetry_daemon(&t_data); return 0; } pmacct-1.7.8/src/crc32.h0000644000175000017500000001476214354105275013700 0ustar paolopaolo/* * Copyright (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. * * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1. * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way, * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to hight-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly. * The feedback terms table consists of 256, 32-bit entries. Notes: * * 1. The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera- * tions for all combinations of data and CRC register values. * * 2. The CRC accumulation logic is the same for all CRC polynomials, * be they sixteen or thirty-two bits wide. You simply choose the * appropriate table. Alternatively, because the table can be * generated at runtime, you can start by generating the table for * the polynomial in question and use exactly the same "updcrc", * if your application needn't simultaneously handle two CRC * polynomials. (Note, however, that XMODEM is strange.) * * 3. For 16-bit CRCs, the table entries need be only 16 bits wide; * of course, 32-bit entries work OK if the high 16 bits are zero. * * 4. The values must be right-shifted by eight bits by the "updcrc" * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions. */ /* static unsigned int crc_32_tab[] = { // 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU }; */ static inline unsigned int cache_crc32(const unsigned char *buf, unsigned int len) { unsigned int hash = 5381; unsigned int i = 0; for (i = 0; i < len; buf++, i++) { hash = ((hash << 5) + hash) + (*buf); } return hash; } pmacct-1.7.8/src/once.h0000644000175000017500000000302514354105275013676 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ONCE_H_ #define _ONCE_H_ extern u_int32_t PdataSz, ChBufHdrSz, CharPtrSz, CounterSz, HostAddrSz; extern u_int32_t PpayloadSz, PextrasSz, PmsgSz, PvhdrSz, PtLabelTSz; extern u_int32_t PmLabelTSz; extern u_int32_t NfHdrV5Sz, NfHdrV9Sz; extern u_int32_t IpFixHdrSz; extern u_int32_t NfDataHdrV9Sz, NfTplHdrV9Sz, NfOptTplHdrV9Sz; extern u_int32_t NfTplFieldV9Sz; extern u_int32_t NfDataV5Sz; extern u_int32_t IP4HdrSz, IP4TlSz, IP6HdrSz, IP6AddrSz, IP6TlSz; extern u_int32_t MyTLHdrSz, TCPFlagOff; extern u_int32_t SFSampleSz, SFLAddressSz, SFrenormEntrySz; extern u_int32_t PptrsSz, UDPHdrSz, CSSz, MyTCPHdrSz, IpFlowCmnSz; extern u_int16_t PbgpSz, PlbgpSz, PnatSz, PmplsSz, PtunSz; #endif /* _ONCE_H_ */ pmacct-1.7.8/src/plugin_common.h0000644000175000017500000001456714354105275015635 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLUGIN_COMMON_H #define PLUGIN_COMMON_H /* includes */ #include "net_aggr.h" #include "preprocess.h" /* defines */ #define DEFAULT_PLUGIN_COMMON_REFRESH_TIME 60 #define DEFAULT_PLUGIN_COMMON_WRITERS_NO 10 #define DEFAULT_PLUGIN_COMMON_RECV_BUDGET 100 #define AVERAGE_CHAIN_LEN 10 #define PRINT_CACHE_ENTRIES 16411 #define MAX_PTM_LABEL_TOKEN_LEN 128 #define TCP_FLAG_LEN 6 #define FWD_TYPES_STR_LEN 50 #define MAX_MPLS_LABEL_STACK 128 #define PORTS_TABLE_ENTRIES 65536 #define PROTOS_TABLE_ENTRIES 256 #define PM_L4_PORT_OTHERS 0 #define PM_IP_PROTO_OTHERS 255 #define PM_IP_TOS_OTHERS 255 /* cache element states */ #define PRINT_CACHE_FREE 0 #define PRINT_CACHE_COMMITTED 1 #define PRINT_CACHE_INUSE 2 #define PRINT_CACHE_INVALID 3 #define PRINT_CACHE_ERROR 255 /* structures */ #ifndef STRUCT_SCRATCH_AREA #define STRUCT_SCRATCH_AREA struct scratch_area { unsigned char *base; unsigned char *ptr; u_int64_t num; u_int64_t size; struct scratch_area *next; }; #endif #ifndef STRUCT_CHAINED_CACHE #define STRUCT_CHAINED_CACHE struct chained_cache { struct pkt_primitives primitives; pm_counter_t bytes_counter; pm_counter_t packet_counter; pm_counter_t flow_counter; u_int8_t flow_type; u_int8_t tcp_flags; u_int8_t tunnel_tcp_flags; struct pkt_bgp_primitives *pbgp; struct pkt_nat_primitives *pnat; struct pkt_mpls_primitives *pmpls; struct pkt_tunnel_primitives *ptun; u_char *pcust; struct pkt_vlen_hdr_primitives *pvlen; u_int8_t valid; u_int8_t prep_valid; struct timeval basetime; struct pkt_stitching *stitch; struct chained_cache *next; }; #endif #ifndef STRUCT_P_TABLE_RR #define STRUCT_P_TABLE_RR struct p_table_rr { int min; /* unused */ int max; int next; }; #endif #ifndef STRUCT_PTM_LABEL #define STRUCT_PTM_LABEL typedef struct { char key[MAX_PTM_LABEL_TOKEN_LEN]; char value[MAX_PTM_LABEL_TOKEN_LEN]; } __attribute__((packed)) ptm_label; #endif #ifndef STRUCT_TCPFLAGS #define STRUCT_TCPFLAGS typedef struct { char flag[TCP_FLAG_LEN]; } __attribute__((packed)) tcpflag; #endif #ifndef STRUCT_NFACCTD_FWDSTATUS #define STRUCT_NFACCTD_FWDSTATUS typedef struct { unsigned int decimal; char description[FWD_TYPES_STR_LEN]; } __attribute__((packed)) fwd_status; #endif #ifndef STRUCT_PORTS_TABLE #define STRUCT_PORTS_TABLE struct ports_table { u_int8_t table[PORTS_TABLE_ENTRIES]; time_t timestamp; }; #endif #ifndef STRUCT_PROTOS_TABLE #define STRUCT_PROTOS_TABLE struct protos_table { u_int8_t table[PROTOS_TABLE_ENTRIES]; time_t timestamp; }; #endif #include "sql_common.h" /* prototypes */ extern void P_set_signals(); extern void P_init_default_values(); extern void P_config_checks(); extern struct chained_cache *P_cache_attach_new_node(struct chained_cache *); extern unsigned int P_cache_modulo(struct primitives_ptrs *); extern void P_sum_host_insert(struct primitives_ptrs *, struct insert_data *); extern void P_sum_port_insert(struct primitives_ptrs *, struct insert_data *); extern void P_sum_as_insert(struct primitives_ptrs *, struct insert_data *); #if defined (HAVE_L2) extern void P_sum_mac_insert(struct primitives_ptrs *, struct insert_data *); #endif extern struct chained_cache *P_cache_search(struct primitives_ptrs *); extern void P_cache_insert(struct primitives_ptrs *, struct insert_data *); extern void P_cache_insert_pending(struct chained_cache *[], int, struct chained_cache *); extern void P_cache_mark_flush(struct chained_cache *[], int, int); extern void P_cache_flush(struct chained_cache *[], int); extern void P_cache_handle_flush_event(struct ports_table *, struct protos_table *, struct protos_table *); extern void P_exit_now(int); extern int P_trigger_exec(char *); extern void primptrs_set_all_from_chained_cache(struct primitives_ptrs *, struct chained_cache *); extern void P_handle_table_dyn_rr(char *, int, char *, struct p_table_rr *); extern void P_init_historical_acct(time_t); extern void P_init_refresh_deadline(time_t *, int, int, char *); extern void P_eval_historical_acct(struct timeval *, struct timeval *, time_t); extern int P_cmp_historical_acct(struct timeval *, struct timeval *); extern void P_update_time_reference(struct insert_data *); extern void P_set_stitch(struct chained_cache *, struct pkt_data *, struct insert_data *); extern void P_update_stitch(struct chained_cache *, struct pkt_data *, struct insert_data *); extern cdada_list_t *ptm_labels_to_linked_list(const char *); extern cdada_list_t *tcpflags_to_linked_list(size_t); extern cdada_list_t *fwd_status_to_linked_list(); extern void mpls_label_stack_to_str(char *, int, u_int32_t *, int); extern void load_ports(char *, struct ports_table *); extern void load_protos(char *, struct protos_table *); extern void load_tos(char *, struct protos_table *); /* global vars */ extern void (*insert_func)(struct primitives_ptrs *, struct insert_data *); /* pointer to INSERT function */ extern void (*purge_func)(struct chained_cache *[], int, int); /* pointer to purge function */ extern struct scratch_area sa; extern struct chained_cache *cache; extern struct chained_cache **queries_queue, **pending_queries_queue, *pqq_container; extern struct timeval flushtime; extern int qq_ptr, pqq_ptr, pp_size, pb_size, pn_size, pm_size, pt_size, pc_size; extern int dbc_size, quit; extern time_t refresh_deadline; extern void (*basetime_init)(time_t); extern void (*basetime_eval)(struct timeval *, struct timeval *, time_t); extern int (*basetime_cmp)(struct timeval *, struct timeval *); extern struct timeval basetime, ibasetime, new_basetime; extern time_t timeslot; extern int dyn_table, dyn_table_time_only; #endif //PLUGIN_COMMON_H pmacct-1.7.8/src/pmacct-dlt.h0000644000175000017500000003760614354105275015016 0ustar paolopaolo/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * * @(#) $Header$ (LBL) */ /* * This is the DLT definition section of original libpcap bpf.h header; * it includes only the what is required by the code generator and the * userland BPF interpreter, and the libpcap APIs for setting filters, * etc.. * * "pcap-bpf.c" will include the native OS version, as it deals with * the OS's BPF implementation. */ /* * Data-link level type codes. * * Do *NOT* add new values to this list without asking * "tcpdump-workers@tcpdump.org" for a value. Otherwise, you run the * risk of using a value that's already being used for some other purpose, * and of having tools that read libpcap-format captures not being able * to handle captures with your new DLT_ value, with no hope that they * will ever be changed to do so (as that would destroy their ability * to read captures using that value for that other purpose). */ /* * These are the types that are the same on all platforms, and that * have been defined by for ages. */ #ifndef DLT_NULL #define DLT_NULL 0 /* no link-layer encapsulation */ #endif #ifndef DLT_EN10MB #define DLT_EN10MB 1 /* Ethernet (10Mb) */ #endif #ifndef DLT_EN3MB #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ #endif #ifndef DLT_AX25 #define DLT_AX25 3 /* Amateur Radio AX.25 */ #endif #ifndef DLT_PRONET #define DLT_PRONET 4 /* Proteon ProNET Token Ring */ #endif #ifndef DLT_CHAOS #define DLT_CHAOS 5 /* Chaos */ #endif #ifndef DLT_IEEE802 #define DLT_IEEE802 6 /* IEEE 802 Networks */ #endif #ifndef DLT_ARCNET #define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ #endif #ifndef DLT_SLIP #define DLT_SLIP 8 /* Serial Line IP */ #endif #ifndef DLT_PPP #define DLT_PPP 9 /* Point-to-point Protocol */ #endif #ifndef DLT_FDDI #define DLT_FDDI 10 /* FDDI */ #endif /* * These are types that are different on some platforms, and that * have been defined by for ages. We use #ifdefs to * detect the BSDs that define them differently from the traditional * libpcap * * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, * but I don't know what the right #define is for BSD/OS. */ #ifndef DLT_ATM_RFC1483 #define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ #endif #ifndef DLT_RAW #ifdef __OpenBSD__ #define DLT_RAW 14 /* raw IP */ #else #define DLT_RAW 12 /* raw IP */ #endif #endif /* * Given that the only OS that currently generates BSD/OS SLIP or PPP * is, well, BSD/OS, arguably everybody should have chosen its values * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they * didn't. So it goes. */ #if defined(__NetBSD__) || defined(__FreeBSD__) #ifndef DLT_SLIP_BSDOS #define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ #endif #else #define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ #endif /* * 17 is used for DLT_PFLOG in OpenBSD; don't use it for anything else. */ #ifndef DLT_ATM_CLIP #define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ #endif /* * These values are defined by NetBSD; other platforms should refrain from * using them for other purposes, so that NetBSD savefiles with link * types of 50 or 51 can be read as this type on all platforms. */ #ifndef DLT_PPP_SERIAL #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ #endif #ifndef DLT_PPP_ETHER #define DLT_PPP_ETHER 51 /* PPP over Ethernet */ #endif /* * Values between 100 and 103 are used in capture file headers as * link-layer types corresponding to DLT_ types that differ * between platforms; don't use those values for new DLT_ new types. */ /* * This value was defined by libpcap 0.5; platforms that have defined * it with a different value should define it here with that value - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, * whatever value that happens to be, so programs will correctly * handle files with that link type regardless of the value of * DLT_C_HDLC. * * The name DLT_C_HDLC was used by BSD/OS; we use that name for source * compatibility with programs written for BSD/OS. * * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, * for source compatibility with programs written for libpcap 0.5. */ #ifndef DLT_C_HDLC #define DLT_C_HDLC 104 /* Cisco HDLC */ #endif #ifndef DLT_CHDLC #define DLT_CHDLC DLT_C_HDLC #endif #ifndef DLT_IEEE802_11 #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ #endif /* * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, * except when it isn't. (I.e., sometimes it's just raw IP, and * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, * so that we don't have to worry about the link-layer header.) */ /* * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides * with other values. * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header * (DLCI, etc.). */ #ifndef DLT_FRELAY #define DLT_FRELAY 107 #endif /* * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except * that the AF_ type in the link-layer header is in network byte order. * * OpenBSD defines it as 12, but that collides with DLT_RAW, so we * define it as 108 here. If OpenBSD picks up this file, it should * define DLT_LOOP as 12 in its version, as per the comment above - * and should not use 108 as a DLT_ value. */ #ifndef DLT_LOOP #define DLT_LOOP 108 #endif /* * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other * than OpenBSD. */ #ifndef DLT_ENC #ifdef __OpenBSD__ #define DLT_ENC 13 #else #define DLT_ENC 109 #endif #endif /* * Values between 110 and 112 are reserved for use in capture file headers * as link-layer types corresponding to DLT_ types that might differ * between platforms; don't use those values for new DLT_ types * other than the corresponding DLT_ types. */ /* * This is for Linux cooked sockets. */ #ifndef DLT_LINUX_SLL #define DLT_LINUX_SLL 113 #endif /* * Apple LocalTalk hardware. */ #ifndef DLT_LTALK #define DLT_LTALK 114 #endif /* * Acorn Econet. */ #ifndef DLT_ECONET #define DLT_ECONET 115 #endif /* * Reserved for use with OpenBSD ipfilter. */ #ifndef DLT_IPFILTER #define DLT_IPFILTER 116 #endif /* * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 * in SuSE 6.3, so we can't use 17 for it in capture-file headers. */ #ifndef DLT_PFLOG #ifdef __OpenBSD__ #define DLT_PFLOG 17 #else #define DLT_PFLOG 117 #endif #endif /* * Registered for Cisco-internal use. */ #ifndef DLT_CISCO_IOS #define DLT_CISCO_IOS 118 #endif /* * For 802.11 cards using the Prism II chips, with a link-layer * header including Prism monitor mode information plus an 802.11 * header. */ #ifndef DLT_PRISM_HEADER #define DLT_PRISM_HEADER 119 #endif /* * Reserved for Aironet 802.11 cards, with an Aironet link-layer header * (see Doug Ambrisko's FreeBSD patches). */ #ifndef DLT_AIRONET_HEADER #define DLT_AIRONET_HEADER 120 #endif /* * Reserved for Siemens HiPath HDLC. */ #ifndef DLT_HHDLC #define DLT_HHDLC 121 #endif /* * This is for RFC 2625 IP-over-Fibre Channel. * * This is not for use with raw Fibre Channel, where the link-layer * header starts with a Fibre Channel frame header; it's for IP-over-FC, * where the link-layer header starts with an RFC 2625 Network_Header * field. */ #ifndef DLT_IP_OVER_FC #define DLT_IP_OVER_FC 122 #endif /* * This is for Full Frontal ATM on Solaris with SunATM, with a * pseudo-header followed by an AALn PDU. * * There may be other forms of Full Frontal ATM on other OSes, * with different pseudo-headers. * * If ATM software returns a pseudo-header with VPI/VCI information * (and, ideally, packet type information, e.g. signalling, ILMI, * LANE, LLC-multiplexed traffic, etc.), it should not use * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump * and the like don't have to infer the presence or absence of a * pseudo-header and the form of the pseudo-header. */ #ifndef DLT_SUNATM #define DLT_SUNATM 123 /* Solaris+SunATM */ #endif /* * Reserved as per request from Kent Dahlgren * for private use. */ #ifndef DLT_RIO #define DLT_RIO 124 /* RapidIO */ #endif #ifndef DLT_PCI_EXP #define DLT_PCI_EXP 125 /* PCI Express */ #endif #ifndef DLT_AURORA #define DLT_AURORA 126 /* Xilinx Aurora link layer */ #endif /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt * * but could and arguably should also be used by non-AVS Linux * 802.11 drivers and BSD drivers; that may happen in the future. */ #ifndef DLT_IEEE802_11_RADIO #define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ #endif /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #ifndef DLT_TZSP #define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ #endif /* * BSD's ARCNET headers have the source host, destination host, * and type at the beginning of the packet; that's what's handed * up to userland via BPF. * * Linux's ARCNET headers, however, have a 2-byte offset field * between the host IDs and the type; that's what's handed up * to userland via PF_PACKET sockets. * * We therefore have to have separate DLT_ values for them. */ #ifndef DLT_ARCNET_LINUX #define DLT_ARCNET_LINUX 129 /* ARCNET */ #endif /* * juniper-private data link types, as per request from * Hannes Gredler the DLT_s are used * for passing on chassis-internal metainformation like * QOS profiles etc. */ #ifndef DLT_JUNIPER_MLPPP #define DLT_JUNIPER_MLPPP 130 #endif #ifndef DLT_JUNIPER_MLFR #define DLT_JUNIPER_MLFR 131 #endif #ifndef DLT_JUNIPER_ES #define DLT_JUNIPER_ES 132 #endif #ifndef DLT_JUNIPER_GGSN #define DLT_JUNIPER_GGSN 133 #endif #ifndef DLT_JUNIPER_MFR #define DLT_JUNIPER_MFR 134 #endif #ifndef DLT_JUNIPER_ATM2 #define DLT_JUNIPER_ATM2 135 #endif #ifndef DLT_JUNIPER_SERVICES #define DLT_JUNIPER_SERVICES 136 #endif #ifndef DLT_JUNIPER_ATM1 #define DLT_JUNIPER_ATM1 137 #endif /* * Reserved for Apple IP-over-IEEE 1394, as per a request from Dieter * Siegmund . The header that would be presented * would be an Ethernet-like header: * * #define FIREWIRE_EUI64_LEN 8 * struct firewire_header { * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; * u_short firewire_type; * }; * * with "firewire_type" being an Ethernet type value, rather than, * for example, raw GASP frames being handed up. */ #ifndef DLT_APPLE_IP_OVER_IEEE1394 #define DLT_APPLE_IP_OVER_IEEE1394 138 #endif /* * 139 through 142 are reserved for SS7. */ /* * Reserved for DOCSIS MAC frames. */ #ifndef DLT_DOCSIS #define DLT_DOCSIS 143 #endif /* * Linux-IrDA packets. Protocol defined at http://www.irda.org. * Those packets include IrLAP headers and above (IrLMP...), but * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy * framing can be handled by the hardware and depend on the bitrate. * This is exactly the format you would get capturing on a Linux-IrDA * interface (irdaX), but not on a raw serial port. * Note the capture is done in "Linux-cooked" mode, so each packet include * a fake packet header (struct sll_header). This is because IrDA packet * decoding is dependant on the direction of the packet (incomming or * outgoing). * When/if other platform implement IrDA capture, we may revisit the * issue and define a real DLT_IRDA... * Jean II */ #ifndef DLT_LINUX_IRDA #define DLT_LINUX_IRDA 144 #endif /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #ifndef DLT_IBM_SP #define DLT_IBM_SP 145 #endif #ifndef DLT_IBM_SN #define DLT_IBM_SN 146 #endif /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that DLT_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Instead, ask "tcpdump-workers@tcpdump.org" for a new DLT_ value, * as per the comment above. */ #ifndef DLT_USER0 #define DLT_USER0 147 #endif #ifndef DLT_USER1 #define DLT_USER1 148 #endif #ifndef DLT_USER2 #define DLT_USER2 149 #endif #ifndef DLT_USER3 #define DLT_USER3 150 #endif #ifndef DLT_USER4 #define DLT_USER4 151 #endif #ifndef DLT_USER5 #define DLT_USER5 152 #endif #ifndef DLT_USER6 #define DLT_USER6 153 #endif #ifndef DLT_USER7 #define DLT_USER7 154 #endif #ifndef DLT_USER8 #define DLT_USER8 155 #endif #ifndef DLT_USER9 #define DLT_USER9 156 #endif #ifndef DLT_USER10 #define DLT_USER10 157 #endif #ifndef DLT_USER11 #define DLT_USER11 158 #endif #ifndef DLT_USER12 #define DLT_USER12 159 #endif #ifndef DLT_USER13 #define DLT_USER13 160 #endif #ifndef DLT_USER14 #define DLT_USER14 161 #endif #ifndef DLT_USER15 #define DLT_USER15 162 #endif pmacct-1.7.8/src/sfprobe_plugin/0000755000175000017500000000000014354105416015614 5ustar paolopaolopmacct-1.7.8/src/sfprobe_plugin/sflow_api.h0000644000175000017500000003015214354105275017754 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on sflowtool which is: Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: http://www.inmon.com/technology/sflowlicense.txt */ ///////////////////////////////////////////////////////////////////////////////// /////////////////////// sFlow Sampling Agent API //////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// #ifndef SFLOW_API_H #define SFLOW_API_H 1 #if defined(__cplusplus) extern "C" { #endif #include "pmacct.h" #include #include #include #include #include "sflow.h" /* uncomment this preprocessor flag (or compile with -DSFL_USE_32BIT_INDEX) if your ds_index numbers can ever be >= 2^30-1 (i.e. >= 0x3FFFFFFF) */ /* #define SFL_USE_32BIT_INDEX */ /* Used to combine ds_class, ds_index and instance into a single 64-bit number like this: __________________________________ | cls| index | instance | ---------------------------------- but now is opened up to a 12-byte struct to ensure that ds_index has a full 32-bit field, and to make accessing the components simpler. The macros have the same behavior as before, so this change should be transparent. The only difference is that these objects are now passed around by reference instead of by value, and the comparison is done using a fn. */ typedef struct _SFLDataSource_instance { u_int32_t ds_class; u_int32_t ds_index; u_int32_t ds_instance; } SFLDataSource_instance; #ifdef SFL_USE_32BIT_INDEX #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded #else #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample /* if index numbers are not going to use all 32 bits, then we can use the more compact encoding, with the dataSource class and index merged */ #define SFL_DS_DATASOURCE(dsi) (((dsi).ds_class << 24) + (dsi).ds_index) #endif #define SFL_DS_INSTANCE(dsi) (dsi).ds_instance #define SFL_DS_CLASS(dsi) (dsi).ds_class #define SFL_DS_INDEX(dsi) (dsi).ds_index #define SFL_DS_SET(dsi,clss,indx,inst) \ do { \ (dsi).ds_class = (clss); \ (dsi).ds_index = (indx); \ (dsi).ds_instance = (inst); \ } while(0) typedef struct _SFLSampleCollector { u_int32_t data[(SFL_MAX_DATAGRAM_SIZE + SFL_DATA_PAD) / sizeof(u_int32_t)]; u_int32_t *datap; /* packet fill pointer */ u_int32_t pktlen; /* accumulated size */ u_int32_t packetSeqNo; u_int32_t numSamples; } SFLSampleCollector; struct _SFLAgent; /* forward decl */ typedef struct _SFLReceiver { struct _SFLReceiver *nxt; /* MIB fields */ char *sFlowRcvrOwner; time_t sFlowRcvrTimeout; u_int32_t sFlowRcvrMaximumDatagramSize; SFLAddress sFlowRcvrAddress; u_int32_t sFlowRcvrPort; u_int32_t sFlowRcvrDatagramVersion; /* public fields */ struct _SFLAgent *agent; /* pointer to my agent */ /* private fields */ SFLSampleCollector sampleCollector; struct sockaddr_storage receiver; } SFLReceiver; typedef struct _SFLSampler { /* for linked list */ struct _SFLSampler *nxt; /* for hash lookup table */ struct _SFLSampler *hash_nxt; /* MIB fields */ SFLDataSource_instance dsi; u_int32_t sFlowFsReceiver; u_int32_t sFlowFsPacketSamplingRate; u_int32_t sFlowFsMaximumHeaderSize; /* public fields */ struct _SFLAgent *agent; /* pointer to my agent */ /* private fields */ SFLReceiver *myReceiver; u_int32_t skip; u_int32_t samplePool; u_int32_t flowSampleSeqNo; /* rate checking */ u_int32_t samplesThisTick; u_int32_t samplesLastTick; u_int32_t backoffThreshold; } SFLSampler; /* declare */ struct _SFLPoller; typedef void (*getCountersFn_t)(void *magic, /* callback to get counters */ struct _SFLPoller *sampler, /* called with self */ SFL_COUNTERS_SAMPLE_TYPE *cs); /* struct to fill in */ typedef struct _SFLPoller { /* for linked list */ struct _SFLPoller *nxt; /* MIB fields */ SFLDataSource_instance dsi; u_int32_t sFlowCpReceiver; time_t sFlowCpInterval; /* public fields */ struct _SFLAgent *agent; /* pointer to my agent */ void *magic; /* ptr to pass back in getCountersFn() */ getCountersFn_t getCountersFn; /* private fields */ SFLReceiver *myReceiver; time_t countersCountdown; u_int32_t countersSampleSeqNo; } SFLPoller; typedef void *(*allocFn_t)(void *magic, /* callback to allocate space on heap */ struct _SFLAgent *agent, /* called with self */ size_t bytes); /* bytes requested */ typedef int (*freeFn_t)(void *magic, /* callback to free space on heap */ struct _SFLAgent *agent, /* called with self */ void *obj); /* obj to free */ typedef void (*errorFn_t)(void *magic, /* callback to log error message */ struct _SFLAgent *agent, /* called with self */ char *msg); /* error message */ typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */ struct _SFLAgent *agent, SFLReceiver *receiver, u_char *pkt, u_int32_t pktLen); /* prime numbers are good for hash tables */ #define SFL_HASHTABLE_SIZ 199 typedef struct _SFLAgent { SFLSampler *jumpTable[SFL_HASHTABLE_SIZ]; /* fast lookup table for samplers (by ifIndex) */ SFLSampler *samplers; /* the list of samplers */ SFLPoller *pollers; /* the list of samplers */ SFLReceiver *receivers; /* the array of receivers */ time_t bootTime; /* time when we booted or started */ time_t now; /* time now */ SFLAddress myIP; /* IP address of this node */ u_int32_t subId; /* sub_agent_id */ void *magic; /* ptr to pass back in logging and alloc fns */ allocFn_t allocFn; freeFn_t freeFn; errorFn_t errorFn; sendFn_t sendFn; int receiverSocket; } SFLAgent; /* call this at the start with a newly created agent */ void sfl_agent_init(SFLAgent *agent, SFLAddress *myIP, /* IP address of this agent */ u_int32_t subId, /* agent_sub_id */ time_t bootTime, /* agent boot time */ time_t now, /* time now */ void *magic, /* ptr to pass back in logging and alloc fns */ allocFn_t allocFn, freeFn_t freeFn, errorFn_t errorFn, sendFn_t sendFn); /* call this to create samplers */ SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); /* call this to create pollers */ SFLPoller *sfl_agent_addPoller(SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, /* ptr to pass back in getCountersFn() */ getCountersFn_t getCountersFn); /* call this to create receivers */ SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent); /* call this to remove samplers */ int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); /* call this to remove pollers */ int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi); /* note: receivers should not be removed. Typically the receivers list will be created at init time and never changed */ /* call these fns to retrieve sampler, poller or receiver (e.g. for SNMP GET or GETNEXT operation) */ SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi); SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi); SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex); SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex); /* jump table access - for performance */ SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex); /* call these functions to GET and SET MIB values */ /* receiver */ char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver); void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner); time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver); void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout); u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver); void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize); SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver); void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress); u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver); void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort); /* sampler */ u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler); void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver); u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler); void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate); u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler); void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize); /* poller */ u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller); void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver); u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller); void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval); /* call this to indicate a discontinuity with a counter like samplePool so that the sflow collector will ignore the next delta */ void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler); /* call this to indicate a discontinuity with one or more of the counters so that the sflow collector will ignore the next delta */ void sfl_poller_resetCountersSeqNo(SFLPoller *poller); /* software sampling: call this with every packet - returns non-zero if the packet should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */ int sfl_sampler_takeSample(SFLSampler *sampler); /* call this to set a maximum samples-per-second threshold. If the sampler reaches this threshold it will automatically back off the sampling rate. A value of 0 disables the mechanism */ void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond); u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler); /* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */ void sfl_agent_tick(SFLAgent *agent, time_t now); /* call this with each flow sample */ void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs); /* call this to push counters samples (usually done in the getCountersFn callback) */ void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs); /* call this to deallocate resources */ void sfl_agent_release(SFLAgent *agent); /* internal fns */ void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent); void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi); void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn); void sfl_receiver_tick(SFLReceiver *receiver, time_t now); void sfl_poller_tick(SFLPoller *poller, time_t now); void sfl_sampler_tick(SFLSampler *sampler, time_t now); int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs); int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs); void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver); void sfl_agent_error(SFLAgent *agent, char *modName, char *msg); void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg); u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver); #define SFL_ALLOC malloc #define SFL_FREE free #if defined(__cplusplus) } /* extern "C" */ #endif #endif /* SFLOW_API_H */ pmacct-1.7.8/src/sfprobe_plugin/sflow_sampler.c0000644000175000017500000001617414354105275020651 0ustar paolopaolo/* Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ /* http://www.inmon.com/technology/sflowlicense.txt */ #include #include #include #include #include #include #include "sflow_api.h" /*_________________--------------------------__________________ _________________ sfl_sampler_init __________________ -----------------__________________________------------------ */ void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi) { /* copy the dsi in case it points to sampler->dsi, which we are about to clear. (Thanks to Jagjit Choudray of Force 10 Networks for pointing out this bug) */ SFLDataSource_instance dsi = *pdsi; /* clear everything */ memset(sampler, 0, sizeof(*sampler)); /* now copy in the parameters */ sampler->agent = agent; sampler->dsi = dsi; /* set defaults */ sampler->sFlowFsMaximumHeaderSize = SFL_DEFAULT_HEADER_SIZE; sampler->sFlowFsPacketSamplingRate = SFL_DEFAULT_FLOW_SAMPLING_RATE; } /*_________________--------------------------__________________ _________________ reset __________________ -----------------__________________________------------------ */ static void reset(SFLSampler *sampler) { SFLDataSource_instance dsi = sampler->dsi; sfl_sampler_init(sampler, sampler->agent, &dsi); } /*_________________---------------------------__________________ _________________ MIB access __________________ -----------------___________________________------------------ */ u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler) { return sampler->sFlowFsReceiver; } void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver) { sampler->sFlowFsReceiver = sFlowFsReceiver; if(sFlowFsReceiver == 0) reset(sampler); else { /* retrieve and cache a direct pointer to my receiver */ sampler->myReceiver = sfl_agent_getReceiver(sampler->agent, sampler->sFlowFsReceiver); } } u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler) { return sampler->sFlowFsPacketSamplingRate; } void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate) { sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate; } u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler) { return sampler->sFlowFsMaximumHeaderSize; } void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize) { sampler->sFlowFsMaximumHeaderSize = sFlowFsMaximumHeaderSize; } /* call this to set a maximum samples-per-second threshold. If the sampler reaches this threshold it will automatically back off the sampling rate. A value of 0 disables the mechanism */ void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond) { sampler->backoffThreshold = samplesPerSecond; } u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler) { return sampler->backoffThreshold; } u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler) { return sampler->samplesLastTick; } /*_________________---------------------------------__________________ _________________ sequence number reset __________________ -----------------_________________________________------------------ Used by the agent to indicate a samplePool discontinuity so that the sflow collector will know to ignore the next delta. */ void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler) { sampler->flowSampleSeqNo = 0; } /*_________________---------------------------__________________ _________________ sfl_sampler_tick __________________ -----------------___________________________------------------ */ void sfl_sampler_tick(SFLSampler *sampler, time_t now) { if(sampler->backoffThreshold && sampler->samplesThisTick > sampler->backoffThreshold) { // automatic backoff. If using hardware sampling then this is where you have to // call out to change the sampling rate and make sure that any other registers/variables // that hold this value are updated. sampler->sFlowFsPacketSamplingRate *= 2; } sampler->samplesLastTick = sampler->samplesThisTick; sampler->samplesThisTick = 0; } /*_________________------------------------------__________________ _________________ sfl_sampler_writeFlowSample __________________ -----------------______________________________------------------ */ void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs) { if(fs == NULL) return; sampler->samplesThisTick++; /* increment the sequence number */ fs->sequence_number = ++sampler->flowSampleSeqNo; /* copy the other header fields in */ #ifdef SFL_USE_32BIT_INDEX fs->ds_class = SFL_DS_CLASS(sampler->dsi); fs->ds_index = SFL_DS_INDEX(sampler->dsi); #else fs->source_id = SFL_DS_DATASOURCE(sampler->dsi); #endif /* the sampling rate may have been set already. */ if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate; /* the samplePool may be maintained upstream too. */ if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool; /* sent to my receiver */ if(sampler->myReceiver) sfl_receiver_writeFlowSample(sampler->myReceiver, fs); } /* ================== software sampling ========================*/ /*_________________---------------------------__________________ _________________ nextRandomSkip __________________ -----------------___________________________------------------ */ inline static u_int32_t nextRandomSkip(u_int32_t mean) { if(mean == 0 || mean == 1) return 1; return ((random() % ((2 * mean) - 1)) + 1); } /*_________________---------------------------__________________ _________________ sfl_sampler_takeSample __________________ -----------------___________________________------------------ */ int sfl_sampler_takeSample(SFLSampler *sampler) { if (sampler->skip == 0) { /* first time - seed the random number generator */ srandom(SFL_DS_INDEX(sampler->dsi)); sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate); } // increment the samplePool sampler->samplePool++; if (--sampler->skip == 0) { /* reached zero. Set the next skip and return true. */ sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate); return 1; } return 0; } /* int sfl_sampler_takeSample(SFLSampler *sampler, u_int32_t pkts) { sampler->samplePool++; return pkts; } */ /* int sfl_sampler_takeSample(SFLSampler *sampler, u_int32_t pkts) { int delta, sampledPkts = 0; run_again: if (sampler->skip == 0) { // first time - seed the random number generator srandom(SFL_DS_INDEX(sampler->dsi)); sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate); } // increment the samplePool sampler->samplePool++; delta = MIN(sampler->skip, pkts); sampler->skip -= delta; pkts -= delta; if (sampler->skip == 0) { // reached zero. Set the next skip and return true. sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate); sampledPkts++; if (pkts > 0) goto run_again; } return sampledPkts; } */ pmacct-1.7.8/src/sfprobe_plugin/sflow_poller.c0000644000175000017500000001077514354105275020504 0ustar paolopaolo/* Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ /* http://www.inmon.com/technology/sflowlicense.txt */ #include #include #include #include #include #include #include "sflow_api.h" /*_________________--------------------------__________________ _________________ sfl_poller_init __________________ -----------------__________________________------------------ */ void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, /* ptr to pass back in getCountersFn() */ getCountersFn_t getCountersFn) { /* copy the dsi in case it points to poller->dsi, which we are about to clear */ SFLDataSource_instance dsi = *pdsi; /* clear everything */ memset(poller, 0, sizeof(*poller)); /* now copy in the parameters */ poller->agent = agent; poller->dsi = dsi; /* structure copy */ poller->magic = magic; poller->getCountersFn = getCountersFn; } /*_________________--------------------------__________________ _________________ reset __________________ -----------------__________________________------------------ */ static void reset(SFLPoller *poller) { SFLDataSource_instance dsi = poller->dsi; sfl_poller_init(poller, poller->agent, &dsi, poller->magic, poller->getCountersFn); } /*_________________---------------------------__________________ _________________ MIB access __________________ -----------------___________________________------------------ */ u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller) { return poller->sFlowCpReceiver; } void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver) { poller->sFlowCpReceiver = sFlowCpReceiver; if(sFlowCpReceiver == 0) reset(poller); else { /* retrieve and cache a direct pointer to my receiver */ poller->myReceiver = sfl_agent_getReceiver(poller->agent, poller->sFlowCpReceiver); } } u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller) { return poller->sFlowCpInterval; } void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval) { poller->sFlowCpInterval = sFlowCpInterval; /* Set the countersCountdown to be a randomly selected value between 1 and sFlowCpInterval. That way the counter polling would be desynchronised (on a 200-port switch, polling all the counters in one second could be harmful). */ poller->countersCountdown = 1 + (random() % sFlowCpInterval); } /*_________________---------------------------------__________________ _________________ sequence number reset __________________ -----------------_________________________________------------------ Used to indicate a counter discontinuity so that the sflow collector will know to ignore the next delta. */ void sfl_poller_resetCountersSeqNo(SFLPoller *poller) { poller->countersSampleSeqNo = 0; } /*_________________---------------------------__________________ _________________ sfl_poller_tick __________________ -----------------___________________________------------------ */ void sfl_poller_tick(SFLPoller *poller, time_t now) { if(poller->countersCountdown == 0) return; /* counters retrieval was not enabled */ if(poller->sFlowCpReceiver == 0) return; if(--poller->countersCountdown == 0) { if(poller->getCountersFn != NULL) { /* call out for counters */ SFL_COUNTERS_SAMPLE_TYPE cs; memset(&cs, 0, sizeof(cs)); poller->getCountersFn(poller->magic, poller, &cs); // this countersFn is expected to fill in some counter block elements // and then call sfl_poller_writeCountersSample(poller, &cs); } /* reset the countdown */ poller->countersCountdown = poller->sFlowCpInterval; } } /*_________________---------------------------------__________________ _________________ sfl_poller_writeCountersSample __________________ -----------------_________________________________------------------ */ void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs) { /* fill in the rest of the header fields, and send to the receiver */ cs->sequence_number = ++poller->countersSampleSeqNo; #ifdef SFL_USE_32BIT_INDEX cs->ds_class = SFL_DS_CLASS(poller->dsi); cs->ds_index = SFL_DS_INDEX(poller->dsi); #else cs->source_id = SFL_DS_DATASOURCE(poller->dsi); #endif /* sent to my receiver */ if(poller->myReceiver) sfl_receiver_writeCountersSample(poller->myReceiver, cs); } pmacct-1.7.8/src/sfprobe_plugin/sflow_agent.c0000644000175000017500000004230214354105275020274 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* Originally based on sflowtool which is: Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: http://www.inmon.com/technology/sflowlicense.txt */ #include #include #include #include #include #include #include "pmacct.h" #include "sflow_api.h" static void * sflAlloc(SFLAgent *agent, size_t bytes); static void sflFree(SFLAgent *agent, void *obj); static void sfl_agent_jumpTableAdd(SFLAgent *agent, SFLSampler *sampler); static void sfl_agent_jumpTableRemove(SFLAgent *agent, SFLSampler *sampler); /*________________--------------------------__________________ ________________ sfl_agent_init __________________ ----------------__________________________------------------ */ void sfl_agent_init(SFLAgent *agent, SFLAddress *myIP, /* IP address of this agent in net byte order */ u_int32_t subId, /* agent_sub_id */ time_t bootTime, /* agent boot time */ time_t now, /* time now */ void *magic, /* ptr to pass back in logging and alloc fns */ allocFn_t allocFn, freeFn_t freeFn, errorFn_t errorFn, sendFn_t sendFn) { struct sockaddr_storage ssource_ip; int ret = 0, family = 0; /* first clear everything */ memset(agent, 0, sizeof(*agent)); memset(&ssource_ip, 0, sizeof(ssource_ip)); /* now copy in the parameters */ agent->myIP = *myIP; /* structure copy */ agent->subId = subId; agent->bootTime = bootTime; agent->now = now; agent->magic = magic; agent->allocFn = allocFn; agent->freeFn = freeFn; agent->errorFn = errorFn; agent->sendFn = sendFn; if (myIP->type == SFLADDRESSTYPE_IP_V4) family = AF_INET; else if (myIP->type == SFLADDRESSTYPE_IP_V6) family = AF_INET6; if (config.nfprobe_source_ip) { ret = str_to_addr(config.nfprobe_source_ip, &config.nfprobe_source_ha); addr_to_sa((struct sockaddr *) &ssource_ip, &config.nfprobe_source_ha, 0); family = config.nfprobe_source_ha.family; } if(sendFn == NULL) { /* open the socket */ if ((agent->receiverSocket = socket(family, SOCK_DGRAM, IPPROTO_UDP)) == -1) sfl_agent_sysError(agent, "agent", "socket open failed"); } if (config.nfprobe_ipprec) { int opt = config.nfprobe_ipprec << 5; int rc; rc = setsockopt(agent->receiverSocket, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_WARNING, "WARN ( %s/%s ): setsockopt() failed for IP_TOS: %s\n", config.name, config.type, strerror(errno)); } if (ret && bind(agent->receiverSocket, (struct sockaddr *) &ssource_ip, sizeof(ssource_ip)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): bind() failed: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } if (config.pipe_size) { int rc, value; value = MIN(config.pipe_size, INT_MAX); rc = Setsocksize(agent->receiverSocket, SOL_SOCKET, SO_SNDBUF, &value, (socklen_t) sizeof(value)); if (rc < 0) Log(LOG_WARNING, "WARN ( %s/%s ): setsockopt() failed for SOL_SNDBUF: %s\n", config.name, config.type, strerror(errno)); } } /*_________________---------------------------__________________ _________________ sfl_agent_release __________________ -----------------___________________________------------------ */ void sfl_agent_release(SFLAgent *agent) { SFLSampler *sm; SFLPoller *pl; SFLReceiver *rcv; /* release and free the samplers */ for(sm = agent->samplers; sm != NULL; ) { SFLSampler *nextSm = sm->nxt; sflFree(agent, sm); sm = nextSm; } agent->samplers = NULL; /* release and free the pollers */ for(pl = agent->pollers; pl != NULL; ) { SFLPoller *nextPl = pl->nxt; sflFree(agent, pl); pl = nextPl; } agent->pollers = NULL; /* release and free the receivers */ for(rcv = agent->receivers; rcv != NULL; ) { SFLReceiver *nextRcv = rcv->nxt; sflFree(agent, rcv); rcv = nextRcv; } agent->receivers = NULL; /* close the socket */ if(agent->receiverSocket > 0) close(agent->receiverSocket); } /*_________________---------------------------__________________ _________________ sfl_agent_tick __________________ -----------------___________________________------------------ */ void sfl_agent_tick(SFLAgent *agent, time_t now) { SFLReceiver *rcv; SFLSampler *sm; SFLPoller *pl; agent->now = now; /* receivers use ticks to flush send data */ for(rcv = agent->receivers; rcv != NULL; rcv = rcv->nxt) sfl_receiver_tick(rcv, now); /* samplers use ticks to decide when they are sampling too fast */ for(sm = agent->samplers; sm != NULL; sm = sm->nxt) sfl_sampler_tick(sm, now); /* pollers use ticks to decide when to ask for counters */ for(pl = agent->pollers; pl != NULL; pl = pl->nxt) sfl_poller_tick(pl, now); } /*_________________---------------------------__________________ _________________ sfl_agent_addReceiver __________________ -----------------___________________________------------------ */ SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent) { SFLReceiver *rcv = (SFLReceiver *)sflAlloc(agent, sizeof(SFLReceiver)); SFLReceiver *r, *prev = NULL; sfl_receiver_init(rcv, agent); // add to end of list - to preserve the receiver index numbers for existing receivers for(r = agent->receivers; r != NULL; prev = r, r = r->nxt); if(prev) prev->nxt = rcv; else agent->receivers = rcv; rcv->nxt = NULL; return rcv; } /*_________________---------------------------__________________ _________________ sfl_dsi_compare __________________ -----------------___________________________------------------ Note that if there is a mixture of ds_classes for this agent, then the simple numeric comparison may not be correct - the sort order (for the purposes of the SNMP MIB) should really be determined by the OID that these numeric ds_class numbers are a shorthand for. For example, ds_class == 0 means ifIndex, which is the oid "1.3.6.1.2.1.2.2.1" */ static inline int sfl_dsi_compare(SFLDataSource_instance *pdsi1, SFLDataSource_instance *pdsi2) { // could have used just memcmp(), but not sure if that would // give the right answer on little-endian platforms. Safer to be explicit... int cmp = pdsi2->ds_class - pdsi1->ds_class; if(cmp == 0) cmp = pdsi2->ds_index - pdsi1->ds_index; if(cmp == 0) cmp = pdsi2->ds_instance - pdsi1->ds_instance; return cmp; } /*_________________---------------------------__________________ _________________ sfl_agent_addSampler __________________ -----------------___________________________------------------ */ SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi) { SFLSampler *newsm; // keep the list sorted SFLSampler *prev = NULL, *sm = agent->samplers; for(; sm != NULL; prev = sm, sm = sm->nxt) { int64_t cmp = sfl_dsi_compare(pdsi, &sm->dsi); if(cmp == 0) return sm; // found - return existing one if(cmp < 0) break; // insert here } // either we found the insert point, or reached the end of the list... newsm = (SFLSampler *)sflAlloc(agent, sizeof(SFLSampler)); sfl_sampler_init(newsm, agent, pdsi); if(prev) prev->nxt = newsm; else agent->samplers = newsm; newsm->nxt = sm; // see if we should go in the ifIndex jumpTable if(SFL_DS_CLASS(newsm->dsi) == 0) { SFLSampler *test = sfl_agent_getSamplerByIfIndex(agent, SFL_DS_INDEX(newsm->dsi)); if(test && (SFL_DS_INSTANCE(newsm->dsi) < SFL_DS_INSTANCE(test->dsi))) { // replace with this new one because it has a lower ds_instance number sfl_agent_jumpTableRemove(agent, test); test = NULL; } if(test == NULL) sfl_agent_jumpTableAdd(agent, newsm); } return newsm; } /*_________________---------------------------__________________ _________________ sfl_agent_addPoller __________________ -----------------___________________________------------------ */ SFLPoller *sfl_agent_addPoller(SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, /* ptr to pass back in getCountersFn() */ getCountersFn_t getCountersFn) { int64_t cmp; SFLPoller *newpl; // keep the list sorted SFLPoller *prev = NULL, *pl = agent->pollers; for(; pl != NULL; prev = pl, pl = pl->nxt) { cmp = sfl_dsi_compare(pdsi, &pl->dsi); if(cmp == 0) return pl; // found - return existing one if(cmp < 0) break; // insert here } // either we found the insert point, or reached the end of the list... newpl = (SFLPoller *)sflAlloc(agent, sizeof(SFLPoller)); sfl_poller_init(newpl, agent, pdsi, magic, getCountersFn); if(prev) prev->nxt = newpl; else agent->pollers = newpl; newpl->nxt = pl; return newpl; } /*_________________---------------------------__________________ _________________ sfl_agent_removeSampler __________________ -----------------___________________________------------------ */ int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi) { SFLSampler *prev, *sm; /* find it, unlink it and free it */ for(prev = NULL, sm = agent->samplers; sm != NULL; prev = sm, sm = sm->nxt) { if(sfl_dsi_compare(pdsi, &sm->dsi) == 0) { if(prev == NULL) agent->samplers = sm->nxt; else prev->nxt = sm->nxt; sfl_agent_jumpTableRemove(agent, sm); sflFree(agent, sm); return 1; } } /* not found */ return 0; } /*_________________---------------------------__________________ _________________ sfl_agent_removePoller __________________ -----------------___________________________------------------ */ int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi) { SFLPoller *prev, *pl; /* find it, unlink it and free it */ for(prev = NULL, pl = agent->pollers; pl != NULL; prev = pl, pl = pl->nxt) { if(sfl_dsi_compare(pdsi, &pl->dsi) == 0) { if(prev == NULL) agent->pollers = pl->nxt; else prev->nxt = pl->nxt; sflFree(agent, pl); return 1; } } /* not found */ return 0; } /*_________________--------------------------------__________________ _________________ sfl_agent_jumpTableAdd __________________ -----------------________________________________------------------ */ static void sfl_agent_jumpTableAdd(SFLAgent *agent, SFLSampler *sampler) { u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ; sampler->hash_nxt = agent->jumpTable[hashIndex]; agent->jumpTable[hashIndex] = sampler; } /*_________________--------------------------------__________________ _________________ sfl_agent_jumpTableRemove __________________ -----------------________________________________------------------ */ static void sfl_agent_jumpTableRemove(SFLAgent *agent, SFLSampler *sampler) { u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ; SFLSampler *search = agent->jumpTable[hashIndex], *prev = NULL; for( ; search != NULL; prev = search, search = search->hash_nxt) if(search == sampler) break; if(search) { // found - unlink if(prev) prev->hash_nxt = search->hash_nxt; else agent->jumpTable[hashIndex] = search->hash_nxt; search->hash_nxt = NULL; } } /*_________________--------------------------------__________________ _________________ sfl_agent_getSamplerByIfIndex __________________ -----------------________________________________------------------ fast lookup (pointers cached in hash table). If there are multiple sampler instances for a given ifIndex, then this fn will return the one with the lowest instance number. Since the samplers list is sorted, this means the other instances will be accesible by following the sampler->nxt pointer (until the ds_class or ds_index changes). This is helpful if you need to offer the same flowSample to multiple samplers. */ SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex) { SFLSampler *search = agent->jumpTable[ifIndex % SFL_HASHTABLE_SIZ]; for( ; search != NULL; search = search->hash_nxt) if(SFL_DS_INDEX(search->dsi) == ifIndex) break; return search; } /*_________________---------------------------__________________ _________________ sfl_agent_getSampler __________________ -----------------___________________________------------------ */ SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi) { SFLSampler *sm; /* find it and return it */ for(sm = agent->samplers; sm != NULL; sm = sm->nxt) if(sfl_dsi_compare(pdsi, &sm->dsi) == 0) return sm; /* not found */ return NULL; } /*_________________---------------------------__________________ _________________ sfl_agent_getPoller __________________ -----------------___________________________------------------ */ SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi) { SFLPoller *pl; /* find it and return it */ for(pl = agent->pollers; pl != NULL; pl = pl->nxt) if(sfl_dsi_compare(pdsi, &pl->dsi) == 0) return pl; /* not found */ return NULL; } /*_________________---------------------------__________________ _________________ sfl_agent_getReceiver __________________ -----------------___________________________------------------ */ SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex) { SFLReceiver *rcv; u_int32_t rcvIdx = 0; for(rcv = agent->receivers; rcv != NULL; rcv = rcv->nxt) if(receiverIndex == ++rcvIdx) return rcv; /* not found - ran off the end of the table */ return NULL; } /*_________________---------------------------__________________ _________________ sfl_agent_getNextSampler __________________ -----------------___________________________------------------ */ SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi) { /* return the one lexograpically just after it - assume they are sorted correctly according to the lexographical ordering of the object ids */ SFLSampler *sm = sfl_agent_getSampler(agent, pdsi); return sm ? sm->nxt : NULL; } /*_________________---------------------------__________________ _________________ sfl_agent_getNextPoller __________________ -----------------___________________________------------------ */ SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi) { /* return the one lexograpically just after it - assume they are sorted correctly according to the lexographical ordering of the object ids */ SFLPoller *pl = sfl_agent_getPoller(agent, pdsi); return pl ? pl->nxt : NULL; } /*_________________---------------------------__________________ _________________ sfl_agent_getNextReceiver __________________ -----------------___________________________------------------ */ SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex) { return sfl_agent_getReceiver(agent, receiverIndex + 1); } /*_________________---------------------------__________________ _________________ sfl_agent_resetReceiver __________________ -----------------___________________________------------------ */ void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver) { SFLReceiver *rcv; SFLSampler *sm; SFLPoller *pl; /* tell samplers and pollers to stop sending to this receiver */ /* first get his receiverIndex */ u_int32_t rcvIdx = 0; for(rcv = agent->receivers; rcv != NULL; rcv = rcv->nxt) if(rcv == receiver) break; /* now tell anyone that is using it to stop */ for(sm = agent->samplers; sm != NULL; sm = sm->nxt) if(sfl_sampler_get_sFlowFsReceiver(sm) == rcvIdx) sfl_sampler_set_sFlowFsReceiver(sm, 0); for(pl = agent->pollers; pl != NULL; pl = pl->nxt) if(sfl_poller_get_sFlowCpReceiver(pl) == rcvIdx) sfl_poller_set_sFlowCpReceiver(pl, 0); } /*_________________---------------------------__________________ _________________ sfl_agent_error __________________ -----------------___________________________------------------ */ #define MAX_ERRMSG_LEN 1000 void sfl_agent_error(SFLAgent *agent, char *modName, char *msg) { char errm[MAX_ERRMSG_LEN]; sprintf(errm, "sfl_agent_error: %s: %s\n", modName, msg); if(agent->errorFn) (*agent->errorFn)(agent->magic, agent, errm); else Log(LOG_ERR, "ERROR ( %s/%s ): %s\n", config.name, config.type, errm); } /*_________________---------------------------__________________ _________________ sfl_agent_sysError __________________ -----------------___________________________------------------ */ void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg) { char errm[MAX_ERRMSG_LEN]; sprintf(errm, "sfl_agent_sysError: %s: %s (errno = %d - %s)\n", modName, msg, errno, strerror(errno)); if(agent->errorFn) (*agent->errorFn)(agent->magic, agent, errm); else Log(LOG_ERR, "ERROR ( %s/%s ): %s\n", config.name, config.type, errm); } /*_________________---------------------------__________________ _________________ alloc and free __________________ -----------------___________________________------------------ */ static void * sflAlloc(SFLAgent *agent, size_t bytes) { if(agent->allocFn) return (*agent->allocFn)(agent->magic, agent, bytes); else return SFL_ALLOC(bytes); } static void sflFree(SFLAgent *agent, void *obj) { if(agent->freeFn) (*agent->freeFn)(agent->magic, agent, obj); else SFL_FREE(obj); } pmacct-1.7.8/src/sfprobe_plugin/sflow_receiver.c0000644000175000017500000007665414354105275021023 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* Originally based on sflowtool which is: Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: http://www.inmon.com/technology/sflowlicense.txt */ #include #include #include #include #include #include #include #include "sflow_api.h" #include "addr.h" #include "ip_flow.h" #include "classifier.h" static void resetSampleCollector(SFLReceiver *receiver); static void sendSample(SFLReceiver *receiver); static void sflError(SFLReceiver *receiver, char *errm); static void putNet32(SFLReceiver *receiver, u_int32_t val); static void putAddress(SFLReceiver *receiver, SFLAddress *addr); /*_________________--------------------------__________________ _________________ sfl_receiver_init __________________ -----------------__________________________------------------ */ void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent) { struct sockaddr_in *sa4 = (struct sockaddr_in *) &receiver->receiver; /* first clear everything */ memset(receiver, 0, sizeof(*receiver)); /* now copy in the parameters */ receiver->agent = agent; /* set defaults */ receiver->sFlowRcvrMaximumDatagramSize = SFL_DEFAULT_DATAGRAM_SIZE; receiver->sFlowRcvrPort = SFL_DEFAULT_COLLECTOR_PORT; /* initialize the socket address */ sa4->sin_family = AF_INET; sa4->sin_port = htons((u_int16_t)receiver->sFlowRcvrPort); sa4->sin_addr = receiver->sFlowRcvrAddress.address.ip_v4; /* preset some of the header fields */ receiver->sampleCollector.datap = receiver->sampleCollector.data; putNet32(receiver, SFLDATAGRAM_VERSION5); putAddress(receiver, &agent->myIP); putNet32(receiver, agent->subId); /* prepare to receive the first sample */ resetSampleCollector(receiver); } /*_________________---------------------------__________________ _________________ reset __________________ -----------------___________________________------------------ called on timeout, or when owner string is cleared */ static void reset(SFLReceiver *receiver) { // ask agent to tell samplers and pollers to stop sending samples sfl_agent_resetReceiver(receiver->agent, receiver); // reinitialize sfl_receiver_init(receiver, receiver->agent); } /*_________________----------------------------------------_____________ _________________ MIB Vars _____________ -----------------________________________________________------------- */ char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver) { return receiver->sFlowRcvrOwner; } void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner) { receiver->sFlowRcvrOwner = sFlowRcvrOwner; if(sFlowRcvrOwner == NULL || sFlowRcvrOwner[0] == '\0') { // reset condition! owner string was cleared reset(receiver); } } time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver) { return receiver->sFlowRcvrTimeout; } void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout) { receiver->sFlowRcvrTimeout =sFlowRcvrTimeout; } u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver) { return receiver->sFlowRcvrMaximumDatagramSize; } void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize) { u_int32_t mdz = sFlowRcvrMaximumDatagramSize; if(mdz < SFL_MIN_DATAGRAM_SIZE) mdz = SFL_MIN_DATAGRAM_SIZE; receiver->sFlowRcvrMaximumDatagramSize = mdz; } SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver) { return &receiver->sFlowRcvrAddress; } void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress) { struct host_addr ha; if (sFlowRcvrAddress) receiver->sFlowRcvrAddress = *sFlowRcvrAddress; // structure copy // update the socket structure memset(&ha, 0, sizeof(ha)); if (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V4) { ha.family = AF_INET; memcpy(&ha.address.ipv4, &receiver->sFlowRcvrAddress.address.ip_v4, sizeof(struct in_addr)); } else { ha.family = AF_INET6; memcpy(&ha.address.ipv6, &receiver->sFlowRcvrAddress.address.ip_v6, sizeof(struct in6_addr)); } addr_to_sa((struct sockaddr *) &receiver->receiver, &ha, (u_int16_t)receiver->sFlowRcvrPort); } u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver) { return receiver->sFlowRcvrPort; } void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort) { struct sockaddr_in *sa4 = (struct sockaddr_in *) &receiver->receiver; receiver->sFlowRcvrPort = sFlowRcvrPort; // update the socket structure sa4->sin_port = htons((u_int16_t)receiver->sFlowRcvrPort); } /*_________________---------------------------__________________ _________________ sfl_receiver_tick __________________ -----------------___________________________------------------ */ void sfl_receiver_tick(SFLReceiver *receiver, time_t now) { // if there are any samples to send, flush them now if(receiver->sampleCollector.numSamples > 0) sendSample(receiver); // check the timeout if(receiver->sFlowRcvrTimeout && receiver->sFlowRcvrTimeout != 0xFFFFFFFF) { // count down one tick and reset if we reach 0 if(--receiver->sFlowRcvrTimeout == 0) reset(receiver); } } /*_________________-----------------------------__________________ _________________ receiver write utilities __________________ -----------------_____________________________------------------ */ inline static void put32(SFLReceiver *receiver, u_int32_t val) { *receiver->sampleCollector.datap++ = val; } inline static void putNet32(SFLReceiver *receiver, u_int32_t val) { *receiver->sampleCollector.datap++ = htonl(val); } inline static void putNet32_run(SFLReceiver *receiver, void *obj, size_t quads) { u_int32_t *from = (u_int32_t *)obj; while(quads--) putNet32(receiver, *from++); } inline static void putNet64(SFLReceiver *receiver, u_int64_t val64) { u_int32_t *firstQuadPtr = receiver->sampleCollector.datap; // first copy the bytes in memcpy((u_char *)firstQuadPtr, &val64, 8); if(htonl(1) != 1) { // swap the bytes, and reverse the quads too u_int32_t tmp = *receiver->sampleCollector.datap++; *firstQuadPtr = htonl(*receiver->sampleCollector.datap); *receiver->sampleCollector.datap++ = htonl(tmp); } else receiver->sampleCollector.datap += 2; } inline static void put128(SFLReceiver *receiver, u_char *val) { memcpy(receiver->sampleCollector.datap, val, 16); receiver->sampleCollector.datap += 4; } inline static void putString(SFLReceiver *receiver, SFLString *s) { putNet32(receiver, s->len); memcpy(receiver->sampleCollector.datap, s->str, s->len); receiver->sampleCollector.datap += (s->len + 3) / 4; /* pad to 4-byte boundary */ } inline static u_int32_t stringEncodingLength(SFLString *s) { // answer in bytes, so remember to mulitply by 4 after rounding up to nearest 4-byte boundary return 4 + (((s->len + 3) / 4) * 4); } inline static void putAddress(SFLReceiver *receiver, SFLAddress *addr) { // encode unspecified addresses as IPV4:0.0.0.0 - or should we flag this as an error? if(addr->type == 0) { putNet32(receiver, SFLADDRESSTYPE_IP_V4); put32(receiver, 0); } else { putNet32(receiver, addr->type); if(addr->type == SFLADDRESSTYPE_IP_V4) put32(receiver, addr->address.ip_v4.s_addr); else put128(receiver, addr->address.ip_v6.s6_addr); } } inline static u_int32_t addressEncodingLength(SFLAddress *addr) { return (addr->type == SFLADDRESSTYPE_IP_V6) ? 20 : 8; // type + address (unspecified == IPV4) } inline static void putMACAddress(SFLReceiver *receiver, u_int8_t *mac) { memcpy(receiver->sampleCollector.datap, mac, 6); receiver->sampleCollector.datap += 2; } inline static void putSwitch(SFLReceiver *receiver, SFLExtended_switch *sw) { putNet32(receiver, sw->src_vlan); putNet32(receiver, sw->src_priority); putNet32(receiver, sw->dst_vlan); putNet32(receiver, sw->dst_priority); } inline static void putRouter(SFLReceiver *receiver, SFLExtended_router *router) { putAddress(receiver, &router->nexthop); putNet32(receiver, router->src_mask); putNet32(receiver, router->dst_mask); } inline static u_int32_t routerEncodingLength(SFLExtended_router *router) { return addressEncodingLength(&router->nexthop) + 8; } inline static void putGateway(SFLReceiver *receiver, SFLExtended_gateway *gw) { int seg; putAddress(receiver, &gw->nexthop); putNet32(receiver, gw->as); putNet32(receiver, gw->src_as); putNet32(receiver, gw->src_peer_as); putNet32(receiver, gw->dst_as_path_segments); for(seg = 0; seg < gw->dst_as_path_segments; seg++) { putNet32(receiver, gw->dst_as_path[seg].type); putNet32(receiver, gw->dst_as_path[seg].length); putNet32_run(receiver, gw->dst_as_path[seg].as.seq, gw->dst_as_path[seg].length); } putNet32(receiver, gw->communities_length); putNet32_run(receiver, gw->communities, gw->communities_length); putNet32(receiver, gw->localpref); } inline static u_int32_t gatewayEncodingLength(SFLExtended_gateway *gw) { u_int32_t elemSiz = addressEncodingLength(&gw->nexthop); int seg; elemSiz += 16; // as, src_as, src_peer_as, dst_as_path_segments for(seg = 0; seg < gw->dst_as_path_segments; seg++) { elemSiz += 8; // type, length elemSiz += 4 * gw->dst_as_path[seg].length; // set/seq bytes } elemSiz += 4; // communities_length elemSiz += 4 * gw->communities_length; // communities elemSiz += 4; // localpref return elemSiz; } inline static void putUser(SFLReceiver *receiver, SFLExtended_user *user) { putNet32(receiver, user->src_charset); putString(receiver, &user->src_user); putNet32(receiver, user->dst_charset); putString(receiver, &user->dst_user); } inline static u_int32_t userEncodingLength(SFLExtended_user *user) { return 4 + stringEncodingLength(&user->src_user) + 4 + stringEncodingLength(&user->dst_user); } inline static void putUrl(SFLReceiver *receiver, SFLExtended_url *url) { putNet32(receiver, url->direction); putString(receiver, &url->url); putString(receiver, &url->host); } inline static u_int32_t urlEncodingLength(SFLExtended_url *url) { return 4 + stringEncodingLength(&url->url) + stringEncodingLength(&url->host); } inline static void putLabelStack(SFLReceiver *receiver, SFLLabelStack *labelStack) { putNet32(receiver, labelStack->depth); putNet32_run(receiver, labelStack->stack, labelStack->depth); } inline static u_int32_t labelStackEncodingLength(SFLLabelStack *labelStack) { return 4 + (4 * labelStack->depth); } inline static void putMpls(SFLReceiver *receiver, SFLExtended_mpls *mpls) { putAddress(receiver, &mpls->nextHop); putLabelStack(receiver, &mpls->in_stack); putLabelStack(receiver, &mpls->out_stack); } inline static u_int32_t mplsEncodingLength(SFLExtended_mpls *mpls) { return addressEncodingLength(&mpls->nextHop) + labelStackEncodingLength(&mpls->in_stack) + labelStackEncodingLength(&mpls->out_stack); } inline static void putNat(SFLReceiver *receiver, SFLExtended_nat *nat) { putAddress(receiver, &nat->src); putAddress(receiver, &nat->dst); } inline static u_int32_t natEncodingLength(SFLExtended_nat *nat) { return addressEncodingLength(&nat->src) + addressEncodingLength(&nat->dst); } inline static void putMplsTunnel(SFLReceiver *receiver, SFLExtended_mpls_tunnel *tunnel) { putString(receiver, &tunnel->tunnel_lsp_name); putNet32(receiver, tunnel->tunnel_id); putNet32(receiver, tunnel->tunnel_cos); } inline static u_int32_t mplsTunnelEncodingLength(SFLExtended_mpls_tunnel *tunnel) { return stringEncodingLength(&tunnel->tunnel_lsp_name) + 8; } inline static void putMplsVc(SFLReceiver *receiver, SFLExtended_mpls_vc *vc) { putString(receiver, &vc->vc_instance_name); putNet32(receiver, vc->vll_vc_id); putNet32(receiver, vc->vc_label_cos); } inline static u_int32_t mplsVcEncodingLength(SFLExtended_mpls_vc *vc) { return stringEncodingLength( &vc->vc_instance_name) + 8; } inline static void putMplsFtn(SFLReceiver *receiver, SFLExtended_mpls_FTN *ftn) { putString(receiver, &ftn->mplsFTNDescr); putNet32(receiver, ftn->mplsFTNMask); } inline static u_int32_t mplsFtnEncodingLength(SFLExtended_mpls_FTN *ftn) { return stringEncodingLength( &ftn->mplsFTNDescr) + 4; } inline static void putMplsLdpFec(SFLReceiver *receiver, SFLExtended_mpls_LDP_FEC *ldpfec) { putNet32(receiver, ldpfec->mplsFecAddrPrefixLength); } inline static u_int32_t mplsLdpFecEncodingLength(SFLExtended_mpls_LDP_FEC *ldpfec) { return 4; } inline static void putVlanTunnel(SFLReceiver *receiver, SFLExtended_vlan_tunnel *vlanTunnel) { putLabelStack(receiver, &vlanTunnel->stack); } inline static u_int32_t vlanTunnelEncodingLength(SFLExtended_vlan_tunnel *vlanTunnel) { return labelStackEncodingLength(&vlanTunnel->stack); } inline static void putClass(SFLReceiver *receiver, SFLExtended_classification *class_elem) { char buf[MAX_PROTOCOL_LEN+1]; memset(buf, 0, MAX_PROTOCOL_LEN+1); if (class_elem->class && class[class_elem->class-1].id) { strlcpy(buf, class[class_elem->class-1].protocol, MAX_PROTOCOL_LEN); buf[sizeof(buf)-1] = '\0'; } else strlcpy(buf, "unknown", MAX_PROTOCOL_LEN); put128(receiver, (u_char *)buf); } inline static void putClass2(SFLReceiver *receiver, SFLExtended_classification2 *class2_elem) { #if defined (WITH_NDPI) putNet32(receiver, class2_elem->id.master_protocol); putNet32(receiver, class2_elem->id.app_protocol); #else u_int64_t dummy = 0; putNet64(receiver, dummy); #endif } inline static void putTag(SFLReceiver *receiver, SFLExtended_tag *tag_elem) { putNet64(receiver, tag_elem->tag); putNet64(receiver, tag_elem->tag2); } inline static void putGenericCounters(SFLReceiver *receiver, SFLIf_counters *counters) { putNet32(receiver, counters->ifIndex); putNet32(receiver, counters->ifType); putNet64(receiver, counters->ifSpeed); putNet32(receiver, counters->ifDirection); putNet32(receiver, counters->ifStatus); putNet64(receiver, counters->ifInOctets); putNet32(receiver, counters->ifInUcastPkts); putNet32(receiver, counters->ifInMulticastPkts); putNet32(receiver, counters->ifInBroadcastPkts); putNet32(receiver, counters->ifInDiscards); putNet32(receiver, counters->ifInErrors); putNet32(receiver, counters->ifInUnknownProtos); putNet64(receiver, counters->ifOutOctets); putNet32(receiver, counters->ifOutUcastPkts); putNet32(receiver, counters->ifOutMulticastPkts); putNet32(receiver, counters->ifOutBroadcastPkts); putNet32(receiver, counters->ifOutDiscards); putNet32(receiver, counters->ifOutErrors); putNet32(receiver, counters->ifPromiscuousMode); } /*_________________-----------------------------__________________ _________________ computeFlowSampleSize __________________ -----------------_____________________________------------------ */ static int computeFlowSampleSize(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs) { SFLFlow_sample_element *elem; u_int elemSiz = 0; #ifdef SFL_USE_32BIT_INDEX u_int siz = 52; /* tag, length, sequence_number, ds_class, ds_index, sampling_rate, sample_pool, drops, inputFormat, input, outputFormat, output, number of elements */ #else u_int siz = 40; /* tag, length, sequence_number, source_id, sampling_rate, sample_pool, drops, input, output, number of elements */ #endif fs->num_elements = 0; /* we're going to count them again even if this was set by the client */ for(elem = fs->elements; elem != NULL; elem = elem->nxt) { fs->num_elements++; siz += 8; /* tag, length */ switch(elem->tag) { case SFLFLOW_HEADER: elemSiz = 16; /* header_protocol, frame_length, stripped, header_length */ elemSiz += ((elem->flowType.header.header_length + 3) / 4) * 4; /* header, rounded up to nearest 4 bytes */ break; case SFLFLOW_ETHERNET: elemSiz = sizeof(SFLSampled_ethernet); break; case SFLFLOW_IPV4: elemSiz = sizeof(SFLSampled_ipv4); break; case SFLFLOW_IPV6: elemSiz = sizeof(SFLSampled_ipv6); break; case SFLFLOW_EX_SWITCH: elemSiz = sizeof(SFLExtended_switch); break; case SFLFLOW_EX_ROUTER: elemSiz = routerEncodingLength(&elem->flowType.router); break; case SFLFLOW_EX_GATEWAY: elemSiz = gatewayEncodingLength(&elem->flowType.gateway); break; case SFLFLOW_EX_USER: elemSiz = userEncodingLength(&elem->flowType.user); break; case SFLFLOW_EX_URL: elemSiz = urlEncodingLength(&elem->flowType.url); break; case SFLFLOW_EX_MPLS: elemSiz = mplsEncodingLength(&elem->flowType.mpls); break; case SFLFLOW_EX_NAT: elemSiz = natEncodingLength(&elem->flowType.nat); break; case SFLFLOW_EX_MPLS_TUNNEL: elemSiz = mplsTunnelEncodingLength(&elem->flowType.mpls_tunnel); break; case SFLFLOW_EX_MPLS_VC: elemSiz = mplsVcEncodingLength(&elem->flowType.mpls_vc); break; case SFLFLOW_EX_MPLS_FTN: elemSiz = mplsFtnEncodingLength(&elem->flowType.mpls_ftn); break; case SFLFLOW_EX_MPLS_LDP_FEC: elemSiz = mplsLdpFecEncodingLength(&elem->flowType.mpls_ldp_fec); break; case SFLFLOW_EX_VLAN_TUNNEL: elemSiz = vlanTunnelEncodingLength(&elem->flowType.vlan_tunnel); break; case SFLFLOW_EX_CLASS: elemSiz = MAX_PROTOCOL_LEN; break; case SFLFLOW_EX_CLASS2: elemSiz = 8; break; case SFLFLOW_EX_TAG: elemSiz = 16; /* (sizeof(pm_id_t) * 2) */ break; default: sflError(receiver, "unexpected packet_data_tag"); return -1; break; } // cache the element size, and accumulate it into the overall FlowSample size elem->length = elemSiz; siz += elemSiz; } return siz; } /*_________________-------------------------------__________________ _________________ sfl_receiver_writeFlowSample __________________ -----------------_______________________________------------------ */ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs) { SFLFlow_sample_element *elem; int packedSize; if(fs == NULL) return -1; if((packedSize = computeFlowSampleSize(receiver, fs)) == -1) return -1; // check in case this one sample alone is too big for the datagram // in fact - if it is even half as big then we should ditch it. Very // important to avoid overruning the packet buffer. if(packedSize > (receiver->sFlowRcvrMaximumDatagramSize / 2)) { sflError(receiver, "flow sample too big for datagram"); return -1; } // if the sample pkt is full enough so that this sample might put // it over the limit, then we should send it now before going on. if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize) sendSample(receiver); receiver->sampleCollector.numSamples++; #ifdef SFL_USE_32BIT_INDEX putNet32(receiver, SFLFLOW_SAMPLE_EXPANDED); #else putNet32(receiver, SFLFLOW_SAMPLE); #endif putNet32(receiver, packedSize - 8); // don't include tag and len putNet32(receiver, fs->sequence_number); #ifdef SFL_USE_32BIT_INDEX putNet32(receiver, fs->ds_class); putNet32(receiver, fs->ds_index); #else putNet32(receiver, fs->source_id); #endif putNet32(receiver, fs->sampling_rate); putNet32(receiver, fs->sample_pool); putNet32(receiver, fs->drops); #ifdef SFL_USE_32BIT_INDEX putNet32(receiver, fs->inputFormat); putNet32(receiver, fs->input); putNet32(receiver, fs->outputFormat); putNet32(receiver, fs->output); #else putNet32(receiver, fs->input); putNet32(receiver, fs->output); #endif putNet32(receiver, fs->num_elements); for (elem = fs->elements; elem != NULL; elem = elem->nxt) { putNet32(receiver, elem->tag); putNet32(receiver, elem->length); // length cached in computeFlowSampleSize() switch(elem->tag) { case SFLFLOW_HEADER: putNet32(receiver, elem->flowType.header.header_protocol); putNet32(receiver, elem->flowType.header.frame_length); putNet32(receiver, elem->flowType.header.stripped); putNet32(receiver, elem->flowType.header.header_length); /* the header */ memcpy(receiver->sampleCollector.datap, elem->flowType.header.header_bytes, elem->flowType.header.header_length); /* round up to multiple of 4 to preserve alignment */ receiver->sampleCollector.datap += ((elem->flowType.header.header_length + 3) / 4); break; case SFLFLOW_ETHERNET: putNet32(receiver, elem->flowType.ethernet.eth_len); putMACAddress(receiver, elem->flowType.ethernet.src_mac); putMACAddress(receiver, elem->flowType.ethernet.dst_mac); putNet32(receiver, elem->flowType.ethernet.eth_type); break; case SFLFLOW_IPV4: putNet32(receiver, elem->flowType.ipv4.length); putNet32(receiver, elem->flowType.ipv4.protocol); put32(receiver, elem->flowType.ipv4.src_ip.s_addr); put32(receiver, elem->flowType.ipv4.dst_ip.s_addr); putNet32(receiver, elem->flowType.ipv4.src_port); putNet32(receiver, elem->flowType.ipv4.dst_port); putNet32(receiver, elem->flowType.ipv4.tcp_flags); putNet32(receiver, elem->flowType.ipv4.tos); break; case SFLFLOW_IPV6: putNet32(receiver, elem->flowType.ipv6.length); putNet32(receiver, elem->flowType.ipv6.protocol); put128(receiver, elem->flowType.ipv6.src_ip.s6_addr); put128(receiver, elem->flowType.ipv6.dst_ip.s6_addr); putNet32(receiver, elem->flowType.ipv6.src_port); putNet32(receiver, elem->flowType.ipv6.dst_port); putNet32(receiver, elem->flowType.ipv6.tcp_flags); putNet32(receiver, elem->flowType.ipv6.priority); break; case SFLFLOW_EX_SWITCH: putSwitch(receiver, &elem->flowType.sw); break; case SFLFLOW_EX_ROUTER: putRouter(receiver, &elem->flowType.router); break; case SFLFLOW_EX_GATEWAY: putGateway(receiver, &elem->flowType.gateway); break; case SFLFLOW_EX_USER: putUser(receiver, &elem->flowType.user); break; case SFLFLOW_EX_URL: putUrl(receiver, &elem->flowType.url); break; case SFLFLOW_EX_MPLS: putMpls(receiver, &elem->flowType.mpls); break; case SFLFLOW_EX_NAT: putNat(receiver, &elem->flowType.nat); break; case SFLFLOW_EX_MPLS_TUNNEL: putMplsTunnel(receiver, &elem->flowType.mpls_tunnel); break; case SFLFLOW_EX_MPLS_VC: putMplsVc(receiver, &elem->flowType.mpls_vc); break; case SFLFLOW_EX_MPLS_FTN: putMplsFtn(receiver, &elem->flowType.mpls_ftn); break; case SFLFLOW_EX_MPLS_LDP_FEC: putMplsLdpFec(receiver, &elem->flowType.mpls_ldp_fec); break; case SFLFLOW_EX_VLAN_TUNNEL: putVlanTunnel(receiver, &elem->flowType.vlan_tunnel); break; case SFLFLOW_EX_CLASS: putClass(receiver, &elem->flowType.class); break; case SFLFLOW_EX_CLASS2: putClass2(receiver, &elem->flowType.ndpi_class); break; case SFLFLOW_EX_TAG: putTag(receiver, &elem->flowType.tag); break; default: sflError(receiver, "unexpected packet_data_tag"); return -1; break; } } // sanity check assert(((u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data - receiver->sampleCollector.pktlen) == packedSize); // update the pktlen receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data; return packedSize; } /*_________________-----------------------------__________________ _________________ computeCountersSampleSize __________________ -----------------_____________________________------------------ */ static int computeCountersSampleSize(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs) { SFLCounters_sample_element *elem; u_int elemSiz = 0; #ifdef SFL_USE_32BIT_INDEX u_int siz = 24; /* tag, length, sequence_number, ds_class, ds_index, number of elements */ #else u_int siz = 20; /* tag, length, sequence_number, source_id, number of elements */ #endif cs->num_elements = 0; /* we're going to count them again even if this was set by the client */ for(elem = cs->elements; elem != NULL; elem = elem->nxt) { cs->num_elements++; siz += 8; /* tag, length */ switch(elem->tag) { case SFLCOUNTERS_GENERIC: elemSiz = sizeof(elem->counterBlock.generic); break; case SFLCOUNTERS_ETHERNET: elemSiz = sizeof(elem->counterBlock.ethernet); break; case SFLCOUNTERS_TOKENRING: elemSiz = sizeof(elem->counterBlock.tokenring); break; case SFLCOUNTERS_VG: elemSiz = sizeof(elem->counterBlock.vg); break; case SFLCOUNTERS_VLAN: elemSiz = sizeof(elem->counterBlock.vlan); break; default: sflError(receiver, "unexpected counters_tag"); return -1; break; } // cache the element size, and accumulate it into the overall FlowSample size elem->length = elemSiz; siz += elemSiz; } return siz; } /*_________________----------------------------------__________________ _________________ sfl_receiver_writeCountersSample __________________ -----------------__________________________________------------------ */ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs) { SFLCounters_sample_element *elem; int packedSize; if(cs == NULL) return -1; // if the sample pkt is full enough so that this sample might put // it over the limit, then we should send it now. if((packedSize = computeCountersSampleSize(receiver, cs)) == -1) return -1; // check in case this one sample alone is too big for the datagram // in fact - if it is even half as big then we should ditch it. Very // important to avoid overruning the packet buffer. if(packedSize > (receiver->sFlowRcvrMaximumDatagramSize / 2)) { sflError(receiver, "counters sample too big for datagram"); return -1; } if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize) sendSample(receiver); receiver->sampleCollector.numSamples++; #ifdef SFL_USE_32BIT_INDEX putNet32(receiver, SFLCOUNTERS_SAMPLE_EXPANDED); #else putNet32(receiver, SFLCOUNTERS_SAMPLE); #endif putNet32(receiver, packedSize - 8); // tag and length not included putNet32(receiver, cs->sequence_number); #ifdef SFL_USE_32BIT_INDEX putNet32(receiver, cs->ds_class); putNet32(receiver, cs->ds_index); #else putNet32(receiver, cs->source_id); #endif putNet32(receiver, cs->num_elements); for(elem = cs->elements; elem != NULL; elem = elem->nxt) { putNet32(receiver, elem->tag); putNet32(receiver, elem->length); // length cached in computeCountersSampleSize() switch(elem->tag) { case SFLCOUNTERS_GENERIC: putGenericCounters(receiver, &(elem->counterBlock.generic)); break; case SFLCOUNTERS_ETHERNET: // all these counters are 32-bit putNet32_run(receiver, &elem->counterBlock.ethernet, sizeof(elem->counterBlock.ethernet) / 4); break; case SFLCOUNTERS_TOKENRING: // all these counters are 32-bit putNet32_run(receiver, &elem->counterBlock.tokenring, sizeof(elem->counterBlock.tokenring) / 4); break; case SFLCOUNTERS_VG: // mixed sizes putNet32(receiver, elem->counterBlock.vg.dot12InHighPriorityFrames); putNet64(receiver, elem->counterBlock.vg.dot12InHighPriorityOctets); putNet32(receiver, elem->counterBlock.vg.dot12InNormPriorityFrames); putNet64(receiver, elem->counterBlock.vg.dot12InNormPriorityOctets); putNet32(receiver, elem->counterBlock.vg.dot12InIPMErrors); putNet32(receiver, elem->counterBlock.vg.dot12InOversizeFrameErrors); putNet32(receiver, elem->counterBlock.vg.dot12InDataErrors); putNet32(receiver, elem->counterBlock.vg.dot12InNullAddressedFrames); putNet32(receiver, elem->counterBlock.vg.dot12OutHighPriorityFrames); putNet64(receiver, elem->counterBlock.vg.dot12OutHighPriorityOctets); putNet32(receiver, elem->counterBlock.vg.dot12TransitionIntoTrainings); putNet64(receiver, elem->counterBlock.vg.dot12HCInHighPriorityOctets); putNet64(receiver, elem->counterBlock.vg.dot12HCInNormPriorityOctets); putNet64(receiver, elem->counterBlock.vg.dot12HCOutHighPriorityOctets); break; case SFLCOUNTERS_VLAN: // mixed sizes putNet32(receiver, elem->counterBlock.vlan.vlan_id); putNet64(receiver, elem->counterBlock.vlan.octets); putNet32(receiver, elem->counterBlock.vlan.ucastPkts); putNet32(receiver, elem->counterBlock.vlan.multicastPkts); putNet32(receiver, elem->counterBlock.vlan.broadcastPkts); putNet32(receiver, elem->counterBlock.vlan.discards); break; default: sflError(receiver, "unexpected counters_tag"); return -1; break; } } // sanity check assert(((u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data - receiver->sampleCollector.pktlen) == packedSize); // update the pktlen receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data; return packedSize; } /*_________________---------------------------------__________________ _________________ sfl_receiver_samplePacketsSent __________________ -----------------_________________________________------------------ */ u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver) { return receiver->sampleCollector.packetSeqNo; } /*_________________---------------------------__________________ _________________ sendSample __________________ -----------------___________________________------------------ */ static void sendSample(SFLReceiver *receiver) { /* construct and send out the sample, then reset for the next one... */ /* first fill in the header with the latest values */ /* version, agent_address and sub_agent_id were pre-set. */ u_int32_t hdrIdx = (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) ? 7 : 4; receiver->sampleCollector.data[hdrIdx++] = htonl(++receiver->sampleCollector.packetSeqNo); /* seq no */ receiver->sampleCollector.data[hdrIdx++] = htonl((receiver->agent->now - receiver->agent->bootTime) * 1000); /* uptime */ receiver->sampleCollector.data[hdrIdx++] = htonl(receiver->sampleCollector.numSamples); /* num samples */ /* send */ if(receiver->agent->sendFn) (*receiver->agent->sendFn)(receiver->agent->magic, receiver->agent, receiver, (u_char *)receiver->sampleCollector.data, receiver->sampleCollector.pktlen); else { /* send it myself */ int result = sendto(receiver->agent->receiverSocket, receiver->sampleCollector.data, receiver->sampleCollector.pktlen, 0, (struct sockaddr *)&receiver->receiver, sa_len(&receiver->receiver)); if(result == -1 && errno != EINTR) sfl_agent_sysError(receiver->agent, "receiver", "socket sendto error"); if(result == 0) sfl_agent_error(receiver->agent, "receiver", "socket sendto returned 0"); } /* reset for the next time */ resetSampleCollector(receiver); } /*_________________---------------------------__________________ _________________ resetSampleCollector __________________ -----------------___________________________------------------ */ static void resetSampleCollector(SFLReceiver *receiver) { receiver->sampleCollector.pktlen = 0; receiver->sampleCollector.numSamples = 0; /* point the datap to just after the header */ receiver->sampleCollector.datap = (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) ? (receiver->sampleCollector.data + 10) : (receiver->sampleCollector.data + 7); receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data; } /*_________________---------------------------__________________ _________________ sflError __________________ -----------------___________________________------------------ */ static void sflError(SFLReceiver *receiver, char *msg) { sfl_agent_error(receiver->agent, "receiver", msg); resetSampleCollector(receiver); } pmacct-1.7.8/src/sfprobe_plugin/Makefile.in0000644000175000017500000006532514354105416017674 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/sfprobe_plugin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsfprobe_plugin_la_LIBADD = am_libsfprobe_plugin_la_OBJECTS = libsfprobe_plugin_la-sflow_agent.lo \ libsfprobe_plugin_la-sflow_poller.lo \ libsfprobe_plugin_la-sflow_receiver.lo \ libsfprobe_plugin_la-sflow_sampler.lo \ libsfprobe_plugin_la-sfprobe_plugin.lo libsfprobe_plugin_la_OBJECTS = $(am_libsfprobe_plugin_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libsfprobe_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Plo \ ./$(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Plo \ ./$(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Plo \ ./$(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Plo \ ./$(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libsfprobe_plugin_la_SOURCES) DIST_SOURCES = $(libsfprobe_plugin_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libsfprobe_plugin.la libsfprobe_plugin_la_SOURCES = sflow_agent.c sflow_poller.c \ sflow_receiver.c sflow_sampler.c sfprobe_plugin.c sflow_api.h libsfprobe_plugin_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/sfprobe_plugin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/sfprobe_plugin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libsfprobe_plugin.la: $(libsfprobe_plugin_la_OBJECTS) $(libsfprobe_plugin_la_DEPENDENCIES) $(EXTRA_libsfprobe_plugin_la_DEPENDENCIES) $(AM_V_CCLD)$(libsfprobe_plugin_la_LINK) $(libsfprobe_plugin_la_OBJECTS) $(libsfprobe_plugin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libsfprobe_plugin_la-sflow_agent.lo: sflow_agent.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libsfprobe_plugin_la-sflow_agent.lo -MD -MP -MF $(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Tpo -c -o libsfprobe_plugin_la-sflow_agent.lo `test -f 'sflow_agent.c' || echo '$(srcdir)/'`sflow_agent.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Tpo $(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sflow_agent.c' object='libsfprobe_plugin_la-sflow_agent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libsfprobe_plugin_la-sflow_agent.lo `test -f 'sflow_agent.c' || echo '$(srcdir)/'`sflow_agent.c libsfprobe_plugin_la-sflow_poller.lo: sflow_poller.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libsfprobe_plugin_la-sflow_poller.lo -MD -MP -MF $(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Tpo -c -o libsfprobe_plugin_la-sflow_poller.lo `test -f 'sflow_poller.c' || echo '$(srcdir)/'`sflow_poller.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Tpo $(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sflow_poller.c' object='libsfprobe_plugin_la-sflow_poller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libsfprobe_plugin_la-sflow_poller.lo `test -f 'sflow_poller.c' || echo '$(srcdir)/'`sflow_poller.c libsfprobe_plugin_la-sflow_receiver.lo: sflow_receiver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libsfprobe_plugin_la-sflow_receiver.lo -MD -MP -MF $(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Tpo -c -o libsfprobe_plugin_la-sflow_receiver.lo `test -f 'sflow_receiver.c' || echo '$(srcdir)/'`sflow_receiver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Tpo $(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sflow_receiver.c' object='libsfprobe_plugin_la-sflow_receiver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libsfprobe_plugin_la-sflow_receiver.lo `test -f 'sflow_receiver.c' || echo '$(srcdir)/'`sflow_receiver.c libsfprobe_plugin_la-sflow_sampler.lo: sflow_sampler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libsfprobe_plugin_la-sflow_sampler.lo -MD -MP -MF $(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Tpo -c -o libsfprobe_plugin_la-sflow_sampler.lo `test -f 'sflow_sampler.c' || echo '$(srcdir)/'`sflow_sampler.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Tpo $(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sflow_sampler.c' object='libsfprobe_plugin_la-sflow_sampler.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libsfprobe_plugin_la-sflow_sampler.lo `test -f 'sflow_sampler.c' || echo '$(srcdir)/'`sflow_sampler.c libsfprobe_plugin_la-sfprobe_plugin.lo: sfprobe_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libsfprobe_plugin_la-sfprobe_plugin.lo -MD -MP -MF $(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Tpo -c -o libsfprobe_plugin_la-sfprobe_plugin.lo `test -f 'sfprobe_plugin.c' || echo '$(srcdir)/'`sfprobe_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Tpo $(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sfprobe_plugin.c' object='libsfprobe_plugin_la-sfprobe_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libsfprobe_plugin_la-sfprobe_plugin.lo `test -f 'sfprobe_plugin.c' || echo '$(srcdir)/'`sfprobe_plugin.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_agent.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_poller.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_receiver.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sflow_sampler.Plo -rm -f ./$(DEPDIR)/libsfprobe_plugin_la-sfprobe_plugin.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/sfprobe_plugin/Makefile.am0000644000175000017500000000040014354105275017645 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libsfprobe_plugin.la libsfprobe_plugin_la_SOURCES = sflow_agent.c sflow_poller.c \ sflow_receiver.c sflow_sampler.c sfprobe_plugin.c sflow_api.h libsfprobe_plugin_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/sfprobe_plugin/sfprobe_plugin.c0000644000175000017500000007007114354105275021006 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* Originally based on sflowtool which is: Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: http://www.inmon.com/technology/sflowlicense.txt */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sflow_api.h" #include "addr.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "net_aggr.h" #define SFL_DIRECTION_IN 0 #define SFL_DIRECTION_OUT 1 #define SFL_MAX_INTERFACES 4096 typedef struct _SflSp_counters { u_int32_t ifIndex; u_int32_t frames[2]; u_int64_t bytes[2]; u_int32_t multicasts[2]; u_int32_t broadcasts[2]; } SflSp_counters; typedef struct _SflSp { int verbose; char *device; int ifIndex_Type; int ifType; u_int64_t ifSpeed; int ifDirection; int promiscuous; u_int32_t samplingRate; u_int32_t counterSamplingInterval; struct host_addr collectorIP; u_int16_t collectorPort; int snaplen; int timeout_ms; int batch; pcap_t *pcap; SflSp_counters counters[SFL_MAX_INTERFACES]; struct host_addr agentIP; u_int32_t agentSubId; struct in_addr interfaceIP; struct in6_addr interfaceIP6; char pad[2]; SFLAgent *agent; SFLSampler *sampler; } SflSp; void sfprobe_exit_now(int signum) { Log(LOG_WARNING, "WARN ( %s/%s ): Shutting down on user request.\n", config.name, config.type); exit_gracefully(0); } /*_________________---------------------------__________________ _________________ Name_to_IP __________________ -----------------___________________________------------------ */ u_long Name_to_IP(char *domainName) { struct hostent *ent = gethostbyname(domainName); if(ent == NULL) return 0; else return ((struct in_addr *)(ent->h_addr))->s_addr; } /*_________________---------------------------__________________ _________________ getMyIPAddress __________________ -----------------___________________________------------------ */ u_long getMyIPAddress() { struct utsname uts; if (uname(&uts) == -1) return Name_to_IP("localhost"); else return Name_to_IP(uts.nodename); } /* setDefaults(): here we define some fixed infos to be placed in our sFlow datagrams. We should either gather real informations from the system or let the user fill these fields through some configuration directives. XXX */ static void setDefaults(SflSp *sp) { sp->device = NULL; sp->counters[0].ifIndex = 1; sp->ifIndex_Type = IFINDEX_STATIC; sp->ifType = 6; // ethernet_csmacd sp->ifSpeed = 100000000L; // assume 100 MBit sp->ifDirection = 1; // assume full duplex sp->samplingRate = SFL_DEFAULT_FLOW_SAMPLING_RATE; sp->counterSamplingInterval = SFL_DEFAULT_COUNTER_INTERVAL_RATE; if (config.snaplen && config.snaplen <= SFL_DEFAULT_HEADER_SIZE) { sp->snaplen = config.snaplen; } else { sp->snaplen = SFL_DEFAULT_HEADER_SIZE; Log(LOG_WARNING, "WARN ( %s/%s ): Max Flow Sample packet headers length set to %u (wanted: %u)\n", config.name, config.type, sp->snaplen, config.snaplen); } sp->collectorIP.family = AF_INET; sp->collectorIP.address.ipv4.s_addr = Name_to_IP("localhost"); sp->collectorPort = SFL_DEFAULT_COLLECTOR_PORT; sp->agentIP.family = AF_INET; sp->agentIP.address.ipv4.s_addr = getMyIPAddress(); sp->agentIP.address.ipv4.s_addr = Name_to_IP("localhost"); sp->agentSubId = 0; } /*_________________---------------------------__________________ _________________ agent callbacks __________________ -----------------___________________________------------------ */ static void *agentCB_alloc(void *magic, SFLAgent *agent, size_t bytes) { return calloc(1, bytes); } static int agentCB_free(void *magic, SFLAgent *agent, void *obj) { free(obj); return 0; } static void agentCB_error(void *magic, SFLAgent *agent, char *msg) { Log(LOG_ERR, "ERROR ( %s/%s ): sFlow agent error: %s\n", config.name, config.type, msg); } void agentCB_getCounters(void *magic, SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs) { SFLCounters_sample_element genElem[SFL_MAX_INTERFACES]; SflSp *sp = (SflSp *)magic; int idx = 0; memset(&genElem, 0, sizeof(genElem)); // build a counters sample for (idx = 0; idx < SFL_MAX_INTERFACES && sp->counters[idx].ifIndex; idx++) { if (sp->counters[idx].frames[SFL_DIRECTION_IN] || sp->counters[idx].frames[SFL_DIRECTION_OUT]) { genElem[idx].tag = SFLCOUNTERS_GENERIC; // don't need to set the length here (set by the encoder) genElem[idx].counterBlock.generic.ifIndex = sp->counters[idx].ifIndex; genElem[idx].counterBlock.generic.ifType = sp->ifType; genElem[idx].counterBlock.generic.ifSpeed = sp->ifSpeed; genElem[idx].counterBlock.generic.ifDirection = sp->ifDirection; genElem[idx].counterBlock.generic.ifStatus = 0x03; // adminStatus = up, operStatus = up genElem[idx].counterBlock.generic.ifPromiscuousMode = sp->promiscuous; // these counters would normally be a snapshot the hardware interface counters - the // same ones that the SNMP agent uses to answer SNMP requests to the ifTable. To ease // the portability of this program, however, I am just using some counters that were // added up in software: genElem[idx].counterBlock.generic.ifInOctets = sp->counters[idx].bytes[SFL_DIRECTION_IN]; genElem[idx].counterBlock.generic.ifInUcastPkts = sp->counters[idx].frames[SFL_DIRECTION_IN]; genElem[idx].counterBlock.generic.ifInMulticastPkts = sp->counters[idx].multicasts[SFL_DIRECTION_IN]; genElem[idx].counterBlock.generic.ifInBroadcastPkts = sp->counters[idx].broadcasts[SFL_DIRECTION_IN]; genElem[idx].counterBlock.generic.ifOutOctets = sp->counters[idx].bytes[SFL_DIRECTION_OUT]; genElem[idx].counterBlock.generic.ifOutUcastPkts = sp->counters[idx].frames[SFL_DIRECTION_OUT]; genElem[idx].counterBlock.generic.ifOutMulticastPkts = sp->counters[idx].multicasts[SFL_DIRECTION_OUT]; genElem[idx].counterBlock.generic.ifOutBroadcastPkts = sp->counters[idx].broadcasts[SFL_DIRECTION_OUT]; // add this counter block to the counter sample that we are building SFLADD_ELEMENT(cs, &genElem[idx]); } } // pass these counters down to be encoded and included with the next sFlow datagram sfl_poller_writeCountersSample(poller, cs); } /*_________________---------------------------__________________ _________________ init_agent __________________ -----------------___________________________------------------ */ static void init_agent(SflSp *sp) { SFLReceiver *receiver; SFLDataSource_instance dsi; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Creating sFlow agent.\n", config.name, config.type); { // create an agent SFLAddress myIP; time_t now = time(NULL); if (sp->agentIP.family == AF_INET) { myIP.type = SFLADDRESSTYPE_IP_V4; memcpy(&myIP.address.ip_v4, &sp->agentIP.address.ipv4, sizeof(struct in_addr)); } else { myIP.type = SFLADDRESSTYPE_IP_V6; memcpy(&myIP.address.ip_v6, &sp->agentIP.address.ipv6, sizeof(struct in6_addr)); } sp->agent = (SFLAgent *)calloc(1, sizeof(SFLAgent)); if (sp->agent) sfl_agent_init(sp->agent, &myIP, sp->agentSubId, now, now, sp, agentCB_alloc, agentCB_free, agentCB_error, NULL); else { Log(LOG_ERR, "ERROR ( %s/%s ): init_agent(): calloc() failed.\n", config.name, config.type); exit_gracefully(1); } } // add a receiver receiver = sfl_agent_addReceiver(sp->agent); (void)receiver; // todo treat result? // define the data source SFL_DS_SET(dsi, 0, 1, 0); // ds_class = 0, ds_index = 1, ds_instance = 0 // create a sampler for it sfl_agent_addSampler(sp->agent, &dsi); // and a poller too sfl_agent_addPoller(sp->agent, &dsi, sp, agentCB_getCounters); // now configure it just as if it were as series of SNMP SET operations through the MIB interface... // claim the receiver slot sfl_receiver_set_sFlowRcvrOwner(sfl_agent_getReceiver(sp->agent, 1), "my owner string $$$"); // set the timeout to infinity sfl_receiver_set_sFlowRcvrTimeout(sfl_agent_getReceiver(sp->agent, 1), 0xFFFFFFFF); { // collector address SFLAddress addr; if (sp->collectorIP.family == AF_INET) { addr.type = SFLADDRESSTYPE_IP_V4; memcpy(&addr.address.ip_v4, &sp->collectorIP.address.ipv4, sizeof(struct in_addr)); } else { addr.type = SFLADDRESSTYPE_IP_V6; memcpy(&addr.address.ip_v6, &sp->collectorIP.address.ipv6, sizeof(struct in6_addr)); } sfl_receiver_set_sFlowRcvrAddress(sfl_agent_getReceiver(sp->agent, 1), &addr); } // collector port sfl_receiver_set_sFlowRcvrPort(sfl_agent_getReceiver(sp->agent, 1), sp->collectorPort); // set the sampling rate sfl_sampler_set_sFlowFsPacketSamplingRate(sfl_agent_getSampler(sp->agent, &dsi), sp->samplingRate); // set the counter interval sfl_poller_set_sFlowCpInterval(sfl_agent_getPoller(sp->agent, &dsi), sp->counterSamplingInterval); // point the sampler to the receiver sfl_sampler_set_sFlowFsReceiver(sfl_agent_getSampler(sp->agent, &dsi), 1); // point the poller to the receiver sfl_poller_set_sFlowCpReceiver(sfl_agent_getPoller(sp->agent, &dsi), 1); // cache the sampler pointer for performance reasons... sp->sampler = sfl_agent_getSampler(sp->agent, &dsi); } /*_________________---------------------------__________________ _________________ readPacket __________________ -----------------___________________________------------------ */ static void readPacket(SflSp *sp, struct pkt_payload *hdr, const unsigned char *buf) { SFLFlow_sample_element hdrElem, tagHdrElem; #if defined (WITH_NDPI) SFLFlow_sample_element class2HdrElem; #endif SFLFlow_sample_element gatewayHdrElem, routerHdrElem, switchHdrElem; SFLExtended_as_path_segment as_path_segment; u_int32_t frame_len, header_len; int direction, ethHdrLen, idx = 0; struct eth_header dummy_eh; u_int16_t ethType = 0, cap_len = hdr->cap_len, pkt_len = hdr->pkt_len; unsigned char *local_buf = (unsigned char *) buf; /* If we have a dummy ethernet header, we strip it here; we have rewritten Ethertype field: only src/dst MAC addresses should be compared */ ethHdrLen = sizeof(dummy_eh); memset(&dummy_eh, 0, ethHdrLen); if (memcmp(&dummy_eh, local_buf, ethHdrLen-2) == 0) { ethType = ((struct eth_header *)local_buf)->ether_type; local_buf += ethHdrLen; cap_len -= ethHdrLen; pkt_len -= ethHdrLen; } /* Let's fill sample direction in - and default to ingress */ direction = 0; if (config.nfprobe_direction) { switch (config.nfprobe_direction) { case DIRECTION_IN: direction = SFL_DIRECTION_IN; break; case DIRECTION_OUT: direction = SFL_DIRECTION_OUT; break; case DIRECTION_TAG: if (hdr->tag == 1) direction = SFL_DIRECTION_IN; else if (hdr->tag == 2) direction = SFL_DIRECTION_OUT; break; case DIRECTION_TAG2: if (hdr->tag2 == 1) direction = SFL_DIRECTION_IN; else if (hdr->tag2 == 2) direction = SFL_DIRECTION_OUT; break; } } // Let's determine the ifIndex { u_int32_t ifIndex = 0; if (hdr->ifindex_in && direction == SFL_DIRECTION_IN) { ifIndex = hdr->ifindex_in; } else if (hdr->ifindex_out && direction == SFL_DIRECTION_OUT) { ifIndex = hdr->ifindex_out; } if (!ifIndex || config.nfprobe_ifindex_override) { if (sp->ifIndex_Type) { switch (sp->ifIndex_Type) { case IFINDEX_STATIC: if (config.nfprobe_ifindex) { ifIndex = config.nfprobe_ifindex; } break; case IFINDEX_TAG: if (hdr->tag) { ifIndex = hdr->tag; } break; case IFINDEX_TAG2: if (hdr->tag2) { ifIndex = hdr->tag2; } break; } } } if (!ifIndex) ifIndex = 0x3FFFFFFF; for (idx = 0; idx < SFL_MAX_INTERFACES; idx++) { if (sp->counters[idx].ifIndex == ifIndex || idx == (SFL_MAX_INTERFACES-1)) break; else if (sp->counters[idx].ifIndex == 0) { sp->counters[idx].ifIndex = ifIndex; break; } } } // maintain some counters in software - just to ease portability sp->counters[idx].bytes[direction] += pkt_len; if (local_buf[0] & 0x01) { if(local_buf[0] == 0xff && local_buf[1] == 0xff && local_buf[2] == 0xff && local_buf[3] == 0xff && local_buf[4] == 0xff && local_buf[5] == 0xff) sp->counters[idx].broadcasts[direction]++; else sp->counters[idx].multicasts[direction]++; } else sp->counters[idx].frames[direction]++; if (config.ext_sampling_rate || sfl_sampler_takeSample(sp->sampler)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): %02x%02x%02x%02x%02x%02x -> %02x%02x%02x%02x%02x%02x (len = %d, captured = %d)\n", config.name, config.type, local_buf[6], local_buf[7], local_buf[8], local_buf[9], local_buf[10], local_buf[11], local_buf[0], local_buf[1], local_buf[2], local_buf[3], local_buf[4], local_buf[5], pkt_len, cap_len); // Yes. Build a flow sample and send it off... SFL_FLOW_SAMPLE_TYPE fs; memset(&fs, 0, sizeof(fs)); if (hdr->ifindex_in) fs.input = hdr->ifindex_in; else if (sp->ifIndex_Type && direction == SFL_DIRECTION_IN) { switch (sp->ifIndex_Type) { case IFINDEX_STATIC: fs.input = sp->counters[idx].ifIndex; break; case IFINDEX_TAG: fs.input = hdr->tag; break; case IFINDEX_TAG2: fs.input = hdr->tag2; break; default: fs.input = 0x3FFFFFFF; break; } } else fs.input = 0x3FFFFFFF; if (hdr->ifindex_out) fs.output = hdr->ifindex_out; else if (sp->ifIndex_Type && direction == SFL_DIRECTION_OUT) { switch (sp->ifIndex_Type) { case IFINDEX_STATIC: fs.output = sp->counters[idx].ifIndex; break; case IFINDEX_TAG: fs.output = hdr->tag; break; case IFINDEX_TAG2: fs.output = hdr->tag2; break; default: fs.output = 0x3FFFFFFF; break; } } else fs.output = 0x3FFFFFFF; memset(&hdrElem, 0, sizeof(hdrElem)); hdrElem.tag = SFLFLOW_HEADER; if (!ethType) hdrElem.flowType.header.header_protocol = SFLHEADER_ETHERNET_ISO8023; else { switch (ntohs(ethType)) { case ETHERTYPE_IP: hdrElem.flowType.header.header_protocol = SFLHEADER_IPv4; break; case ETHERTYPE_IPV6: hdrElem.flowType.header.header_protocol = SFLHEADER_IPv6; break; default: hdrElem.flowType.header.header_protocol = SFLHEADER_ETHERNET_ISO8023; break; } } // the FCS trailing bytes should be counted in the frame_length // but they should also be recorded in the "stripped" field. // assume that libpcap is not giving us the FCS frame_len = pkt_len; if (config.acct_type == ACCT_PM) { u_int32_t FCS_bytes = 4; hdrElem.flowType.header.frame_length = frame_len + FCS_bytes; hdrElem.flowType.header.stripped = FCS_bytes; } else hdrElem.flowType.header.frame_length = frame_len; header_len = cap_len; if (header_len > frame_len) header_len = frame_len; if (header_len > sp->snaplen) header_len = sp->snaplen; hdrElem.flowType.header.header_length = header_len; hdrElem.flowType.header.header_bytes = (u_int8_t *)local_buf; SFLADD_ELEMENT(&fs, &hdrElem); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) { memset(&class2HdrElem, 0, sizeof(class2HdrElem)); class2HdrElem.tag = SFLFLOW_EX_CLASS2; class2HdrElem.flowType.ndpi_class.id.master_protocol = hdr->ndpi_class.master_protocol; class2HdrElem.flowType.ndpi_class.id.app_protocol = hdr->ndpi_class.app_protocol; SFLADD_ELEMENT(&fs, &class2HdrElem); } #endif if (config.what_to_count & (COUNT_TAG|COUNT_TAG2)) { memset(&tagHdrElem, 0, sizeof(tagHdrElem)); tagHdrElem.tag = SFLFLOW_EX_TAG; tagHdrElem.flowType.tag.tag = hdr->tag; tagHdrElem.flowType.tag.tag2 = hdr->tag2; SFLADD_ELEMENT(&fs, &tagHdrElem); } /* Extended gateway is meant to have a broad range of informations; we will fill in only infos pertaining to src and dst ASNs */ if (config.networks_file || config.nfacctd_as == NF_AS_BGP) { memset(&gatewayHdrElem, 0, sizeof(gatewayHdrElem)); memset(&as_path_segment, 0, sizeof(as_path_segment)); gatewayHdrElem.tag = SFLFLOW_EX_GATEWAY; // gatewayHdrElem.flowType.gateway.src_as = htonl(hdr->src_ip.address.ipv4.s_addr); gatewayHdrElem.flowType.gateway.src_as = hdr->src_as; if (hdr->dst_as == 0) { gatewayHdrElem.flowType.gateway.dst_as_path_segments = 0; } else { gatewayHdrElem.flowType.gateway.dst_as_path_segments = 1; gatewayHdrElem.flowType.gateway.dst_as_path = &as_path_segment; as_path_segment.type = SFLEXTENDED_AS_SET; as_path_segment.length = 1; as_path_segment.as.set = &hdr->dst_as; } if (config.what_to_count & COUNT_PEER_DST_IP) { switch (hdr->bgp_next_hop.family) { case AF_INET: gatewayHdrElem.flowType.gateway.nexthop.type = SFLADDRESSTYPE_IP_V4; memcpy(&gatewayHdrElem.flowType.gateway.nexthop.address.ip_v4, &hdr->bgp_next_hop.address.ipv4, 4); break; case AF_INET6: gatewayHdrElem.flowType.gateway.nexthop.type = SFLADDRESSTYPE_IP_V6; memcpy(&gatewayHdrElem.flowType.gateway.nexthop.address.ip_v6, &hdr->bgp_next_hop.address.ipv6, 16); break; default: memset(&gatewayHdrElem.flowType.gateway.nexthop, 0, sizeof(routerHdrElem.flowType.router.nexthop)); break; } } SFLADD_ELEMENT(&fs, &gatewayHdrElem); } if (config.what_to_count & (COUNT_SRC_NMASK|COUNT_DST_NMASK)) { memset(&routerHdrElem, 0, sizeof(routerHdrElem)); routerHdrElem.tag = SFLFLOW_EX_ROUTER; routerHdrElem.flowType.router.src_mask = hdr->src_nmask; routerHdrElem.flowType.router.dst_mask = hdr->dst_nmask; SFLADD_ELEMENT(&fs, &routerHdrElem); } if (config.what_to_count & (COUNT_VLAN|COUNT_COS)) { memset(&switchHdrElem, 0, sizeof(switchHdrElem)); switchHdrElem.tag = SFLFLOW_EX_SWITCH; if (direction == SFL_DIRECTION_IN) { switchHdrElem.flowType.sw.src_vlan = hdr->vlan; switchHdrElem.flowType.sw.src_priority = hdr->priority; } else if (direction == SFL_DIRECTION_OUT) { switchHdrElem.flowType.sw.dst_vlan = hdr->vlan; switchHdrElem.flowType.sw.dst_priority = hdr->priority; } SFLADD_ELEMENT(&fs, &switchHdrElem); } // submit the sample to be encoded and sent out - that's all there is to it(!) sfl_sampler_writeFlowSample(sp->sampler, &fs); } } /*_________________---------------------------__________________ _________________ process_config_options __________________ -----------------___________________________------------------ */ static void process_config_options(SflSp *sp) { if (config.nfprobe_ifindex_type) sp->ifIndex_Type = config.nfprobe_ifindex_type; if (config.nfprobe_ifindex) sp->counters[0].ifIndex = config.nfprobe_ifindex; if (config.sfprobe_ifspeed) sp->ifSpeed = config.sfprobe_ifspeed; if (config.sfprobe_agentip) str_to_addr(config.sfprobe_agentip, &sp->agentIP); if (config.sfprobe_agentsubid) sp->agentSubId = config.sfprobe_agentsubid; if (config.sfprobe_receiver) { struct sockaddr_storage dest; socklen_t dest_len = sizeof(dest); parse_hostport(config.sfprobe_receiver, (struct sockaddr *)&dest, &dest_len); sa_to_addr((struct sockaddr *) &dest, &sp->collectorIP, &sp->collectorPort); } if (config.sampling_rate) sp->samplingRate = config.sampling_rate; else if (config.ext_sampling_rate) sp->samplingRate = config.ext_sampling_rate; } /*_________________---------------------------__________________ _________________ sfprobe_plugin __________________ -----------------___________________________------------------ */ #define NF_NET_NEW 0x00000002 void sfprobe_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_payload *hdr; struct pkt_data dummy; struct pkt_bgp_primitives dummy_pbgp; struct pollfd pfd; unsigned char *pipebuf, *pipebuf_ptr; int refresh_timeout, ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct networks_file_data nfd; time_t clk, test_clk; SflSp sp; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memset(&sp, 0, sizeof(sp)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); memcpy(&config, cfgptr, sizeof(struct configuration)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "sFlow Probe Plugin", config.name); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } reload_map = FALSE; /* signal handling */ signal(SIGINT, sfprobe_exit_now); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); /* ****** sFlow part starts here ****** */ setDefaults(&sp); process_config_options(&sp); // create the agent and sampler objects init_agent(&sp); // initialize the clock so we can detect second boundaries clk = time(NULL); /* ****** sFlow part ends here ****** */ { char dest_str[INET6_ADDRSTRLEN]; addr_to_str(dest_str, &sp.collectorIP); Log(LOG_INFO, "INFO ( %s/%s ): Exporting flows to [%s]:%d\n", config.name, config.type, dest_str, sp.collectorPort); Log(LOG_INFO, "INFO ( %s/%s ): Sampling at: 1/%d\n", config.name, config.type, sp.samplingRate); } memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&dummy, 0, sizeof(dummy)); if (config.networks_file) { config.what_to_count |= (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SRC_NMASK|COUNT_DST_NMASK); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); } pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); refresh_timeout = 60 * 1000; /* 1 min */ #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif for (;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret < 0) goto poll_again; poll_ops: if (reload_map) { load_networks(config.networks_file, &nt, &nc); reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } if (ret > 0) { /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto handle_tick; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif hdr = (struct pkt_payload *) (pipebuf+ChBufHdrSz); pipebuf_ptr = (unsigned char *) pipebuf+ChBufHdrSz+PpayloadSz; if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { if (config.networks_file) { memset(&dummy.primitives, 0, sizeof(dummy.primitives)); memset(&dummy_pbgp, 0, sizeof(dummy_pbgp)); memcpy(&dummy.primitives.src_ip, &hdr->src_ip, HostAddrSz); memcpy(&dummy.primitives.dst_ip, &hdr->dst_ip, HostAddrSz); dummy.primitives.src_nmask = hdr->src_nmask; dummy.primitives.dst_nmask = hdr->dst_nmask; for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &dummy.primitives, &dummy_pbgp, &nfd); /* hacky */ if (config.nfacctd_as & NF_AS_NEW && dummy.primitives.src_as) hdr->src_as = dummy.primitives.src_as; if (config.nfacctd_as & NF_AS_NEW && dummy.primitives.dst_as) hdr->dst_as = dummy.primitives.dst_as; if (config.nfacctd_net & NF_NET_NEW && dummy.primitives.src_nmask) hdr->src_nmask = dummy.primitives.src_nmask; if (config.nfacctd_net & NF_NET_NEW && dummy.primitives.dst_nmask) hdr->dst_nmask = dummy.primitives.dst_nmask; if (config.nfacctd_net & NF_NET_NEW && dummy_pbgp.peer_dst_ip.family) memcpy(&hdr->bgp_next_hop, &dummy_pbgp.peer_dst_ip, sizeof(struct host_addr)); } readPacket(&sp, hdr, pipebuf_ptr); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { #if ! NEED_ALIGN pipebuf_ptr += hdr->cap_len; #else uint32_t tmp = hdr->cap_len; if ( ( tmp%4 ) != 0 ) tmp = ( tmp + 4 ) & 4; pipebuf_ptr += tmp; #endif hdr = (struct pkt_payload *) pipebuf_ptr; pipebuf_ptr += PpayloadSz; } } recv_budget++; goto read_data; } handle_tick: test_clk = time(NULL); while(clk < test_clk) sfl_agent_tick(sp.agent, clk++); } } pmacct-1.7.8/src/pretag.c0000644000175000017500000014476514354105275014250 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "nfacctd.h" #include "pretag_handlers.h" #include "pretag-data.h" #include "plugin_hooks.h" #include "tee_plugin/tee_recvs.h" #include "tee_plugin/tee_recvs-data.h" #include "isis/isis.h" #include "isis/isis-data.h" #include "bgp/bgp_xcs.h" #include "bgp/bgp_xcs-data.h" #include "crc32.h" #include "pmacct-data.h" //Global variables int bpas_map_allocated; int blp_map_allocated; int bmed_map_allocated; int biss_map_allocated; int bta_map_allocated; int bitr_map_allocated; int sampling_map_allocated; int custom_primitives_allocated; int bta_map_caching; int sampling_map_caching; int (*find_id_func)(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); /* XXX: load_id_file() interface cleanup pending: - if a table is tag-related then it is passed as argument t - else it is passed as argument req->key_value_table */ void load_id_file(int acct_type, char *filename, struct id_table *t, struct plugin_requests *req, int *map_allocated) { struct id_table tmp; struct id_entry *ptr; FILE *file; char *buf = NULL; int v4_num = 0, x, tot_lines = 0, err, errs = 0, index, label_solved; int ignoring, report = TRUE, map_entries, map_row_len; struct stat st; int v6_num = 0; u_int64_t sz; if (!filename || !map_allocated) return; if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM || acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_TO_XFLOW_AGENT || acct_type == MAP_BGP_SRC_LOCAL_PREF || acct_type == MAP_BGP_SRC_MED || acct_type == MAP_FLOW_TO_RD || acct_type == MAP_SAMPLING || acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE) { req->key_value_table = (void *) &tmp; } /* parsing engine vars */ char *start, *key = NULL, *value = NULL; int len; Log(LOG_INFO, "INFO ( %s/%s ): [%s] (re)loading map.\n", config.name, config.type, filename); memset(&st, 0, sizeof(st)); memset(&tmp, 0, sizeof(struct id_table)); if (req->map_entries) map_entries = req->map_entries; else if (config.maps_entries) map_entries = config.maps_entries; else map_entries = MAX_PRETAG_MAP_ENTRIES; if (req->map_row_len) map_row_len = req->map_row_len; else if (config.maps_row_len) map_row_len = config.maps_row_len; else { if (acct_type == MAP_IGP) map_row_len = LARGEBUFLEN; else map_row_len = SRVBUFLEN; } buf = (char *) malloc(map_row_len); if (!buf) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (readbuf: %u chars).\n", config.name, config.type, filename, map_row_len); goto handle_error; } memset(buf, 0, map_row_len); if (filename) { if ((file = fopen(filename, "r")) == NULL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); goto handle_error; } sz = sizeof(struct id_entry) * map_entries; if (t) { if (*map_allocated == 0) { memset(t, 0, sizeof(struct id_table)); t->e = (struct id_entry *) malloc(sz); if (!t->e) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename); goto handle_error; } *map_allocated = TRUE; } else { ptr = t->e ; /* freeing up resources before memset() */ if (config.maps_index && pretag_index_have_one(t)) { pretag_index_destroy(t); } for (index = 0; index < t->num; index++) { pcap_freecode(&t->e[index].key.filter); pretag_free_label(&t->e[index].label); if (t->e[index].jeq.label) free(t->e[index].jeq.label); if (t->e[index].entry_label) free(t->e[index].entry_label); } cdada_map_destroy(t->label_map_v4); cdada_map_destroy(t->label_map_v6); memset(t, 0, sizeof(struct id_table)); t->e = ptr ; } } else { *map_allocated = TRUE; } tmp.e = (struct id_entry *) malloc(sz); if (!tmp.e) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename); goto handle_error; } memset(tmp.e, 0, sz); if (t) memset(t->e, 0, sz); if (acct_type == MAP_IGP) igp_daemon_map_initialize(filename, req); if (acct_type == MAP_CUSTOM_PRIMITIVES) custom_primitives_map_initialize(); /* first stage: reading Agent ID file and arranging it in a temporary memory table */ while (!feof(file)) { ignoring = FALSE; req->line_num = ++tot_lines; if (tmp.num >= map_entries) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file cut to the first %u entries. Number of entries can be configured via 'maps_entries'.\n", config.name, config.type, filename, map_entries); break; } memset(buf, 0, map_row_len); if (fgets(buf, map_row_len, file)) { if (!iscomment(buf) && !isblankline(buf)) { if (strlen(buf) == (map_row_len-1) && !strchr(buf, '\n')) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] line too long (max %u chars). Ignored.\n", config.name, config.type, filename, tot_lines, map_row_len); continue; } if (!check_not_valid_char(filename, buf, '|')) { mark_columns(buf); trim_all_spaces(buf); strip_quotes(buf); /* resetting the entry and enforcing defaults */ if (acct_type == MAP_IGP) memset(&ime, 0, sizeof(ime)); memset(&tmp.e[tmp.num], 0, sizeof(struct id_entry)); tmp.e[tmp.num].ret = FALSE; err = FALSE; key = NULL; value = NULL; start = buf; len = strlen(buf); for (x = 0; x <= len; x++) { if (buf[x] == '=') { if (start == &buf[x]) continue; if (!key) { buf[x] = '\0'; key = start; x++; start = &buf[x]; } } if ((buf[x] == '|') || (buf[x] == '\0')) { if (start == &buf[x]) continue; buf[x] = '\0'; if (value || !key) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] malformed line. Ignored.\n", config.name, config.type, filename, tot_lines); err = TRUE; break; } else value = start; x++; start = &buf[x]; } if (key && value) { int dindex; /* dictionary index */ /* Processing of source BGP-related primitives kept consistent; This can indeed be split as required in future */ if (acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_SRC_LOCAL_PREF || acct_type == MAP_BGP_SRC_MED) { for (dindex = 0; strcmp(bpas_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(bpas_map_dictionary[dindex].key, key)) { err = (*bpas_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_BGP_TO_XFLOW_AGENT) { for (dindex = 0; strcmp(bta_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(bta_map_dictionary[dindex].key, key)) { err = (*bta_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_FLOW_TO_RD) { for (dindex = 0; strcmp(bitr_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(bitr_map_dictionary[dindex].key, key)) { err = (*bitr_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_SAMPLING) { for (dindex = 0; strcmp(sampling_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(sampling_map_dictionary[dindex].key, key)) { err = (*sampling_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_TEE_RECVS) { for (dindex = 0; strcmp(tee_recvs_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(tee_recvs_map_dictionary[dindex].key, key)) { err = (*tee_recvs_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_BGP_XCS) { for (dindex = 0; strcmp(bgp_xcs_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(bgp_xcs_map_dictionary[dindex].key, key)) { err = (*bgp_xcs_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == MAP_IGP) { for (dindex = 0; strcmp(igp_daemon_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(igp_daemon_map_dictionary[dindex].key, key)) { err = (*igp_daemon_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); ignoring = TRUE; } } key = NULL; value = NULL; } else if (acct_type == MAP_CUSTOM_PRIMITIVES) { for (dindex = 0; strcmp(custom_primitives_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(custom_primitives_map_dictionary[dindex].key, key)) { err = (*custom_primitives_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); ignoring = TRUE; break; } key = NULL; value = NULL; } else if (acct_type == MAP_PCAP_INTERFACES) { for (dindex = 0; strcmp(pm_pcap_interfaces_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(pm_pcap_interfaces_map_dictionary[dindex].key, key)) { err = (*pm_pcap_interfaces_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else if (acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE) { for (dindex = 0; strcmp(tag_map_nonflow_dictionary[dindex].key, ""); dindex++) { if (!strcmp(tag_map_nonflow_dictionary[dindex].key, key)) { err = (*tag_map_nonflow_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } else { /* ACCT_NF, ACCT_SF, ACCT_PM, etc. */ if (tee_plugins) { for (dindex = 0; strcmp(tag_map_tee_dictionary[dindex].key, ""); dindex++) { if (!strcmp(tag_map_tee_dictionary[dindex].key, key)) { err = (*tag_map_tee_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } } else { for (dindex = 0; strcmp(tag_map_dictionary[dindex].key, ""); dindex++) { if (!strcmp(tag_map_dictionary[dindex].key, key)) { err = (*tag_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type); break; } else err = E_NOTFOUND; /* key not found */ } } if (err) { if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n", config.name, config.type, filename, tot_lines, key); else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines); break; } key = NULL; value = NULL; } } } if (!ignoring) { /* verifying errors and required fields */ if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE) { if (tmp.e[tmp.num].id && tmp.e[tmp.num].id2 && tmp.e[tmp.num].label.len) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] set_tag (id), set_tag2 (id2) and set_label are mutual exclusive. Line ignored.\n", config.name, config.type, filename, tot_lines); else if (!err) { int j, z, recirculate; struct id_entry recirc_e; recirculate = FALSE; recirculate_ipv6: if (!tmp.e[tmp.num].key.agent_ip.a.family) { if (!recirculate) { memset(&tmp.e[tmp.num].key.agent_ip, 0, sizeof(pt_hostaddr_t)); memset(&tmp.e[tmp.num].key.agent_mask, 0, sizeof(pt_hostmask_t)); tmp.e[tmp.num].key.agent_ip.a.family = AF_INET; tmp.e[tmp.num].key.agent_mask.family = AF_INET; memcpy(&recirc_e, &tmp.e[tmp.num], sizeof(struct id_entry)); /* If indexing is enabled and no address family is specified for 'ip' (ie. 'ip' is likely not specified), we will not include it as part of the index hash serializer anyway; we can skip recirculation. */ if (!config.maps_index) { recirculate = TRUE; } } else { memcpy(&tmp.e[tmp.num], &recirc_e, sizeof(struct id_entry)); tmp.e[tmp.num].key.agent_ip.a.family = AF_INET6; tmp.e[tmp.num].key.agent_mask.family = AF_INET6; if (recirc_e.label.val) { memset(&tmp.e[tmp.num].label, 0, sizeof(pt_label_t)); pretag_copy_label(&tmp.e[tmp.num].label, &recirc_e.label); } recirculate = FALSE; } } for (j = 0; tmp.e[tmp.num].func[j]; j++); for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) { tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z]; tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z]; } if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++; else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++; tmp.num++; if (recirculate) { if (tmp.num < map_entries) goto recirculate_ipv6; } } /* if any required field is missing and other errors have been signalled before we will trap an error message */ } else if (acct_type == ACCT_PM) { if (tmp.e[tmp.num].id && tmp.e[tmp.num].id2 && tmp.e[tmp.num].label.len) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] set_tag (id), set_tag2 (id2) and set_label are mutual exclusive. Line ignored.\n", config.name, config.type, filename, tot_lines); else if (tmp.e[tmp.num].key.agent_ip.a.family) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] key 'ip' not applicable. Line ignored.\n", config.name, config.type, filename, tot_lines); else if (!err) { int j, z; for (j = 0; tmp.e[tmp.num].func[j]; j++); for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) { tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z]; tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z]; } tmp.e[tmp.num].key.agent_ip.a.family = AF_INET; /* we emulate a dummy '0.0.0.0' IPv4 address */ v4_num++; tmp.num++; } } else if (acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_SRC_LOCAL_PREF || acct_type == MAP_BGP_SRC_MED) { if (!err && (tmp.e[tmp.num].id || tmp.e[tmp.num].flags) && tmp.e[tmp.num].key.agent_ip.a.family) { int j; for (j = 0; tmp.e[tmp.num].func[j]; j++); tmp.e[tmp.num].func[j] = pretag_id_handler; if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++; else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++; tmp.num++; } else if ((!tmp.e[tmp.num].id || !tmp.e[tmp.num].key.agent_ip.a.family) && !err) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n", config.name, config.type, filename, tot_lines); } else if (acct_type == MAP_BGP_TO_XFLOW_AGENT) { if (!err && (tmp.e[tmp.num].id || tmp.e[tmp.num].id2) && tmp.e[tmp.num].key.agent_ip.a.family) { int j, z; for (j = 0; tmp.e[tmp.num].func[j]; j++); for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) { tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z]; tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z]; } /* imposing pretag_id_handler to be the last one */ tmp.e[tmp.num].func[j] = pretag_id_handler; if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++; else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++; tmp.num++; } else if (((!tmp.e[tmp.num].id && !tmp.e[tmp.num].id2) || !tmp.e[tmp.num].key.agent_ip.a.family) && !err) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n", config.name, config.type, filename, tot_lines); } else if (acct_type == MAP_FLOW_TO_RD) { if (!err && tmp.e[tmp.num].id && tmp.e[tmp.num].key.agent_ip.a.family) { int j; for (j = 0; tmp.e[tmp.num].func[j]; j++); tmp.e[tmp.num].func[j] = pretag_id_handler; if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++; else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++; tmp.num++; } } else if (acct_type == MAP_SAMPLING) { if (!err && tmp.e[tmp.num].id && tmp.e[tmp.num].key.agent_ip.a.family) { int j; for (j = 0; tmp.e[tmp.num].func[j]; j++); tmp.e[tmp.num].func[j] = pretag_id_handler; if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++; else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++; tmp.num++; } else if ((!tmp.e[tmp.num].id || !tmp.e[tmp.num].key.agent_ip.a.family) && !err) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n", config.name, config.type, filename, tot_lines); } else if (acct_type == MAP_TEE_RECVS) tee_recvs_map_validate(filename, tot_lines, req); else if (acct_type == MAP_BGP_XCS) bgp_xcs_map_validate(filename, req); else if (acct_type == MAP_IGP) igp_daemon_map_validate(filename, req); else if (acct_type == MAP_CUSTOM_PRIMITIVES) custom_primitives_map_validate(filename, req); else if (acct_type == MAP_PCAP_INTERFACES) pm_pcap_interfaces_map_validate(filename, req); } } else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] malformed line. Ignored.\n", config.name, config.type, filename, tot_lines); } } } fclose(file); if (acct_type == MAP_IGP) igp_daemon_map_finalize(filename, req); if (t) { stat(filename, &st); t->timestamp = st.st_mtime; /* second stage: segregating IPv4, IPv6. No further reordering in order to deal smoothly with jumps (ie. JEQs) */ x = 0; t->type = acct_type; t->num = tmp.num; t->ipv4_num = v4_num; t->ipv4_base = &t->e[x]; t->flags = tmp.flags; { pm_id_t pm_cdada_map_container; t->label_map_v4 = cdada_map_create(pm_cdada_map_container); t->label_map_v6 = cdada_map_create(pm_cdada_map_container); if (!t->label_map_v4 || !t->label_map_v6) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] unable to allocate Label Map. Exiting.\n", config.name, config.type, t->filename); exit_gracefully(1); } } for (index = 0; index < tmp.num; index++) { if (tmp.e[index].key.agent_ip.a.family == AF_INET) { memcpy(&t->e[x], &tmp.e[index], sizeof(struct id_entry)); t->e[x].pos = x; if (t->e[x].entry_label) { int ret; pm_id_t *idx_value; ret = cdada_map_find(t->label_map_v4, t->e[x].entry_label, (void **) &idx_value); if (ret == CDADA_E_NOT_FOUND) { ret = cdada_map_insert(t->label_map_v4, t->e[x].entry_label, &t->e[x].pos); if (ret != CDADA_SUCCESS) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] unable to insert in Label Map v4. Exiting.\n", config.name, config.type, t->filename); exit_gracefully(1); } } } x++; } } t->ipv6_num = v6_num; t->ipv6_base = &t->e[x]; for (index = 0; index < tmp.num; index++) { if (tmp.e[index].key.agent_ip.a.family == AF_INET6) { memcpy(&t->e[x], &tmp.e[index], sizeof(struct id_entry)); t->e[x].pos = x; if (t->e[x].entry_label) { int ret; pm_id_t *idx_value; ret = cdada_map_find(t->label_map_v6, t->e[x].entry_label, (void **) &idx_value); if (ret == CDADA_E_NOT_FOUND) { ret = cdada_map_insert(t->label_map_v6, t->e[x].entry_label, &t->e[x].pos); if (ret != CDADA_SUCCESS) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] unable to insert in Label Map v6. Exiting.\n", config.name, config.type, t->filename); exit_gracefully(1); } } } x++; } } /* third stage: building short circuits basing on jumps and labels. Only forward references are solved. Backward and unsolved references will generate errors. */ for (ptr = t->ipv4_base, x = 0; x < t->ipv4_num; ptr++, x++) { if (ptr->jeq.label) { label_solved = FALSE; /* honouring reserved labels (ie. "next"). Then resolving unknown labels */ if (!strcmp(ptr->jeq.label, "next")) { ptr->jeq.ptr = ptr+1; label_solved = TRUE; } else { int ret; pm_id_t *idx_value; ret = cdada_map_find(t->label_map_v4, ptr->jeq.label, (void **) &idx_value); if (ret == CDADA_SUCCESS) { if ((*idx_value) > ptr->pos) { ptr->jeq.ptr = &t->e[(*idx_value)]; label_solved = TRUE; } } } if (!label_solved) { ptr->jeq.ptr = NULL; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unresolved label '%s'. Ignoring it.\n", config.name, config.type, filename, ptr->jeq.label); } } } for (ptr = t->ipv6_base, x = 0; x < t->ipv6_num; ptr++, x++) { if (ptr->jeq.label) { int ret; pm_id_t *idx_value; label_solved = FALSE; ret = cdada_map_find(t->label_map_v6, ptr->jeq.label, (void **) &idx_value); if (ret == CDADA_SUCCESS) { if ((*idx_value) > ptr->pos) { ptr->jeq.ptr = &t->e[(*idx_value)]; label_solved = TRUE; } } if (!label_solved) { ptr->jeq.ptr = NULL; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unresolved label '%s'. Ignoring it.\n", config.name, config.type, filename, ptr->jeq.label); } } } t->filename = filename; /* pre_tag_map indexing here */ if (config.maps_index && (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM || acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_FLOW_TO_RD || acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE)) { pt_bitmap_t idx_bmap; t->index_num = MAX_ID_TABLE_INDEXES; for (ptr = t->ipv4_base, x = 0; x < (t->ipv4_num + t->ipv6_num); ptr++, x++) { idx_bmap = pretag_index_build_bitmap(ptr, acct_type); /* insert bitmap to index list and determine entries per index */ if (pretag_index_insert_bitmap(t, idx_bmap)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Out of indexes. Indexing disabled.\n", config.name, config.type, filename); pretag_index_destroy(t); break; } } /* set handlers */ pretag_index_set_handlers(t); /* allocate indexes */ pretag_index_allocate(t); for (ptr = t->ipv4_base, x = 0; x < (t->ipv4_num + t->ipv6_num); ptr++, x++) { idx_bmap = pretag_index_build_bitmap(ptr, acct_type); /* fill indexes */ err = pretag_index_fill(t, idx_bmap, ptr, x); if (err == PRETAG_IDX_ERR_FATAL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Fatal error. Indexing disabled.\n", config.name, config.type, filename); pretag_index_destroy(t); errs++; report = FALSE; break; } else if (err) { errs++; } } } if (errs && t->flags & PRETAG_FLAG_JEQ) { /* in case of fatal error, index was already destroyed */ if (err != PRETAG_IDX_ERR_FATAL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'jeq' not supported if error count is non-zero when loading. Indexing disabled.\n", config.name, config.type, filename); pretag_index_destroy(t); } report = FALSE; } if (t->flags & PRETAG_FLAG_NEG) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Negations not supported. Indexing disabled.\n", config.name, config.type, filename); pretag_index_destroy(t); report = FALSE; } if (pretag_index_validate_dedup_netmask_lists(t) == ERR) { pretag_index_destroy(t); report = FALSE; } if (report) { pretag_index_report(t); } } } if (tmp.e) free(tmp.e) ; if (buf) free(buf) ; Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, config.type, filename); return; handle_error: if (*map_allocated && tmp.e) free(tmp.e) ; if (buf) free(buf); if (t && t->timestamp) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back old map.\n", config.name, config.type, filename); /* we update the timestamp to avoid loops */ stat(filename, &st); t->timestamp = st.st_mtime; } else exit_gracefully(1); } u_int8_t pt_check_neg(char **value, u_int32_t *flags) { if (**value == '-') { (*value)++; if (flags) { *flags |= PRETAG_FLAG_NEG; } return TRUE; } else return FALSE; } void pt_set_jeq(u_int32_t *flags) { if (flags) { *flags |= PRETAG_FLAG_JEQ; } } char *pt_check_range(char *str) { char *ptr; if ((ptr = strchr(str, '-'))) { *ptr = '\0'; ptr++; return ptr; } else return NULL; } void load_pre_tag_map(int acct_type, char *filename, struct id_table *t, struct plugin_requests *req, int *map_allocated, int map_entries, int map_row_len) { if (req) { req->map_entries = map_entries; req->map_row_len = map_row_len; } load_id_file(acct_type, filename, t, req, map_allocated); if (req) { req->map_entries = FALSE; req->map_row_len = FALSE; } } void pretag_init_vars(struct packet_ptrs *pptrs, struct id_table *t) { if (!pptrs) return; if (t->type == ACCT_NF) memset(&pptrs->set_tos, 0, sizeof(s_uint8_t)); if (t->type == MAP_BGP_TO_XFLOW_AGENT) memset(&pptrs->lookup_bgp_port, 0, sizeof(s_uint16_t)); if (pptrs->label.val) { pretag_free_label(&pptrs->label); pptrs->have_label = FALSE; } } void pretag_init_label(pt_label_t *label) { if (!label) return; memset(label, 0, sizeof(pt_label_t)); } int pretag_malloc_label(pt_label_t *label, int len) { if (!label) return ERR; label->val = malloc(len); if (!label->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_malloc_label).\n", config.name, config.type); return ERR; } label->len = len; return SUCCESS; } int pretag_realloc_label(pt_label_t *label, int old_len, int add_len) { char *local_val = NULL; if (!label) return ERR; local_val = malloc((old_len + add_len)); if (!local_val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_realloc_label).\n", config.name, config.type); return ERR; } memset(local_val, 0, (old_len + add_len)); strcpy(local_val, label->val); free(label->val); label->val = local_val; label->len = (old_len + add_len); return SUCCESS; } int pretag_copy_label(pt_label_t *dst, pt_label_t *src) { if (!src || !dst) return ERR; if (dst->val) { Log(LOG_WARNING, "WARN ( %s/%s ): pretag_copy_label failed: dst->val not null\n", config.name, config.type); return ERR; } else { if (src->len) { pretag_malloc_label(dst, src->len + 1); if (!dst->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_copy_label).\n", config.name, config.type); return ERR; } strncpy(dst->val, src->val, src->len); dst->val[dst->len - 1] = '\0'; } } return SUCCESS; } int pretag_move_label(pt_label_t *dst, pt_label_t *src) { if (!src || !dst) return ERR; if (dst->val) { Log(LOG_WARNING, "WARN ( %s/%s ): pretag_move_label failed: dst->val not null\n", config.name, config.type); return ERR; } else { if (src->len) { dst->val = src->val; dst->len = src->len; src->val = NULL; src->len = 0; } } return SUCCESS; } int pretag_append_label(pt_label_t *dst, pt_label_t *src) { if (!src || !dst) return ERR; if (!dst->val) { Log(LOG_WARNING, "WARN ( %s/%s ): pretag_append_label failed: dst->val null\n", config.name, config.type); return ERR; } else { if (src->len) { pretag_realloc_label(dst, dst->len, (src->len + 1 /* sep */ + 1 /* null */)); if (!dst->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_append_label).\n", config.name, config.type); return ERR; } strcat(dst->val, DEFAULT_SEP); strncat(dst->val, src->val, src->len); dst->val[dst->len - 1] = '\0'; } } return SUCCESS; } void pretag_free_label(pt_label_t *label) { if (label && label->val) { free(label->val); label->val = NULL; label->len = 0; } } int pretag_entry_process(struct id_entry *e, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2) { int j = 0; pm_id_t id = 0, stop = 0, ret = 0; pt_label_t *label_local = malloc(sizeof(pt_label_t)); pretag_init_label(label_local); e->last_matched = FALSE; for (j = 0, stop = 0, ret = 0; ((!ret || ret > TRUE) && (*e->func[j])); j++) { if (e->func_type[j] == PRETAG_SET_LABEL) { ret = (*e->func[j])(pptrs, label_local, e); } else { ret = (*e->func[j])(pptrs, &id, e); } if (ret > TRUE) stop |= ret; else stop = ret; } if (!stop || stop > TRUE) { if (stop & PRETAG_MAP_RCODE_ID) { if (e->stack.func) id = (*e->stack.func)(id, *tag); *tag = id; pptrs->have_tag = TRUE; } else if (stop & PRETAG_MAP_RCODE_ID2) { if (e->stack.func) id = (*e->stack.func)(id, *tag2); *tag2 = id; pptrs->have_tag2 = TRUE; } else if (stop & PRETAG_MAP_RCODE_LABEL) { if (pptrs->label.len) { pretag_append_label(&pptrs->label, label_local); } else { pretag_copy_label(&pptrs->label, label_local); } pptrs->have_label = TRUE; } else if (stop == BTA_MAP_RCODE_ID_ID2) { // stack not applicable here *tag = id; *tag2 = e->id2; pptrs->have_tag = TRUE; pptrs->have_tag2 = TRUE; } if (e->jeq.ptr) { if (e->ret) { exec_plugins(pptrs, NULL); set_shadow_status(pptrs); *tag = 0; *tag2 = 0; if (pptrs->label.val) pretag_free_label(&pptrs->label); pptrs->have_tag = FALSE; pptrs->have_tag2 = FALSE; pptrs->have_label = FALSE; } stop |= PRETAG_MAP_RCODE_JEQ; } } pretag_free_label(label_local); if (label_local) free(label_local); return stop; } pt_bitmap_t pretag_index_build_bitmap(struct id_entry *ptr, int acct_type) { pt_bitmap_t idx_bmap = 0; u_int32_t iterator = 0; for (; ptr->func[iterator]; iterator++) idx_bmap |= ptr->func_type[iterator]; /* 1) invalidate bitmap if we have fields incompatible with indexing */ if (idx_bmap & PRETAG_FILTER) return 0; /* 2) scrub bitmap: remove PRETAG_SET_* fields from the bitmap */ if (idx_bmap & PRETAG_SET_TOS) idx_bmap ^= PRETAG_SET_TOS; if (idx_bmap & PRETAG_SET_TAG) idx_bmap ^= PRETAG_SET_TAG; if (idx_bmap & PRETAG_SET_TAG2) idx_bmap ^= PRETAG_SET_TAG2; if (idx_bmap & PRETAG_SET_LABEL) idx_bmap ^= PRETAG_SET_LABEL; /* 3) handle the case of catch-all rule */ if (!idx_bmap) idx_bmap = PRETAG_NULL; return idx_bmap; } int pretag_index_insert_bitmap(struct id_table *t, pt_bitmap_t idx_bmap) { u_int32_t iterator = 0; if (!t) return TRUE; for (iterator = 0; iterator < t->index_num; iterator++) { if (!t->index[iterator].entries || t->index[iterator].bitmap == idx_bmap) { t->index[iterator].bitmap = idx_bmap; t->index[iterator].entries++; return FALSE; } } return TRUE; } int pretag_index_set_handlers(struct id_table *t) { pt_bitmap_t residual_idx_bmap = 0; u_int32_t index = 0, iterator = 0, handler_index = 0; if (!t) return TRUE; for (iterator = 0; iterator < t->index_num; iterator++) { residual_idx_bmap = t->index[iterator].bitmap; handler_index = 0; memset(t->index[iterator].idt_handler, 0, sizeof(t->index[iterator].idt_handler)); memset(t->index[iterator].fdata_handler, 0, sizeof(t->index[iterator].fdata_handler)); for (index = 0; tag_map_index_entries_dictionary[index].key; index++) { if (t->index[iterator].bitmap & tag_map_index_entries_dictionary[index].key) { t->index[iterator].idt_handler[handler_index] = (*tag_map_index_entries_dictionary[index].func); handler_index++; residual_idx_bmap ^= tag_map_index_entries_dictionary[index].key; } } handler_index = 0; /* we set foreign data handlers here but skip on the residual_idx_bmap */ for (index = 0; tag_map_index_fdata_dictionary[index].key; index++) { if (t->index[iterator].bitmap & tag_map_index_fdata_dictionary[index].key) { t->index[iterator].fdata_handler[handler_index] = (*tag_map_index_fdata_dictionary[index].func); handler_index++; } } if (residual_idx_bmap) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: not supported for field(s) %llx. Indexing disabled.\n", config.name, config.type, t->filename, (unsigned long long)residual_idx_bmap); pretag_index_destroy(t); } } return FALSE; } int pretag_index_allocate(struct id_table *t) { u_int32_t iterator = 0, i = 0, j = 0, z = 0; int destroy = FALSE; if (!t) return TRUE; for (iterator = 0; iterator < t->index_num; iterator++) { if (t->index[iterator].entries) { u_int32_t idx_entry_size = 0; Log(LOG_INFO, "INFO ( %s/%s ): [%s] maps_index: creating index %llx (%u entries).\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap, t->index[iterator].entries); assert(!t->index[iterator].idx_map); for (idx_entry_size = 0, i = 0; i < MAX_BITMAP_ENTRIES; i++) { if (!t->index[iterator].idt_handler[i]) { break; } for (j = 0; tag_map_index_entries_dictionary[j].key; j++) { if (t->index[iterator].idt_handler[i] == tag_map_index_entries_dictionary[j].func) { for (z = 0; tag_map_index_entries_size_dictionary[z].key; z++) { if (tag_map_index_entries_size_dictionary[z].key == tag_map_index_entries_dictionary[j].key) { idx_entry_size += tag_map_index_entries_size_dictionary[z].size; break; } } break; } } } if (idx_entry_size) { char pm_cdada_map_container[idx_entry_size]; hash_init_serial(&t->index[iterator].hash_serializer, idx_entry_size); t->index[iterator].idx_map = cdada_map_create(pm_cdada_map_container); if (!t->index[iterator].idx_map) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: unable to allocate index %llx. Destroying.\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap); destroy = TRUE; break; } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: null key for index %llx. Destroying.\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap); destroy = TRUE; break; } } } if (destroy) { pretag_index_destroy(t); return ERR; } return SUCCESS; } int pretag_index_fill(struct id_table *t, pt_bitmap_t idx_bmap, struct id_entry *ptr, int lineno) { u_int32_t iterator = 0, handler_index = 0; int ret = SUCCESS; if (!t) return PRETAG_IDX_ERR_FATAL; for (iterator = 0; iterator < t->index_num; iterator++) { if (t->index[iterator].entries && t->index[iterator].bitmap == idx_bmap) { pm_hash_serial_t *hash_serializer; pm_hash_key_t *hash_key; /* fill serializer in */ hash_serializer = &t->index[iterator].hash_serializer; hash_serial_set_off(hash_serializer, 0); hash_key = hash_serial_get_key(hash_serializer); if (!hash_key) return PRETAG_IDX_ERR_FATAL; for (handler_index = 0; t->index[iterator].idt_handler[handler_index]; handler_index++) { ret = (*t->index[iterator].idt_handler[handler_index])(&t->index[iterator], handler_index, hash_serializer, ptr); if (ret) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] pretag_index_fill(): index=%llx line=%d (err!)\n", config.name, config.type, t->filename, (unsigned long long)idx_bmap, (lineno + 1)); break; } } if (!ret) { ret = cdada_map_insert(t->index[iterator].idx_map, hash_key_get_val(hash_key), ptr); if (ret == CDADA_E_EXISTS) { u_char key_hexdump[hash_key_get_len(hash_key) * 3]; serialize_hex(hash_key_get_val(hash_key), key_hexdump, hash_key_get_len(hash_key)); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] pretag_index_fill(): index=%llx line=%d key=%s (dup!)\n", config.name, config.type, t->filename, (unsigned long long)idx_bmap, (lineno + 1), key_hexdump); ret = PRETAG_IDX_ERR_NONE; /* alias SUCCESS */ } } break; } } return ret; } int pretag_index_validate_dedup_netmask_lists(struct id_table *t) { u_int32_t iterator = 0; if (!t) return ERR; /* dedup */ for (iterator = 0; iterator < t->index_num; iterator++) { if (t->index[iterator].netmask.v4.list) { cdada_list_sort(t->index[iterator].netmask.v4.list); cdada_list_unique(t->index[iterator].netmask.v4.list); t->index[iterator].netmask.v4.size = cdada_list_size(t->index[iterator].netmask.v4.list); } if (t->index[iterator].netmask.v6.list) { cdada_list_sort(t->index[iterator].netmask.v6.list); cdada_list_unique(t->index[iterator].netmask.v6.list); t->index[iterator].netmask.v6.size = cdada_list_size(t->index[iterator].netmask.v6.list); } } return SUCCESS; } void pretag_index_print_key(const cdada_map_t *map, const void *key, void *value, void *opaque) { struct id_table_index *index = opaque; pm_hash_serial_t *hash_serializer; pm_hash_key_t *hash_key; u_int16_t hash_keylen; hash_serializer = &index->hash_serializer; hash_key = hash_serial_get_key(hash_serializer); hash_keylen = hash_key_get_len(hash_key); { u_char key_hexdump[hash_keylen * 3]; serialize_hex(key, key_hexdump, hash_keylen); Log(LOG_DEBUG, "DEBUG ( %s/%s ): pretag_index_print_key(): index=%llx key=%s\n", config.name, config.type, (unsigned long long)index->bitmap, key_hexdump); } } void pretag_index_report(struct id_table *t) { u_int32_t iterator = 0; if (!t) return; for (iterator = 0; iterator < t->index_num; iterator++) { if (t->index[iterator].entries) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] pretag_index_report(): index=%llx entries=%u\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap, cdada_map_size(t->index[iterator].idx_map)); if (t->index[iterator].netmask.v4.list) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] pretag_index_report(): index=%llx handler=%u netmask.v4.list_entries=%u\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap, t->index[iterator].netmask.hdlr_no, cdada_list_size(t->index[iterator].netmask.v4.list)); } if (t->index[iterator].netmask.v6.list) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] pretag_index_report(): index=%llx handler=%u netmask.v6.list_entries=%u\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap, t->index[iterator].netmask.hdlr_no, cdada_list_size(t->index[iterator].netmask.v6.list)); } if (config.debug) { cdada_map_traverse(t->index[iterator].idx_map, &pretag_index_print_key, &t->index[iterator]); } } } } void pretag_index_destroy(struct id_table *t) { pm_hash_serial_t *hash_serializer; pm_hash_key_t *hash_key; u_int32_t iterator = 0; if (!t) return; for (iterator = 0; iterator < t->index_num; iterator++) { hash_serializer = &t->index[iterator].hash_serializer; hash_key = hash_serial_get_key(hash_serializer); /* destroy the hash */ if (t->index[iterator].idx_map) { char pm_cdada_map_container[hash_key_get_len(hash_key)]; void *idx_map_val; Log(LOG_INFO, "INFO ( %s/%s ): [%s] maps_index: destroying index %llx.\n", config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap); while (cdada_map_first(t->index[iterator].idx_map, pm_cdada_map_container, &idx_map_val) == CDADA_SUCCESS) { cdada_map_erase(t->index[iterator].idx_map, pm_cdada_map_container); } cdada_map_destroy(t->index[iterator].idx_map); t->index[iterator].idx_map = NULL; } /* destroy the serializer */ hash_destroy_key(hash_key); /* destroy the lists */ if (t->index[iterator].netmask.v4.list) { cdada_list_destroy(t->index[iterator].netmask.v4.list); } if (t->index[iterator].netmask.v6.list) { cdada_list_destroy(t->index[iterator].netmask.v6.list); } /* cleanup */ memset(&t->index[iterator], 0, sizeof(struct id_table_index)); } t->index_num = 0; } u_int32_t pretag_index_lookup(struct id_table *t, struct packet_ptrs *pptrs, struct id_entry **index_results, int ir_entries) { struct id_entry res_fdata; pm_hash_serial_t *hash_serializer; pm_hash_key_t *hash_key; u_int32_t iterator, index_hdlr; int iterator_ir, netmask_idx, netmask_max, ret; void *idx_value = NULL; if (!t || !pptrs || !index_results) return 0; memset(&res_fdata, 0, sizeof(res_fdata)); memset(index_results, 0, (sizeof(struct id_entry *) * ir_entries)); iterator_ir = 0; netmask_idx = netmask_max = ERR; for (iterator = 0; iterator < t->index_num; iterator++) { if (t->index[iterator].entries) { if (pptrs->l3_proto == ETHERTYPE_IP && t->index[iterator].netmask.v4.size) { netmask_idx = 0; netmask_max = t->index[iterator].netmask.v4.size; } else if (pptrs->l3_proto == ETHERTYPE_IPV6 && t->index[iterator].netmask.v6.size) { netmask_idx = 0; netmask_max = t->index[iterator].netmask.v6.size; } netmask_recirc: hash_serializer = &t->index[iterator].hash_serializer; hash_serial_set_off(hash_serializer, 0); hash_key = hash_serial_get_key(hash_serializer); for (index_hdlr = 0; (*t->index[iterator].fdata_handler[index_hdlr]); index_hdlr++) { (*t->index[iterator].fdata_handler[index_hdlr])(&t->index[iterator], index_hdlr, netmask_idx, &res_fdata, &t->index[iterator].hash_serializer, pptrs); } if (netmask_idx >= 0) { netmask_idx++; } idx_value = NULL; ret = cdada_map_find(t->index[iterator].idx_map, hash_key_get_val(hash_key), &idx_value); if (ret == CDADA_SUCCESS) { index_results[iterator_ir] = idx_value; if (iterator_ir < ir_entries) iterator_ir++; else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: out of index results space. Indexing disabled.\n", config.name, config.type, t->filename); pretag_index_destroy(t); memset(index_results, 0, (sizeof(struct id_entry *) * ir_entries)); return 0; } } if (netmask_idx < netmask_max) { goto netmask_recirc; } } else break; } pretag_index_results_sort(index_results, iterator_ir); pretag_index_results_compress_jeqs(index_results, iterator_ir); return iterator_ir; } void pretag_index_results_sort(struct id_entry **index_results, int ir_entries) { struct id_entry *ptr = NULL; u_int32_t i, j; if (!index_results) return; for (i = 0, j = 1; index_results[i] && i < ir_entries; i++, j++) { if (index_results[j] && j < ir_entries) { if (index_results[i]->pos > index_results[j]->pos) { ptr = index_results[j]; index_results[j] = index_results[i]; index_results[i] = ptr; } } } } void pretag_index_results_compress_jeqs(struct id_entry **index_results, int ir_entries) { u_int32_t i, j, x; if (!index_results) return; for (i = 0; index_results[i] && i < ir_entries; i++) { if (index_results[i]->jeq.ptr) { for (j = i + 1; index_results[j] && j < ir_entries; j++) { if (index_results[i]->jeq.ptr->pos > index_results[j]->pos) { for (x = j + 1; x < ir_entries; x++) { index_results[x-1] = index_results[x]; } index_results[ir_entries-1] = NULL; } } } } } int pretag_index_have_one(struct id_table *t) { return t->index[0].entries; } pmacct-1.7.8/src/bgp/0000755000175000017500000000000014354105415013345 5ustar paolopaolopmacct-1.7.8/src/bgp/bgp_lcommunity.h0000644000175000017500000000406014354105275016552 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_LCOMMUNITY_H_ #define _BGP_LCOMMUNITY_H_ #define LCOMMUNITY_SIZE 12 #define LCOMMUNITY_PART_SIZE 4 #define LCOMMUNITY_STR_DEFAULT_LEN 32 /* Large Communities attribute */ struct lcommunity { /* Reference counter */ unsigned long refcnt; /* Size of Large Communities attribute. */ int size; /* Large Communities value. */ u_int8_t *val; /* Human readable format string. */ char *str; }; /* Extended community value is eight octet. */ struct lcommunity_val { char val[LCOMMUNITY_SIZE]; }; #define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE) extern void lcommunity_init (int, struct hash **); extern void lcommunity_free (struct lcommunity *); extern struct lcommunity *lcommunity_new (struct bgp_peer *); extern struct lcommunity *lcommunity_parse (struct bgp_peer *, u_int8_t *, u_short); extern struct lcommunity *lcommunity_intern (struct bgp_peer *, struct lcommunity *); extern int lcommunity_cmp (const void *, const void *); extern void lcommunity_unintern (struct bgp_peer *, struct lcommunity *); extern unsigned int lcommunity_hash_make (void *); extern char *lcommunity_lcom2str (struct bgp_peer *, struct lcommunity *); extern struct lcommunity *lcommunity_dup(struct lcommunity *); #endif pmacct-1.7.8/src/bgp/bgp.c0000644000175000017500000013332414354105275014273 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp.h" #include "bgp_xcs.h" #include "rpki/rpki.h" #include "bgp_blackhole.h" #include "thread_pool.h" #if defined WITH_EBPF #include "ebpf/ebpf_rp_balancer.h" #endif #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined WITH_ZMQ #include "zmq_common.h" #endif #if defined WITH_AVRO #include "plugin_cmn_avro.h" #endif #include "bgp_lg.h" /* Global variables */ thread_pool_t *bgp_pool; struct bgp_peer *peers; struct bgp_peer_cache_bucket *peers_cache, *peers_port_cache; char *std_comm_patterns[MAX_BGP_COMM_PATTERNS]; char *ext_comm_patterns[MAX_BGP_COMM_PATTERNS]; char *lrg_comm_patterns[MAX_BGP_COMM_PATTERNS]; char *std_comm_patterns_to_asn[MAX_BGP_COMM_PATTERNS]; char *lrg_comm_patterns_to_asn[MAX_BGP_COMM_PATTERNS]; struct bgp_comm_range peer_src_as_ifrange; struct bgp_comm_range peer_src_as_asrange; u_int32_t (*bgp_route_info_modulo)(struct bgp_peer *, path_id_t *, int); struct bgp_rt_structs inter_domain_routing_dbs[FUNC_TYPE_MAX], *bgp_routing_db; struct bgp_misc_structs inter_domain_misc_dbs[FUNC_TYPE_MAX], *bgp_misc_db; bgp_tag_t bgp_logdump_tag; struct sockaddr_storage bgp_logdump_tag_peer; struct bgp_xconnects bgp_xcs_map; /* Functions */ void bgp_daemon_wrapper() { /* initialize variables */ if (!config.bgp_daemon_port) config.bgp_daemon_port = BGP_TCP_PORT; #if defined WITH_ZMQ if (config.bgp_lg) bgp_lg_wrapper(); #else if (config.bgp_lg) { Log(LOG_ERR, "ERROR ( %s/core/lg ): 'bgp_daemon_lg' requires --enable-zmq. Exiting.\n", config.name); exit_gracefully(1); } #endif /* initialize threads pool */ bgp_pool = allocate_thread_pool(1); assert(bgp_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/BGP ): %d thread(s) initialized\n", config.name, 1); bgp_prepare_thread(); /* giving a kick to the BGP thread */ send_to_pool(bgp_pool, skinny_bgp_daemon, NULL); } int skinny_bgp_daemon() { skinny_bgp_daemon_online(); return SUCCESS; } void skinny_bgp_daemon_online() { int ret, rc, peers_idx, allowed, yes=1; int peers_idx_rr = 0, peers_xconnect_idx_rr = 0, max_peers_idx = 0; struct plugin_requests req; struct host_addr addr; struct bgp_peer *peer; struct bgp_peer_buf *peer_buf; char bgp_reply_pkt[BGP_BUFFER_SIZE], *bgp_reply_pkt_ptr; char bgp_peer_str[INET6_ADDRSTRLEN], bgp_xconnect_peer_str[BGP_XCONNECT_STRLEN]; struct sockaddr_storage server, client; afi_t afi; safi_t safi; time_t now, dump_refresh_deadline = {0}; struct hosts_table allow; struct bgp_md5_table bgp_md5; struct timeval dump_refresh_timeout, *drt_ptr; struct bgp_peer_batch bp_batch; socklen_t slen, clen = sizeof(client); struct id_table bgp_logdump_tag_table; int bgp_logdump_tag_map_allocated; sigset_t signal_set; /* select() stuff */ fd_set read_descs, bkp_read_descs; int fd, select_fd, bkp_select_fd, recalc_fds, select_num; int recv_fd, send_fd; /* initial cleanups */ reload_map_bgp_thread = FALSE; reload_log_bgp_thread = FALSE; memset(&server, 0, sizeof(server)); memset(&client, 0, sizeof(client)); memset(&allow, 0, sizeof(struct hosts_table)); bgp_routing_db = &inter_domain_routing_dbs[FUNC_TYPE_BGP]; memset(bgp_routing_db, 0, sizeof(struct bgp_rt_structs)); if (!config.bgp_table_attr_hash_buckets) config.bgp_table_attr_hash_buckets = HASHTABSIZE; bgp_attr_init(config.bgp_table_attr_hash_buckets, bgp_routing_db); /* socket creation for BGP server: IPv4 only */ if (!config.bgp_daemon_ip) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&server; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.bgp_daemon_port); slen = sizeof(struct sockaddr_in6); } else { trim_spaces(config.bgp_daemon_ip); ret = str_to_addr(config.bgp_daemon_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bgp_daemon_ip' value is not a valid IPv4/IPv6 address. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } slen = addr_to_sa((struct sockaddr *)&server, &addr, config.bgp_daemon_port); } if (!config.bgp_daemon_max_peers) config.bgp_daemon_max_peers = MAX_BGP_PEERS_DEFAULT; Log(LOG_INFO, "INFO ( %s/%s ): maximum BGP peers allowed: %d\n", config.name, bgp_misc_db->log_str, config.bgp_daemon_max_peers); peers = malloc(config.bgp_daemon_max_peers*sizeof(struct bgp_peer)); if (!peers) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BGP peers structure. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } memset(peers, 0, config.bgp_daemon_max_peers*sizeof(struct bgp_peer)); if (config.bgp_lg) { peers_cache = malloc(config.bgp_daemon_max_peers*sizeof(struct bgp_peer_cache_bucket)); if (!peers_cache) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BGP peers cache structure. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } bgp_peer_cache_init(peers_cache, config.bgp_daemon_max_peers); peers_port_cache = malloc(config.bgp_daemon_max_peers*sizeof(struct bgp_peer_cache_bucket)); if (!peers_port_cache) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BGP peers cache structure (2). Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } bgp_peer_cache_init(peers_port_cache, config.bgp_daemon_max_peers); } else { peers_cache = NULL; peers_port_cache = NULL; } if (config.bgp_xconnect_map) { int bgp_xcs_allocated = FALSE; int bgp_xcs_size = config.maps_entries ? config.maps_entries : MAX_PRETAG_MAP_ENTRIES; if (config.acct_type != ACCT_PMBGP) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_daemon_xconnect_map feature not supported for this daemon. Exiting ...\n", config.name, config.type); exit_gracefully(1); } memset(&bgp_xcs_map, 0, sizeof(bgp_xcs_map)); memset(&req, 0, sizeof(req)); /* Setting up the pool */ bgp_xcs_map.pool = malloc(bgp_xcs_size * sizeof(struct bgp_xconnect)); if (!bgp_xcs_map.pool) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate BGP xconnect pool. Exiting ...\n", config.name, config.type); exit_gracefully(1); } else memset(bgp_xcs_map.pool, 0, bgp_xcs_size * sizeof(struct bgp_xconnect)); req.key_value_table = (void *) &bgp_xcs_map; req.map_entries = bgp_xcs_size; load_id_file(MAP_BGP_XCS, config.bgp_xconnect_map, NULL, &req, &bgp_xcs_allocated); } else { bgp_xcs_map.pool = 0; bgp_xcs_map.num = 0; } if (config.rpki_roas_file || config.rpki_rtr_cache) { rpki_daemon_wrapper(); /* Let's give the RPKI thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } if (config.bgp_blackhole_stdcomm_list) { #if defined WITH_ZMQ struct p_zmq_host *bgp_blackhole_zmq_host = NULL; char inproc_blackhole_str[] = "inproc://bgp_blackhole"; (void)inproc_blackhole_str; bgp_blackhole_daemon_wrapper(); /* Let's give the BGP blackhole thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); bgp_blackhole_zmq_host = bgp_blackhole_misc_db->bgp_blackhole_zmq_host; p_zmq_push_connect_setup(bgp_blackhole_zmq_host); #else Log(LOG_ERR, "ERROR ( %s/%s ): 'bgp_blackhole_stdcomm_list' requires compiling with --enable-zmq. Exiting ..\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); #endif } if (config.bgp_daemon_msglog_file || config.bgp_daemon_msglog_amqp_routing_key || config.bgp_daemon_msglog_kafka_topic) { if (config.bgp_daemon_msglog_file) bgp_misc_db->msglog_backend_methods++; if (config.bgp_daemon_msglog_amqp_routing_key) bgp_misc_db->msglog_backend_methods++; if (config.bgp_daemon_msglog_kafka_topic) bgp_misc_db->msglog_backend_methods++; if (bgp_misc_db->msglog_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_daemon_msglog_file, bgp_daemon_msglog_amqp_routing_key and bgp_daemon_msglog_kafka_topic are mutually exclusive. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } bgp_misc_db->peers_log = malloc(config.bgp_daemon_max_peers*sizeof(struct bgp_peer_log)); if (!bgp_misc_db->peers_log) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BGP peers log structure. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } memset(bgp_misc_db->peers_log, 0, config.bgp_daemon_max_peers*sizeof(struct bgp_peer_log)); bgp_peer_log_seq_init(&bgp_misc_db->log_seq); if (config.bgp_daemon_msglog_amqp_routing_key) { #ifdef WITH_RABBITMQ bgp_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&bgp_daemon_msglog_amqp_host); #else Log(LOG_WARNING, "WARN ( %s/%s ): p_amqp_connect_to_publish() not possible due to missing --enable-rabbitmq\n", config.name, bgp_misc_db->log_str); #endif } if (config.bgp_daemon_msglog_kafka_topic) { #ifdef WITH_KAFKA bgp_daemon_msglog_init_kafka_host(); #else Log(LOG_WARNING, "WARN ( %s/%s ): p_kafka_connect_to_produce() not possible due to missing --enable-kafka\n", config.name, bgp_misc_db->log_str); #endif } } if (config.bgp_table_dump_file || config.bgp_table_dump_amqp_routing_key || config.bgp_table_dump_kafka_topic) { if (config.bgp_table_dump_file) bgp_misc_db->dump_backend_methods++; if (config.bgp_table_dump_amqp_routing_key) bgp_misc_db->dump_backend_methods++; if (config.bgp_table_dump_kafka_topic) bgp_misc_db->dump_backend_methods++; if (bgp_misc_db->dump_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_table_dump_file, bgp_table_dump_amqp_routing_key and bgp_table_dump_kafka_topic are mutually exclusive. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } } if ((bgp_misc_db->msglog_backend_methods || bgp_misc_db->dump_backend_methods) && config.bgp_xconnect_map) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_daemon_xconnect_map is mutually exclusive with any BGP msglog and dump method. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } if (!config.bgp_table_peer_buckets) config.bgp_table_peer_buckets = DEFAULT_BGP_INFO_HASH; if (!config.bgp_table_per_peer_buckets) config.bgp_table_per_peer_buckets = DEFAULT_BGP_INFO_PER_PEER_HASH; if (config.bgp_table_per_peer_hash == BGP_ASPATH_HASH_PATHID) bgp_route_info_modulo = bgp_route_info_modulo_pathid; else { Log(LOG_ERR, "ERROR ( %s/%s ): Unknown 'bgp_table_per_peer_hash' value. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } config.bgp_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); if (config.bgp_sock < 0) { /* retry with IPv4 */ if (!config.bgp_daemon_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.bgp_daemon_port); slen = sizeof(struct sockaddr_in); config.bgp_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); } if (config.bgp_sock < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): thread socket() failed. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } } setsockopt(config.bgp_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&yes, sizeof(yes)); if (config.bgp_daemon_ipprec) { int opt = config.bgp_daemon_ipprec << 5; rc = setsockopt(config.bgp_sock, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IP_TOS (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); } #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.bgp_sock, SOL_SOCKET, SO_REUSEPORT, (char *)&yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEPORT (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); #endif rc = setsockopt(config.bgp_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEADDR (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); #if (defined HAVE_SO_BINDTODEVICE) if (config.bgp_daemon_interface) { rc = setsockopt(config.bgp_sock, SOL_SOCKET, SO_BINDTODEVICE, config.bgp_daemon_interface, (socklen_t) strlen(config.bgp_daemon_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); } #endif if (config.bgp_daemon_ipv6_only) { int yes=1; rc = setsockopt(config.bgp_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IPV6_V6ONLY (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); } if (config.bgp_daemon_pipe_size) { socklen_t l = sizeof(config.bgp_daemon_pipe_size); int saved = 0, obtained = 0; getsockopt(config.bgp_sock, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(config.bgp_sock, SOL_SOCKET, SO_RCVBUF, &config.bgp_daemon_pipe_size, (socklen_t) sizeof(config.bgp_daemon_pipe_size)); getsockopt(config.bgp_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Setsocksize(config.bgp_sock, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(config.bgp_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Log(LOG_INFO, "INFO ( %s/%s ): bgp_daemon_pipe_size: obtained=%d target=%d.\n", config.name, bgp_misc_db->log_str, obtained, config.bgp_daemon_pipe_size); } rc = bind(config.bgp_sock, (struct sockaddr *) &server, slen); if (rc < 0) { char null_ip_address[] = "0.0.0.0"; char *ip_address; ip_address = config.bgp_daemon_ip ? config.bgp_daemon_ip : null_ip_address; Log(LOG_ERR, "ERROR ( %s/%s ): bind() to ip=%s port=%d/tcp failed (errno: %d).\n", config.name, bgp_misc_db->log_str, ip_address, config.bgp_daemon_port, errno); exit_gracefully(1); } rc = listen(config.bgp_sock, 1); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): listen() failed (errno: %d).\n", config.name, bgp_misc_db->log_str, errno); exit_gracefully(1); } #if defined WITH_EBPF if (config.bgp_daemon_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(config.bgp_sock, config.bgp_daemon_rp_ebpf_prog, config.cluster_name, "bgp", config.cluster_id, TRUE); } #endif /* Preparing for syncronous I/O multiplexing */ select_fd = 0; FD_ZERO(&bkp_read_descs); FD_SET(config.bgp_sock, &bkp_read_descs); { char srv_string[INET6_ADDRSTRLEN]; struct host_addr srv_addr; u_int16_t srv_port; sa_to_addr((struct sockaddr *)&server, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/%s ): waiting for BGP data on %s:%u\n", config.name, bgp_misc_db->log_str, srv_string, srv_port); } /* Preparing ACL, if any */ if (config.bgp_daemon_allow_file) load_allow_file(config.bgp_daemon_allow_file, &allow); /* Preparing MD5 keys, if any */ if (config.bgp_daemon_md5_file) { bgp_md5_file_init(&bgp_md5); bgp_md5_file_load(config.bgp_daemon_md5_file, &bgp_md5); if (bgp_md5.num) bgp_md5_file_process(config.bgp_sock, &bgp_md5); } /* Let's initialize clean shared RIB */ for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { bgp_routing_db->rib[afi][safi] = bgp_table_init(afi, safi); } } /* BGP peers batching checks */ if ((config.bgp_daemon_batch && !config.bgp_daemon_batch_interval) || (config.bgp_daemon_batch_interval && !config.bgp_daemon_batch)) { Log(LOG_WARNING, "WARN ( %s/%s ): 'bgp_daemon_batch_interval' and 'bgp_daemon_batch' both set to zero.\n", config.name, bgp_misc_db->log_str); config.bgp_daemon_batch = 0; config.bgp_daemon_batch_interval = 0; } else bgp_batch_init(&bp_batch, config.bgp_daemon_batch, config.bgp_daemon_batch_interval); /* bgp_link_misc_structs() will re-apply. But we need to anticipate this definition in order to build the Avro schemas correctly */ bgp_misc_db->tag_map = config.bgp_daemon_tag_map; if (bgp_misc_db->msglog_backend_methods) { #ifdef WITH_JANSSON if (!config.bgp_daemon_msglog_output) config.bgp_daemon_msglog_output = PRINT_OUTPUT_JSON; #else Log(LOG_WARNING, "WARN ( %s/%s ): bgp_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", config.name, bgp_misc_db->log_str); #endif #ifdef WITH_AVRO if ((config.bgp_daemon_msglog_output == PRINT_OUTPUT_AVRO_BIN) || (config.bgp_daemon_msglog_output == PRINT_OUTPUT_AVRO_JSON)) { assert(BGP_LOG_TYPE_MAX < MAX_AVRO_SCHEMA); bgp_misc_db->msglog_avro_schema[0] = p_avro_schema_build_bgp(BGP_LOGDUMP_ET_LOG, "bgp_msglog"); bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGINIT] = p_avro_schema_build_bgp_log_initclose(BGP_LOGDUMP_ET_LOG, "bgp_loginit"); bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGCLOSE] = p_avro_schema_build_bgp_log_initclose(BGP_LOGDUMP_ET_LOG, "bgp_logclose"); if (config.bgp_daemon_msglog_avro_schema_file) { char p_avro_schema_file[SRVBUFLEN]; if (strlen(config.bgp_daemon_msglog_avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bgp_daemon_msglog_avro_schema_file' too long. Exiting.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.bgp_daemon_msglog_avro_schema_file, "-bgp_msglog", p_avro_schema_file, bgp_misc_db->msglog_avro_schema[0]); write_avro_schema_to_file_with_suffix(config.bgp_daemon_msglog_avro_schema_file, "-bgp_loginit", p_avro_schema_file, bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGINIT]); write_avro_schema_to_file_with_suffix(config.bgp_daemon_msglog_avro_schema_file, "-bgp_logclose", p_avro_schema_file, bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGCLOSE]); } if (config.bgp_daemon_msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES if (strchr(config.bgp_daemon_msglog_kafka_topic, '$')) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'bgp_daemon_msglog_kafka_topic' is not compatible with 'bgp_daemon_msglog_kafka_avro_schema_registry'. Exiting.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } if (config.bgp_daemon_msglog_output == PRINT_OUTPUT_AVRO_JSON) { Log(LOG_ERR, "ERROR ( %s/%s ): 'avro_json' output is not compatible with 'bgp_daemon_msglog_kafka_avro_schema_registry'. Exiting.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } bgp_daemon_msglog_prepare_sd_schemas(); #endif } } #endif } if (bgp_misc_db->dump_backend_methods) { if (!config.bgp_table_dump_workers) { config.bgp_table_dump_workers = 1; } #ifdef WITH_JANSSON if (!config.bgp_table_dump_output) { config.bgp_table_dump_output = PRINT_OUTPUT_JSON; } #else Log(LOG_WARNING, "WARN ( %s/%s ): bgp_table_dump_output set to json but will produce no output (missing --enable-jansson).\n", config.name, bgp_misc_db->log_str); #endif #ifdef WITH_AVRO if ((config.bgp_table_dump_output == PRINT_OUTPUT_AVRO_BIN) || (config.bgp_table_dump_output == PRINT_OUTPUT_AVRO_JSON)) { assert(BGP_LOG_TYPE_MAX < MAX_AVRO_SCHEMA); bgp_misc_db->dump_avro_schema[0] = p_avro_schema_build_bgp(BGP_LOGDUMP_ET_DUMP, "bgp_dump"); bgp_misc_db->dump_avro_schema[BGP_LOG_TYPE_DUMPINIT] = p_avro_schema_build_bgp_dump_init(BGP_LOGDUMP_ET_DUMP, "bgp_dumpinit"); bgp_misc_db->dump_avro_schema[BGP_LOG_TYPE_DUMPCLOSE] = p_avro_schema_build_bgp_dump_close(BGP_LOGDUMP_ET_DUMP, "bgp_dumpclose"); if (config.bgp_table_dump_avro_schema_file) { char p_avro_schema_file[SRVBUFLEN]; if (strlen(config.bgp_table_dump_avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bgp_table_dump_avro_schema_file' too long. Exiting.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.bgp_table_dump_avro_schema_file, "-bgp_dump", p_avro_schema_file, bgp_misc_db->dump_avro_schema[0]); write_avro_schema_to_file_with_suffix(config.bgp_table_dump_avro_schema_file, "-bgp_dumpinit", p_avro_schema_file, bgp_misc_db->dump_avro_schema[BGP_LOG_TYPE_DUMPINIT]); write_avro_schema_to_file_with_suffix(config.bgp_table_dump_avro_schema_file, "-bgp_dumpclose", p_avro_schema_file, bgp_misc_db->dump_avro_schema[BGP_LOG_TYPE_DUMPCLOSE]); } } #endif } if (bgp_misc_db->dump_backend_methods) { char dump_roundoff[] = "m"; time_t tmp_time; if (!config.bgp_table_dump_time_slots) { config.bgp_table_dump_time_slots = 1; } bgp_misc_db->current_slot = 0; if (config.bgp_table_dump_refresh_time % config.bgp_table_dump_time_slots != 0) { Log(LOG_WARNING, "WARN ( %s/%s ): 'bgp_table_dump_time_slots' is not a divisor of 'bgp_table_dump_refresh_time', please fix.\n", config.name, bgp_misc_db->log_str); } if (config.bgp_table_dump_refresh_time) { gettimeofday(&bgp_misc_db->log_tstamp, NULL); dump_refresh_deadline = bgp_misc_db->log_tstamp.tv_sec; tmp_time = roundoff_time(dump_refresh_deadline, dump_roundoff); while ((tmp_time+config.bgp_table_dump_refresh_time) < dump_refresh_deadline) { tmp_time += config.bgp_table_dump_refresh_time; } dump_refresh_deadline = tmp_time; dump_refresh_deadline += config.bgp_table_dump_refresh_time; /* it's a deadline not a basetime */ } else { config.bgp_table_dump_file = NULL; bgp_misc_db->dump_backend_methods = FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): Invalid 'bgp_table_dump_refresh_time'.\n", config.name, bgp_misc_db->log_str); } } #ifdef WITH_AVRO bgp_misc_db->avro_buf = malloc(LARGEBUFLEN); if (!bgp_misc_db->avro_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (avro_buf). Exiting ..\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } else memset(bgp_misc_db->avro_buf, 0, LARGEBUFLEN); #endif if (config.bgp_daemon_msglog_kafka_avro_schema_registry || config.bgp_table_dump_kafka_avro_schema_registry) { #ifndef WITH_SERDES Log(LOG_ERR, "ERROR ( %s/%s ): 'bgp_*_kafka_avro_schema_registry' require --enable-serdes. Exiting.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); #endif } if (!config.writer_id_string) { config.writer_id_string = DYNNAME_DEFAULT_WRITER_ID; } dynname_tokens_prepare(config.writer_id_string, &bgp_misc_db->writer_id_tokens, DYN_STR_WRITER_ID); select_fd = bkp_select_fd = (config.bgp_sock + 1); recalc_fds = FALSE; bgp_link_misc_structs(bgp_misc_db); if (config.bgp_daemon_tag_map) { memset(&bgp_logdump_tag, 0, sizeof(bgp_logdump_tag)); memset(&bgp_logdump_tag_table, 0, sizeof(bgp_logdump_tag_table)); memset(&req, 0, sizeof(req)); bgp_logdump_tag_map_allocated = FALSE; load_pre_tag_map(ACCT_PMBGP, config.bgp_daemon_tag_map, &bgp_logdump_tag_table, &req, &bgp_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); /* making some bindings */ bgp_logdump_tag.tag_table = (unsigned char *) &bgp_logdump_tag_table; } sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } for (;;) { select_again: if (!bgp_misc_db->is_thread) { sigprocmask(SIG_UNBLOCK, &signal_set, NULL); sigprocmask(SIG_BLOCK, &signal_set, NULL); } if (recalc_fds) { select_fd = config.bgp_sock; max_peers_idx = -1; /* .. since valid indexes include 0 */ for (peers_idx = 0; peers_idx < config.bgp_daemon_max_peers; peers_idx++) { if (select_fd < peers[peers_idx].fd) select_fd = peers[peers_idx].fd; if (config.bgp_xconnect_map) { if (select_fd < peers[peers_idx].xconnect_fd) select_fd = peers[peers_idx].xconnect_fd; } if (peers[peers_idx].fd) max_peers_idx = peers_idx; } select_fd++; max_peers_idx++; bkp_select_fd = select_fd; recalc_fds = FALSE; } else select_fd = bkp_select_fd; memcpy(&read_descs, &bkp_read_descs, sizeof(bkp_read_descs)); if (bgp_misc_db->dump_backend_methods) { int delta; calc_refresh_timeout_sec(dump_refresh_deadline, bgp_misc_db->log_tstamp.tv_sec, &delta); dump_refresh_timeout.tv_sec = delta; dump_refresh_timeout.tv_usec = 0; drt_ptr = &dump_refresh_timeout; } else drt_ptr = NULL; select_num = select(select_fd, &read_descs, NULL, NULL, drt_ptr); if (select_num < 0) goto select_again; now = time(NULL); /* signals handling */ if (reload_map_bgp_thread) { if (config.bgp_daemon_allow_file) load_allow_file(config.bgp_daemon_allow_file, &allow); if (config.bgp_daemon_md5_file) { bgp_md5_file_unload(&bgp_md5); if (bgp_md5.num) bgp_md5_file_process(config.bgp_sock, &bgp_md5); // process unload bgp_md5_file_load(config.bgp_daemon_md5_file, &bgp_md5); if (bgp_md5.num) bgp_md5_file_process(config.bgp_sock, &bgp_md5); // process load } if (config.bgp_xconnect_map) { int bgp_xcs_allocated = FALSE; bgp_xcs_map_destroy(); memset(&req, 0, sizeof(req)); req.key_value_table = (void *) &bgp_xcs_map; load_id_file(MAP_BGP_XCS, config.bgp_xconnect_map, NULL, &req, &bgp_xcs_allocated); } if (config.bgp_daemon_tag_map) { load_pre_tag_map(ACCT_PMBGP, config.bgp_daemon_tag_map, &bgp_logdump_tag_table, &req, &bgp_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); } reload_map_bgp_thread = FALSE; } if (reload_log_bgp_thread) { for (peers_idx = 0; peers_idx < config.bgp_daemon_max_peers; peers_idx++) { if (bgp_misc_db->peers_log[peers_idx].fd) { fclose(bgp_misc_db->peers_log[peers_idx].fd); bgp_misc_db->peers_log[peers_idx].fd = open_output_file(bgp_misc_db->peers_log[peers_idx].filename, "a", FALSE); setlinebuf(bgp_misc_db->peers_log[peers_idx].fd); } else break; } reload_log_bgp_thread = FALSE; } if (reload_log && !bgp_misc_db->is_thread) { reload_logs(PMBGPD_USAGE_HEADER); reload_log = FALSE; } if (bgp_misc_db->msglog_backend_methods || bgp_misc_db->dump_backend_methods) { gettimeofday(&bgp_misc_db->log_tstamp, NULL); compose_timestamp(bgp_misc_db->log_tstamp_str, SRVBUFLEN, &bgp_misc_db->log_tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); /* if dumping, let's reset log sequence at the next dump event */ if (!bgp_misc_db->dump_backend_methods) { if (bgp_peer_log_seq_has_ro_bit(&bgp_misc_db->log_seq)) bgp_peer_log_seq_init(&bgp_misc_db->log_seq); } int refreshTimePerSlot = config.bgp_table_dump_refresh_time / config.bgp_table_dump_time_slots; if (bgp_misc_db->dump_backend_methods) { while (bgp_misc_db->log_tstamp.tv_sec > dump_refresh_deadline) { bgp_misc_db->dump.tstamp.tv_sec = dump_refresh_deadline; bgp_misc_db->dump.tstamp.tv_usec = 0; compose_timestamp(bgp_misc_db->dump.tstamp_str, SRVBUFLEN, &bgp_misc_db->dump.tstamp, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bgp_misc_db->dump.period = refreshTimePerSlot; if (bgp_peer_log_seq_has_ro_bit(&bgp_misc_db->log_seq)) bgp_peer_log_seq_init(&bgp_misc_db->log_seq); bgp_handle_dump_event(max_peers_idx); dump_refresh_deadline += refreshTimePerSlot; } } #ifdef WITH_RABBITMQ if (config.bgp_daemon_msglog_amqp_routing_key) { time_t last_fail = P_broker_timers_get_last_fail(&bgp_daemon_msglog_amqp_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&bgp_daemon_msglog_amqp_host.btimers)) <= bgp_misc_db->log_tstamp.tv_sec)) { bgp_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&bgp_daemon_msglog_amqp_host); } } #endif #ifdef WITH_KAFKA if (config.bgp_daemon_msglog_kafka_topic) { time_t last_fail = P_broker_timers_get_last_fail(&bgp_daemon_msglog_kafka_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&bgp_daemon_msglog_kafka_host.btimers)) <= bgp_misc_db->log_tstamp.tv_sec)) bgp_daemon_msglog_init_kafka_host(); if (config.bgp_daemon_msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES bgp_daemon_msglog_prepare_sd_schemas(); #endif } } #endif } /* If select_num == 0 then we got out of select() due to a timeout rather than because we had a message from a peer to handle. By now we did all routine checks and can happily return to select() again. */ if (!select_num) goto select_again; /* New connection is coming in */ if (FD_ISSET(config.bgp_sock, &read_descs)) { int peers_check_idx, peers_num; fd = accept(config.bgp_sock, (struct sockaddr *) &client, &clen); if (fd == ERR) goto read_data; ipv4_mapped_to_ipv4(&client); /* If an ACL is defined, here we check against and enforce it */ if (allow.num) allowed = check_allow(&allow, (struct sockaddr *)&client); else allowed = TRUE; if (!allowed) { char disallowed_str[INET6_ADDRSTRLEN]; sa_to_str(disallowed_str, sizeof(disallowed_str), (struct sockaddr *) &client, TRUE); Log(LOG_INFO, "INFO ( %s/%s ): [%s] peer '%s' not allowed. close()\n", config.name, bgp_misc_db->log_str, config.bgp_daemon_allow_file, disallowed_str); close(fd); goto read_data; } for (peer = NULL, peers_idx = 0; peers_idx < config.bgp_daemon_max_peers; peers_idx++) { if (!peers[peers_idx].fd) { /* Admitted if: * batching feature is disabled or * we have room in the current batch or * we can start a new batch */ if (bgp_batch_is_admitted(&bp_batch, now)) { peer = &peers[peers_idx]; if (bgp_peer_init(peer, FUNC_TYPE_BGP)) peer = NULL; else recalc_fds = TRUE; log_notification_unset(&log_notifications.bgp_peers_throttling); if (bgp_batch_is_enabled(&bp_batch) && peer) { if (bgp_batch_is_expired(&bp_batch, now)) bgp_batch_reset(&bp_batch, now); if (bgp_batch_is_not_empty(&bp_batch)) bgp_batch_decrease_counter(&bp_batch); } break; } else { /* throttle */ /* We briefly accept the new connection to be able to drop it */ if (!log_notification_isset(&log_notifications.bgp_peers_throttling, now)) { Log(LOG_INFO, "INFO ( %s/%s ): throttling at BGP peer #%u\n", config.name, bgp_misc_db->log_str, peers_idx); log_notification_set(&log_notifications.bgp_peers_throttling, now, FALSE); } close(fd); goto read_data; } } /* XXX: replenish sessions with expired keepalives */ } if (!peer) { /* We briefly accept the new connection to be able to drop it */ if (!log_notification_isset(&log_notifications.bgp_peers_limit, now)) { log_notification_set(&log_notifications.bgp_peers_limit, now, FALSE); Log(LOG_WARNING, "WARN ( %s/%s ): Insufficient number of BGP peers has been configured by 'bgp_daemon_max_peers' (%d).\n", config.name, bgp_misc_db->log_str, config.bgp_daemon_max_peers); } close(fd); goto read_data; } peer->fd = fd; peer->idx = peers_idx; FD_SET(peer->fd, &bkp_read_descs); sa_to_addr((struct sockaddr *) &client, &peer->addr, &peer->tcp_port); if (peers_cache && peers_port_cache) { u_int32_t bucket; bucket = addr_hash(&peer->addr, config.bgp_daemon_max_peers); bgp_peer_cache_insert(peers_cache, bucket, peer); bucket = addr_port_hash(&peer->addr, peer->tcp_port, config.bgp_daemon_max_peers); bgp_peer_cache_insert(peers_port_cache, bucket, peer); } /* Being bgp_daemon_tag_map limited to 'ip' key lookups, this is finely placed here. Should further lookups be possible, this may be very possibly moved inside the loop */ if (config.bgp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bgp_logdump_tag_peer, &bgp_logdump_tag); bgp_tag_find((struct id_table *)bgp_logdump_tag.tag_table, &bgp_logdump_tag, &bgp_logdump_tag.tag, NULL); } if (bgp_misc_db->msglog_backend_methods) bgp_peer_log_init(peer, &bgp_logdump_tag, config.bgp_daemon_msglog_output, FUNC_TYPE_BGP); /* Check: more than one TCP connection from a peer (IP address) */ for (peers_check_idx = 0, peers_num = 0; peers_check_idx < config.bgp_daemon_max_peers; peers_check_idx++) { if (peers_idx != peers_check_idx && !memcmp(&peers[peers_check_idx].addr, &peer->addr, sizeof(peers[peers_check_idx].addr))) { int same_peer = FALSE; bgp_peer_print(&peers[peers_check_idx], bgp_peer_str, INET6_ADDRSTRLEN); /* Check: if not x-connecting, let's see if we have to compare TCP ports (ie. NAT traversal / non-transparent tee scenarios); then evaluate if the new session is valid or has to be rejected */ if (!config.bgp_xconnect_map) { if (config.tmp_bgp_lookup_compare_ports) { if (peers[peers_check_idx].tcp_port == peer->tcp_port) same_peer = TRUE; else { same_peer = FALSE; if (peers[peers_check_idx].fd) peers_num++; } } else same_peer = TRUE; if (same_peer) { if ((now - peers[peers_check_idx].last_keepalive) > peers[peers_check_idx].ht) { bgp_peer_print(&peers[peers_check_idx], bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Replenishing stale connection by peer.\n", config.name, bgp_misc_db->log_str, bgp_peer_str); FD_CLR(peers[peers_check_idx].fd, &bkp_read_descs); bgp_peer_close(&peers[peers_check_idx], FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Refusing new connection from existing peer (residual holdtime: %ld).\n", config.name, bgp_misc_db->log_str, bgp_peer_str, (peers[peers_check_idx].ht - ((long)now - peers[peers_check_idx].last_keepalive))); FD_CLR(peer->fd, &bkp_read_descs); bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); goto read_data; } } } /* XXX: if x-connecting we don't support NAT traversal / non-transparent tee scenarios (yet?) */ else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Refusing new incoming connection for existing BGP xconnect.\n", config.name, bgp_misc_db->log_str, bgp_peer_str); FD_CLR(peer->fd, &bkp_read_descs); bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); goto read_data; } } else if (peers[peers_check_idx].fd) peers_num++; } if (config.bgp_xconnect_map) { bgp_peer_xconnect_init(peer, FUNC_TYPE_BGP); if (peer->xconnect_fd) FD_SET(peer->xconnect_fd, &bkp_read_descs); else { FD_CLR(peer->fd, &bkp_read_descs); bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); goto read_data; } } if (!config.bgp_xconnect_map) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] BGP peers usage: %u/%u\n", config.name, bgp_misc_db->log_str, bgp_peer_str, peers_num, config.bgp_daemon_max_peers); } else { bgp_peer_xconnect_print(peer, bgp_xconnect_peer_str, BGP_XCONNECT_STRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] BGP xconnects usage: %u/%u\n", config.name, bgp_misc_db->log_str, bgp_xconnect_peer_str, peers_num, config.bgp_daemon_max_peers); } if (config.bgp_daemon_neighbors_file) write_neighbors_file(config.bgp_daemon_neighbors_file, FUNC_TYPE_BGP); } read_data: /* We have something coming in: let's lookup which peer is that. FvD: To avoid starvation of the "later established" peers, we offset the start of the search in a round-robin style. */ for (peer = NULL, peer_buf = NULL, peers_idx = 0; peers_idx < max_peers_idx; peers_idx++) { int loc_idx = (peers_idx + peers_idx_rr) % max_peers_idx; recv_fd = 0; send_fd = 0; if (peers[loc_idx].fd && FD_ISSET(peers[loc_idx].fd, &read_descs)) { peer = &peers[loc_idx]; peer_buf = &peer->buf; recv_fd = peer->fd; if (config.bgp_xconnect_map) send_fd = peer->xconnect_fd; peers_idx_rr = (peers_idx_rr + 1) % max_peers_idx; break; } if (config.bgp_xconnect_map) { loc_idx = (peers_idx + peers_xconnect_idx_rr) % max_peers_idx; if (peers[loc_idx].xconnect_fd && FD_ISSET(peers[loc_idx].xconnect_fd, &read_descs)) { peer = &peers[loc_idx]; peer_buf = &peer->xbuf; recv_fd = peer->xconnect_fd; send_fd = peer->fd; peers_xconnect_idx_rr = (peers_xconnect_idx_rr + 1) % max_peers_idx; break; } } } if (!peer) goto select_again; if (!peer_buf->exp_len) { ret = recv(recv_fd, &peer_buf->base[peer_buf->cur_len], (BGP_HEADER_SIZE - peer_buf->cur_len), 0); if (ret > 0) { peer_buf->cur_len += ret; if (peer_buf->cur_len == BGP_HEADER_SIZE) { struct bgp_header *bhdr = (struct bgp_header *) peer_buf->base; if (bgp_marker_check(bhdr, BGP_MARKER_SIZE) == ERR) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP packet (marker check failed).\n", config.name, bgp_misc_db->log_str, bgp_peer_str); peer->msglen = 0; peer_buf->cur_len = 0; peer_buf->exp_len = 0; ret = ERR; } else { peer_buf->exp_len = ntohs(bhdr->bgpo_len); /* commit */ if (peer_buf->cur_len == peer_buf->exp_len) { peer->msglen = peer_buf->exp_len; peer_buf->cur_len = 0; peer_buf->exp_len = 0; } } } else { goto select_again; } } } if (peer_buf->exp_len) { ret = recv(recv_fd, &peer_buf->base[peer_buf->cur_len], (peer_buf->exp_len - peer_buf->cur_len), 0); if (ret > 0) { peer_buf->cur_len += ret; /* commit */ if (peer_buf->cur_len == peer_buf->exp_len) { peer->msglen = peer_buf->exp_len; peer_buf->cur_len = 0; peer_buf->exp_len = 0; } else { goto select_again; } } } if (ret <= 0) { if (!config.bgp_xconnect_map) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] BGP connection reset by peer (%d).\n", config.name, bgp_misc_db->log_str, bgp_peer_str, errno); FD_CLR(peer->fd, &bkp_read_descs); } else { bgp_peer_xconnect_print(peer, bgp_xconnect_peer_str, BGP_XCONNECT_STRLEN); if (recv_fd == peer->fd) Log(LOG_INFO, "INFO ( %s/%s ): [%s] recv(): BGP xconnect reset by src peer (%d).\n", config.name, bgp_misc_db->log_str, bgp_xconnect_peer_str, errno); else if (recv_fd == peer->xconnect_fd) Log(LOG_INFO, "INFO ( %s/%s ): [%s] recv(): BGP xconnect reset by dst peer (%d).\n", config.name, bgp_misc_db->log_str, bgp_xconnect_peer_str, errno); FD_CLR(peer->fd, &bkp_read_descs); FD_CLR(peer->xconnect_fd, &bkp_read_descs); } bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); recalc_fds = TRUE; goto select_again; } else { if (!config.bgp_xconnect_map) { /* Appears a valid peer with a valid BGP message: before continuing let's see if it's time to send a KEEPALIVE back */ if (peer->status == Established && ((now - peer->last_keepalive) > (peer->ht / 2))) { bgp_reply_pkt_ptr = bgp_reply_pkt; bgp_reply_pkt_ptr += bgp_write_keepalive_msg(bgp_reply_pkt_ptr); ret = send(recv_fd, bgp_reply_pkt, bgp_reply_pkt_ptr - bgp_reply_pkt, 0); peer->last_keepalive = now; } if (config.bgp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bgp_logdump_tag_peer, &bgp_logdump_tag); bgp_tag_find((struct id_table *)bgp_logdump_tag.tag_table, &bgp_logdump_tag, &bgp_logdump_tag.tag, NULL); } ret = bgp_parse_msg(peer, now, TRUE); if (ret) { FD_CLR(recv_fd, &bkp_read_descs); if (ret < 0) bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); else bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, TRUE, ret, BGP_NOTIFY_SUBCODE_UNSPECIFIC, NULL); recalc_fds = TRUE; goto select_again; } } else { ret = send(send_fd, peer_buf->base, peer->msglen, 0); if (ret <= 0) { bgp_peer_xconnect_print(peer, bgp_xconnect_peer_str, BGP_XCONNECT_STRLEN); if (send_fd == peer->fd) Log(LOG_INFO, "INFO ( %s/%s ): [%s] send(): BGP xconnect reset by src peer (%d).\n", config.name, bgp_misc_db->log_str, bgp_xconnect_peer_str, errno); else if (send_fd == peer->xconnect_fd) Log(LOG_INFO, "INFO ( %s/%s ): [%s] send(): BGP xconnect reset by dst peer (%d).\n", config.name, bgp_misc_db->log_str, bgp_xconnect_peer_str, errno); FD_CLR(peer->fd, &bkp_read_descs); FD_CLR(peer->xconnect_fd, &bkp_read_descs); bgp_peer_close(peer, FUNC_TYPE_BGP, FALSE, FALSE, FALSE, FALSE, NULL); recalc_fds = TRUE; goto select_again; } } } } } void bgp_prepare_thread() { bgp_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_BGP]; memset(bgp_misc_db, 0, sizeof(struct bgp_misc_structs)); bgp_misc_db->is_thread = TRUE; if (config.bgp_lg) bgp_misc_db->has_lglass = TRUE; if (config.rpki_roas_file || config.rpki_rtr_cache) { bgp_misc_db->bnv = malloc(sizeof(struct bgp_node_vector)); memset(bgp_misc_db->bnv, 0, sizeof(struct bgp_node_vector)); } if (config.bgp_blackhole_stdcomm_list) bgp_misc_db->has_blackhole = TRUE; bgp_misc_db->log_str = malloc(strlen("core/BGP") + 1); strcpy(bgp_misc_db->log_str, "core/BGP"); } void bgp_prepare_daemon() { bgp_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_BGP]; memset(bgp_misc_db, 0, sizeof(struct bgp_misc_structs)); bgp_misc_db->is_thread = FALSE; if (config.bgp_lg) bgp_misc_db->has_lglass = TRUE; if (config.rpki_roas_file || config.rpki_rtr_cache) { bgp_misc_db->bnv = malloc(sizeof(struct bgp_node_vector)); memset(bgp_misc_db->bnv, 0, sizeof(struct bgp_node_vector)); } if (config.bgp_blackhole_stdcomm_list) bgp_misc_db->has_blackhole = TRUE; bgp_misc_db->log_str = malloc(strlen("core") + 1); strcpy(bgp_misc_db->log_str, "core"); } void bgp_daemon_msglog_prepare_sd_schemas() { #ifdef WITH_SERDES time_t last_fail = P_broker_timers_get_last_fail(&bgp_daemon_msglog_kafka_host.sd_schema_timers); if ((last_fail + P_broker_timers_get_retry_interval(&bgp_daemon_msglog_kafka_host.sd_schema_timers)) <= bgp_misc_db->log_tstamp.tv_sec) { if (!bgp_daemon_msglog_kafka_host.sd_schema[0]) { bgp_daemon_msglog_kafka_host.sd_schema[0] = compose_avro_schema_registry_name_2(config.bgp_daemon_msglog_kafka_topic, FALSE, bgp_misc_db->msglog_avro_schema[0], "bgp", "msglog", config.bgp_daemon_msglog_kafka_avro_schema_registry); if (!bgp_daemon_msglog_kafka_host.sd_schema[0]) goto exit_lane; } if (!bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGINIT]) { bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGINIT] = compose_avro_schema_registry_name_2(config.bgp_daemon_msglog_kafka_topic, FALSE, bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGINIT], "bgp", "loginit", config.bgp_daemon_msglog_kafka_avro_schema_registry); if (!bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGINIT]) goto exit_lane; } if (!bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGCLOSE]) { bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGCLOSE] = compose_avro_schema_registry_name_2(config.bgp_daemon_msglog_kafka_topic, FALSE, bgp_misc_db->msglog_avro_schema[BGP_LOG_TYPE_LOGCLOSE], "bgp", "logclose", config.bgp_daemon_msglog_kafka_avro_schema_registry); if (!bgp_daemon_msglog_kafka_host.sd_schema[BGP_LOG_TYPE_LOGCLOSE]) goto exit_lane; } } return; exit_lane: P_broker_timers_set_last_fail(&bgp_daemon_msglog_kafka_host.sd_schema_timers, time(NULL)); #endif } void bgp_tag_init_find(struct bgp_peer *peer, struct sockaddr *sa, bgp_tag_t *pptrs) { addr_to_sa(sa, &peer->addr, peer->tcp_port); pptrs->f_agent = (u_char *) sa; } int bgp_tag_find(struct id_table *t, bgp_tag_t *pptrs, pm_id_t *tag, pm_id_t *tag2) { struct sockaddr *sa = NULL; int x, begin = 0, end = 0; pm_id_t ret = 0; if (!t) return 0; sa = (struct sockaddr *) pptrs->f_agent; /* The id_table is shared between by IPv4 and IPv6 NetFlow agents. IPv4 ones are in the lower part (0..x), IPv6 ones are in the upper part (x+1..end) */ pretag_init_vars(pptrs, t); if (tag) *tag = 0; if (tag2) *tag2 = 0; if (pptrs) { pptrs->have_tag = FALSE; pptrs->have_tag2 = FALSE; } /* XXX: tackle indexing */ if (sa->sa_family == AF_INET) { begin = 0; end = t->ipv4_num; } else if (sa->sa_family == AF_INET6) { begin = t->num-t->ipv6_num; end = t->num; } for (x = begin; x < end; x++) { if (host_addr_mask_sa_cmp(&t->e[x].key.agent_ip.a, &t->e[x].key.agent_mask, sa) == 0) { ret = pretag_entry_process(&t->e[x], pptrs, tag, tag2); if (!ret || ret > TRUE) { if (ret & PRETAG_MAP_RCODE_JEQ) { x = t->e[x].jeq.ptr->pos; x--; // yes, it will be automagically incremented by the for() cycle } else break; } } } return ret; } pmacct-1.7.8/src/bgp/bgp_msg.h0000644000175000017500000000647114354105275015150 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_MSG_H_ #define _BGP_MSG_H_ /* prototypes */ extern int bgp_max_msglen_check(u_int32_t); extern int bgp_marker_check(struct bgp_header *, int); extern int bgp_parse_msg(struct bgp_peer *, time_t, int); extern int bgp_parse_open_msg(struct bgp_msg_data *, char *, time_t, int); extern int bgp_parse_update_msg(struct bgp_msg_data *, char *); extern int bgp_parse_notification_msg(struct bgp_msg_data *, char *, u_int8_t *, u_int8_t *, char *, u_int16_t); extern int bgp_write_keepalive_msg(char *); extern int bgp_write_open_msg(char *, char *, int, struct bgp_peer *); extern int bgp_write_notification_msg(char *, int, u_int8_t, u_int8_t, char *); extern int bgp_attr_parse(struct bgp_peer *, struct bgp_attr *, struct bgp_attr_extra *, char *, int, struct bgp_nlri *, struct bgp_nlri *); extern int bgp_attr_parse_community(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t); extern int bgp_attr_parse_ecommunity(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t); extern int bgp_attr_parse_lcommunity(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t); extern int bgp_attr_parse_aspath(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t); extern int bgp_attr_parse_as4path(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t, struct aspath **); extern int bgp_attr_parse_nexthop(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_int8_t); extern int bgp_attr_parse_med(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_char); extern int bgp_attr_parse_local_pref(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_char); extern int bgp_attr_parse_origin(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, u_char); extern int bgp_attr_parse_mp_reach(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, struct bgp_nlri *); extern int bgp_attr_parse_mp_unreach(struct bgp_peer *, u_int16_t, struct bgp_attr *, char *, struct bgp_nlri *); extern int bgp_attr_parse_aigp(struct bgp_peer *, u_int16_t, struct bgp_attr_extra *, char *, u_char); extern int bgp_attr_parse_prefix_sid(struct bgp_peer *, u_int16_t, struct bgp_attr_extra *, char *, u_char); extern int bgp_nlri_parse(struct bgp_msg_data *, void *, struct bgp_attr_extra *, struct bgp_nlri *, int); extern int bgp_process_update(struct bgp_msg_data *, struct prefix *, void *, struct bgp_attr_extra *, afi_t, safi_t, int); extern int bgp_process_withdraw(struct bgp_msg_data *, struct prefix *, void *, struct bgp_attr_extra *, afi_t, safi_t, int); #endif pmacct-1.7.8/src/bgp/bgp_xcs-data.h0000644000175000017500000000175314354105275016064 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ const struct _map_dictionary_line bgp_xcs_map_dictionary[] = { {"bgp_dst", bgp_xcs_map_dst_handler}, {"bgp_src", bgp_xcs_map_src_handler}, {"", NULL} }; pmacct-1.7.8/src/bgp/bgp_hash.c0000644000175000017500000001262114354105275015272 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* * Originally based on Quagga hash routine which is: * * Copyright (C) 1998 Kunihiro Ishiguro * * GNU Zebra 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, or (at your * option) any later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "bgp.h" /* Allocate a new hash. */ struct hash * hash_create_size (unsigned int size, unsigned int (*hash_key) (void *), int (*hash_cmp) (const void *, const void *)) { struct hash *hash; hash = malloc(sizeof (struct hash)); if (!hash) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (hash_create_size). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset (hash, 0, sizeof (struct hash)); hash->index = malloc(sizeof (struct hash_backet *) * size); if (!hash->index) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (hash_create_size). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset (hash->index, 0, sizeof (struct hash_backet *) * size); hash->size = size; hash->hash_key = hash_key; hash->hash_cmp = hash_cmp; hash->count = 0; return hash; } /* Allocate a new hash with default hash size. */ struct hash * hash_create (int buckets, unsigned int (*hash_key) (void *), int (*hash_cmp) (const void *, const void *)) { return hash_create_size (buckets, hash_key, hash_cmp); } /* Utility function for hash_get(). When this function is specified as alloc_func, return arugment as it is. This function is used for intern already allocated value. */ void * hash_alloc_intern (void *arg) { return arg; } /* Lookup and return hash backet in hash. If there is no corresponding hash backet and alloc_func is specified, create new hash backet. */ void * hash_get (struct bgp_peer *peer, struct hash *hash, void *data, void * (*alloc_func) (void *)) { struct bgp_misc_structs *bms; unsigned int key; unsigned int index; void *newdata; struct hash_backet *backet; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; key = (*hash->hash_key) (data); index = key % hash->size; for (backet = hash->index[index]; backet != NULL; backet = backet->next) if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) return backet->data; if (alloc_func) { newdata = (*alloc_func) (data); if (!newdata) { Log(LOG_ERR, "ERROR ( %s/%s ): alloc_func failed (hash_get). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } backet = malloc(sizeof (struct hash_backet)); if (!backet) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (hash_get). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memset(backet, 0, sizeof (struct hash_backet)); backet->data = newdata; backet->key = key; backet->next = hash->index[index]; hash->index[index] = backet; hash->count++; return backet->data; } return NULL; } /* This function release registered value from specified hash. When release is successfully finished, return the data pointer in the hash backet. */ void * hash_release (struct hash *hash, void *data) { void *ret; unsigned int key; unsigned int index; struct hash_backet *backet; struct hash_backet *pp; key = (*hash->hash_key) (data); index = key % hash->size; for (backet = pp = hash->index[index]; backet; backet = backet->next) { if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) { if (backet == pp) hash->index[index] = backet->next; else pp->next = backet->next; ret = backet->data; free(backet); hash->count--; return ret; } pp = backet; } return NULL; } /* Iterator function for hash. */ void hash_iterate (struct hash *hash, void (*func) (struct hash_backet *, void *), void *arg) { unsigned int i; struct hash_backet *hb; struct hash_backet *hbnext; for (i = 0; i < hash->size; i++) for (hb = hash->index[i]; hb; hb = hbnext) { /* get pointer to next hash backet here, in case (*func) * decides to delete hb by calling hash_release */ hbnext = hb->next; (*func) (hb, arg); } } /* Clean up hash. */ void hash_clean (struct hash *hash, void (*free_func) (void *)) { unsigned int i; struct hash_backet *hb; struct hash_backet *next; for (i = 0; i < hash->size; i++) { for (hb = hash->index[i]; hb; hb = next) { next = hb->next; if (free_func) (*free_func) (hb->data); free(hb); hash->count--; } hash->index[i] = NULL; } } /* Free hash memory. You may call hash_clean before call this function. */ void hash_free (struct hash *hash) { free(hash->index); free(hash); } pmacct-1.7.8/src/bgp/bgp_table.h0000644000175000017500000000771614354105275015454 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* Originally based on Quagga BGP routing table which is: Copyright (C) 1998, 2001 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_TABLE_H_ #define _BGP_TABLE_H_ #define DEFAULT_BGP_INFO_HASH 13 #define DEFAULT_BGP_INFO_PER_PEER_HASH 1 #define BGP_NODE_VECTOR_MAX_DEPTH 128 struct bgp_table { /* afi/safi of this table */ afi_t afi; safi_t safi; /* The owner of this 'bgp_table' structure. */ void *owner; struct bgp_node *top; unsigned long count; }; struct bgp_node { struct prefix p; struct bgp_table *table; struct bgp_node *parent; struct bgp_node *link[2]; #define l_left link[0] #define l_right link[1] void **info; unsigned int lock; }; struct bgp_msg_extra_data { u_int8_t id; u_int16_t len; void *data; }; struct bgp_attr_extra { u_int8_t bitmap; rd_t rd; u_char label[3]; path_id_t path_id; u_int64_t aigp; u_int32_t psid_li; }; struct bgp_info { struct bgp_info *next; struct bgp_info *prev; struct bgp_peer *peer; struct bgp_attr *attr; struct bgp_attr_extra *attr_extra; struct bgp_msg_extra_data bmed; }; struct node_match_cmp_term2 { struct bgp_peer *peer; afi_t afi; safi_t safi; rd_t *rd; struct host_addr *peer_dst_ip; /* mainly used for RPKI purposes */ struct prefix *p; as_t last_as; int ret_code; }; struct bgp_node_vector_entry { struct prefix *p; struct bgp_info *info; }; struct bgp_node_vector { u_int8_t entries; struct bgp_node_vector_entry v[BGP_NODE_VECTOR_MAX_DEPTH]; }; /* Prototypes */ extern struct bgp_table *bgp_table_init (afi_t, safi_t); extern void bgp_unlock_node (struct bgp_peer *, struct bgp_node *node); extern struct bgp_node *bgp_table_top (struct bgp_peer *, const struct bgp_table *const); extern struct bgp_node *bgp_route_next (struct bgp_peer *, struct bgp_node *); extern struct bgp_node *bgp_node_get (struct bgp_peer *, struct bgp_table *const, struct prefix *); extern struct bgp_node *bgp_lock_node (struct bgp_peer *, struct bgp_node *node); extern void bgp_node_vector_debug(struct bgp_node_vector *, struct prefix *); extern void bgp_node_match (const struct bgp_table *, struct prefix *, struct bgp_peer *, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *, struct bgp_node_vector *, struct bgp_node **result_node, struct bgp_info **result_info); extern void bgp_node_match_ipv4 (const struct bgp_table *, struct in_addr *, struct bgp_peer *, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *, struct bgp_node_vector *, struct bgp_node **result_node, struct bgp_info **result_info); extern void bgp_node_match_ipv6 (const struct bgp_table *, struct in6_addr *, struct bgp_peer *, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *, struct bgp_node_vector *, struct bgp_node **result_node, struct bgp_info **result_info); extern void bgp_table_free (struct bgp_table *); #endif pmacct-1.7.8/src/bgp/bgp_aspath.h0000644000175000017500000001123014354105275015627 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on Quagga AS path related definitions which is: Copyright (C) 1997, 98, 99 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_ASPATH_H_ #define _BGP_ASPATH_H_ /* AS path segment type. */ #define AS_SET 1 #define AS_SEQUENCE 2 #define AS_CONFED_SEQUENCE 3 #define AS_CONFED_SET 4 /* Private AS range defined in RFC2270. */ #define BGP_PRIVATE_AS_MIN 64512U #define BGP_PRIVATE_AS_MAX 65535U /* we leave BGP_AS_MAX as the 16bit AS MAX number. */ #define BGP_AS_MAX 65535U #define BGP_AS4_MAX 4294967295U /* Transition 16Bit AS as defined by IANA */ #define BGP_AS_TRANS 23456U /* Attr. Flags and Attr. Type Code. */ #define AS_HEADER_SIZE 2 /* Now FOUR octets are used for AS value. */ #define AS_VALUE_SIZE sizeof (as_t) /* This is the old one */ #define AS16_VALUE_SIZE sizeof (as16_t) /* Maximum protocol segment length value */ #define AS_SEGMENT_MAX 255 /* Calculated size in bytes of ASN segment data to hold N ASN's */ #define ASSEGMENT_DATA_SIZE(N,S) \ ((N) * ( (S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE) ) /* Calculated size of segment struct to hold N ASN's */ #define ASSEGMENT_SIZE(N,S) (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N,S)) /* AS segment octet length. */ #define ASSEGMENT_LEN(X,S) ASSEGMENT_SIZE((X)->length,S) /* AS_SEQUENCE segments can be packed together */ /* Can the types of X and Y be considered for packing? */ #define ASSEGMENT_TYPES_PACKABLE(X,Y) \ ( ((X)->type == (Y)->type) \ && ((X)->type == AS_SEQUENCE)) /* Types and length of X,Y suitable for packing? */ #define ASSEGMENTS_PACKABLE(X,Y) \ ( ASSEGMENT_TYPES_PACKABLE( (X), (Y)) \ && ( ((X)->length + (Y)->length) <= AS_SEGMENT_MAX ) ) #define ASPATH_STR_DEFAULT_LEN 32 /* AS path string lexical token enum. */ enum as_token { as_token_asval, as_token_set_start, as_token_set_end, as_token_confed_seq_start, as_token_confed_seq_end, as_token_confed_set_start, as_token_confed_set_end, as_token_unknown }; /* As segment header - the on-wire representation NOT the internal representation! */ struct assegment_header { u_char type; u_char length; }; /* AS_PATH segment data in abstracted form, no limit is placed on length */ struct assegment { struct assegment *next; as_t *as; u_short length; u_char type; }; /* AS path may be include some AsSegments. */ struct aspath { /* Reference count to this aspath. */ unsigned long refcnt; /* segment data */ struct assegment *segments; as_t last_as; char *str; }; /* Prototypes. */ extern void aspath_init (int, struct hash **); extern struct aspath *aspath_parse (struct bgp_peer *, char *, size_t, int); extern struct aspath *aspath_dup (struct aspath *); extern int aspath_cmp_left (const struct aspath *, const struct aspath *); extern int aspath_cmp_left_confed (const struct aspath *, const struct aspath *); extern void aspath_free (struct aspath *); extern struct aspath *aspath_intern (struct bgp_peer *, struct aspath *); extern void aspath_unintern (struct bgp_peer *, struct aspath *); extern const char *aspath_print (struct aspath *); extern const char *aspath_gettoken (const char *, enum as_token *, as_t *); extern struct aspath *aspath_str2aspath (const char *); extern struct aspath *aspath_ast2aspath (as_t); extern struct aspath *aspath_parse_ast(struct bgp_peer *, as_t); extern unsigned int aspath_key_make (void *); extern int aspath_loop_check (struct aspath *, as_t); extern int aspath_private_as_check (struct aspath *); extern int aspath_firstas_check (struct aspath *, as_t); extern unsigned int aspath_count_hops (struct aspath *); extern unsigned int aspath_count_confeds (struct aspath *); extern unsigned int aspath_size (struct aspath *); extern as_t aspath_highest (struct aspath *); extern char *aspath_make_empty(); extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *); extern unsigned int aspath_has_as4 (struct aspath *); extern unsigned int aspath_count_numas (struct aspath *); #endif pmacct-1.7.8/src/bgp/bgp_ecommunity.c0000644000175000017500000002527714354105275016553 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* Originally based on Quagga BGP extended community attribute related functions which is: Copyright (C) 2000 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "bgp_prefix.h" #include "bgp.h" /* Allocate a new ecommunities. */ struct ecommunity * ecommunity_new (struct bgp_peer *peer) { struct bgp_misc_structs *bms; void *tmp; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; tmp = malloc(sizeof (struct ecommunity)); if (!tmp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (ecommunity_new). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memset(tmp, 0, sizeof (struct ecommunity)); return (struct ecommunity *) tmp; } /* Allocate ecommunities. */ void ecommunity_free (struct ecommunity *ecom) { if (ecom->val) free(ecom->val); if (ecom->str) free(ecom->str); free(ecom); } /* Add a new Extended Communities value to Extended Communities Attribute structure. When the value is already exists in the structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ static int ecommunity_add_val (struct bgp_peer *peer, struct ecommunity *ecom, struct ecommunity_val *eval) { struct bgp_misc_structs *bms; u_int8_t *p; int ret; int c; if (!peer) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; /* When this is fist value, just add it. */ if (ecom->val == NULL) { ecom->size++; ecom->val = malloc(ecom_length (ecom)); if (!ecom->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (ecommunity_add_val). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memcpy (ecom->val, eval->val, ECOMMUNITY_SIZE); return 1; } /* If the value already exists in the structure return 0. */ c = 0; for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { ret = memcmp (p, eval->val, ECOMMUNITY_SIZE); if (ret == 0) return 0; if (ret > 0) break; } /* Add the value to the structure with numerical sorting. */ ecom->size++; ecom->val = realloc(ecom->val, ecom_length (ecom)); memmove (ecom->val + (c + 1) * ECOMMUNITY_SIZE, ecom->val + c * ECOMMUNITY_SIZE, (ecom->size - 1 - c) * ECOMMUNITY_SIZE); memcpy (ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE); return 1; } /* This function takes pointer to Extended Communites strucutre then create a new Extended Communities structure by uniq and sort each Exteneded Communities value. */ static struct ecommunity * ecommunity_uniq_sort (struct bgp_peer *peer, struct ecommunity *ecom) { int i; struct ecommunity *new; struct ecommunity_val *eval; if (!ecom) return NULL; new = ecommunity_new (peer); for (i = 0; i < ecom->size; i++) { eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); ecommunity_add_val (peer, new, eval); } return new; } /* Parse Extended Communites Attribute in BGP packet. */ struct ecommunity * ecommunity_parse (struct bgp_peer *peer, u_int8_t *pnt, u_short length) { struct ecommunity tmp; struct ecommunity *new; /* Length check. */ if (length % ECOMMUNITY_SIZE) return NULL; /* Prepare tmporary structure for making a new Extended Communities Attribute. */ tmp.size = length / ECOMMUNITY_SIZE; tmp.val = pnt; /* Create a new Extended Communities Attribute by uniq and sort each Extended Communities value */ new = ecommunity_uniq_sort (peer, &tmp); return ecommunity_intern (peer, new); } /* Intern Extended Communities Attribute. */ struct ecommunity * ecommunity_intern (struct bgp_peer *peer, struct ecommunity *ecom) { struct bgp_rt_structs *inter_domain_routing_db; struct ecommunity *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; assert (ecom->refcnt == 0); find = (struct ecommunity *) hash_get(peer, inter_domain_routing_db->ecomhash, ecom, hash_alloc_intern); if (find != ecom) ecommunity_free (ecom); find->refcnt++; if (! find->str) find->str = ecommunity_ecom2str (peer, find, ECOMMUNITY_FORMAT_DISPLAY); return find; } /* Unintern Extended Communities Attribute. */ void ecommunity_unintern (struct bgp_peer *peer, struct ecommunity *ecom) { struct bgp_rt_structs *inter_domain_routing_db; struct ecommunity *ret = NULL; (void) ret; if (!peer) return; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return; if (ecom->refcnt) ecom->refcnt--; /* Pull off from hash. */ if (ecom->refcnt == 0) { /* Extended community must be in the hash. */ ret = (struct ecommunity *) hash_release(inter_domain_routing_db->ecomhash, ecom); assert (ret != NULL); ecommunity_free(ecom); } } /* Utinity function to make hash key. */ unsigned int ecommunity_hash_make (void *arg) { const struct ecommunity *ecom = arg; int c; unsigned int key; u_int8_t *pnt; key = 0; pnt = ecom->val; for (c = 0; c < ecom->size * ECOMMUNITY_SIZE; c++) key += pnt[c]; return key; } /* Compare two Extended Communities Attribute structure. */ int ecommunity_cmp (const void *arg1, const void *arg2) { const struct ecommunity *ecom1 = arg1; const struct ecommunity *ecom2 = arg2; return (ecom1->size == ecom2->size && memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0); } /* Initialize Extended Comminities related hash. */ void ecommunity_init (int buckets, struct hash **loc_ecomhash) { (*loc_ecomhash) = hash_create (buckets, ecommunity_hash_make, ecommunity_cmp); } /* Convert extended community attribute to string. Due to historical reason of industry standard implementation, there are three types of format. route-map set extcommunity format "rt 100:1 100:2" "soo 100:3" extcommunity-list "rt 100:1 rt 100:2 soo 100:3" "show ip bgp" and extcommunity-list regular expression matching "RT:100:1 RT:100:2 SoO:100:3" For each formath please use below definition for format: ECOMMUNITY_FORMAT_ROUTE_MAP ECOMMUNITY_FORMAT_COMMUNITY_LIST ECOMMUNITY_FORMAT_DISPLAY */ char * ecommunity_ecom2str (struct bgp_peer *peer, struct ecommunity *ecom, int format) { struct bgp_misc_structs *bms; int i; u_int8_t *pnt; int encode = 0; int type = 0; #define ECOMMUNITY_STR_DEFAULT_LEN 27 int str_size; int str_pnt; char *str_buf; const char *prefix; int len = 0; int first = 1; /* For parse Extended Community attribute tupple. */ struct ecommunity_as { as_t as; u_int32_t val; } eas; struct ecommunity_ip { struct in_addr ip; u_int16_t val; } eip; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; if (ecom->size == 0) { str_buf = malloc(1); if (!str_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (ecommunity_ecom2str). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } str_buf[0] = '\0'; return str_buf; } /* Prepare buffer. */ str_buf = malloc(ECOMMUNITY_STR_DEFAULT_LEN + 1); if (!str_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (ecommunity_ecom2str). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1; str_pnt = 0; for (i = 0; i < ecom->size; i++) { /* Make it sure size is enough. */ while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) { str_size *= 2; str_buf = realloc(str_buf, str_size); } /* Space between each value. */ if (! first) str_buf[str_pnt++] = ' '; pnt = ecom->val + (i * 8); /* High-order octet of type. */ encode = *pnt++; if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP && encode != ECOMMUNITY_ENCODE_AS4) { len = sprintf (str_buf + str_pnt, "?"); str_pnt += len; first = 0; continue; } /* Low-order octet of type. */ type = *pnt++; if (type != ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN) { len = sprintf (str_buf + str_pnt, "?"); str_pnt += len; first = 0; continue; } switch (format) { case ECOMMUNITY_FORMAT_COMMUNITY_LIST: prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo "); break; case ECOMMUNITY_FORMAT_DISPLAY: prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:"); break; case ECOMMUNITY_FORMAT_ROUTE_MAP: prefix = ""; break; default: prefix = ""; break; } /* Put string into buffer. */ if (encode == ECOMMUNITY_ENCODE_AS4) { eas.as = (*pnt++ << 24); eas.as |= (*pnt++ << 16); eas.as |= (*pnt++ << 8); eas.as |= (*pnt++); eas.val = (*pnt++ << 8); eas.val |= (*pnt++); len = sprintf( str_buf + str_pnt, "%s%u:%u", prefix, eas.as, eas.val ); str_pnt += len; first = 0; } if (encode == ECOMMUNITY_ENCODE_AS) { eas.as = (*pnt++ << 8); eas.as |= (*pnt++); eas.val = (*pnt++ << 24); eas.val |= (*pnt++ << 16); eas.val |= (*pnt++ << 8); eas.val |= (*pnt++); len = sprintf (str_buf + str_pnt, "%s%u:%u", prefix, eas.as, eas.val); str_pnt += len; first = 0; } else if (encode == ECOMMUNITY_ENCODE_IP) { memcpy (&eip.ip, pnt, 4); pnt += 4; eip.val = (*pnt++ << 8); eip.val |= (*pnt++); len = sprintf (str_buf + str_pnt, "%s%s:%u", prefix, inet_ntoa (eip.ip), eip.val); str_pnt += len; first = 0; } } return str_buf; } struct ecommunity *ecommunity_dup(struct ecommunity *ecom) { struct ecommunity *new; new = malloc(sizeof(struct ecommunity)); new->size = ecom->size; if (new->size) { new->val = malloc(ecom->size * ECOMMUNITY_SIZE); memcpy (new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE); } else new->val = NULL; return new; } pmacct-1.7.8/src/bgp/bgp_lcommunity.c0000644000175000017500000002023314354105275016545 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Based on BGP standard and extended communities implementation from Quagga */ #include "pmacct.h" #include "bgp_prefix.h" #include "bgp.h" /* Allocate a new lcommunities. */ struct lcommunity * lcommunity_new (struct bgp_peer *peer) { struct bgp_misc_structs *bms; void *tmp; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; tmp = malloc(sizeof (struct lcommunity)); if (!tmp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (lcommunity_new). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memset(tmp, 0, sizeof (struct lcommunity)); return (struct lcommunity *) tmp; } /* Allocate lcommunities. */ void lcommunity_free (struct lcommunity *lcom) { if (lcom->val) free(lcom->val); if (lcom->str) free(lcom->str); free(lcom); } /* Add a new Large Communities value to Large Communities Attribute structure. When the value already exists in the structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ static int lcommunity_add_val (struct bgp_peer *peer, struct lcommunity *lcom, struct lcommunity_val *lval) { struct bgp_misc_structs *bms; u_int8_t *p; int ret; int c; if (!peer) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; /* When this is fist value, just add it. */ if (lcom->val == NULL) { lcom->size++; lcom->val = malloc(lcom_length (lcom)); if (!lcom->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (lcommunity_add_val). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE); return 1; } /* If the value already exists in the structure return 0. */ c = 0; for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) { ret = memcmp (p, lval->val, LCOMMUNITY_SIZE); if (ret == 0) return 0; if (ret > 0) break; } /* Add the value to the structure with numerical sorting. */ lcom->size++; lcom->val = realloc(lcom->val, lcom_length (lcom)); memmove (lcom->val + (c + 1) * LCOMMUNITY_SIZE, lcom->val + c * LCOMMUNITY_SIZE, (lcom->size - 1 - c) * LCOMMUNITY_SIZE); memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); return 1; } /* This function takes pointer to Large Communites strucutre then create a new Large Communities structure by uniq and sort each Exteneded Communities value. */ static struct lcommunity * lcommunity_uniq_sort (struct bgp_peer *peer, struct lcommunity *lcom) { int i; struct lcommunity *new; struct lcommunity_val *lval; if (!lcom) return NULL; new = lcommunity_new (peer); for (i = 0; i < lcom->size; i++) { lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE)); lcommunity_add_val (peer, new, lval); } return new; } /* Parse Large Communites Attribute in BGP packet. */ struct lcommunity * lcommunity_parse (struct bgp_peer *peer, u_int8_t *pnt, u_short length) { struct lcommunity tmp; struct lcommunity *new; /* Length check. */ if (length % LCOMMUNITY_SIZE) return NULL; /* Prepare tmporary structure for making a new Large Communities Attribute. */ tmp.size = length / LCOMMUNITY_SIZE; tmp.val = pnt; /* Create a new Large Communities Attribute by uniq and sort each Large Communities value */ new = lcommunity_uniq_sort (peer, &tmp); return lcommunity_intern (peer, new); } /* Intern Large Communities Attribute. */ struct lcommunity * lcommunity_intern (struct bgp_peer *peer, struct lcommunity *lcom) { struct bgp_rt_structs *inter_domain_routing_db; struct lcommunity *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; assert (lcom->refcnt == 0); find = (struct lcommunity *) hash_get(peer, inter_domain_routing_db->lcomhash, lcom, hash_alloc_intern); if (find != lcom) lcommunity_free (lcom); find->refcnt++; if (! find->str) find->str = lcommunity_lcom2str (peer, find); return find; } /* Unintern Large Communities Attribute. */ void lcommunity_unintern (struct bgp_peer *peer, struct lcommunity *lcom) { struct bgp_rt_structs *inter_domain_routing_db; struct lcommunity *ret = NULL; (void) ret; if (!peer) return; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return; if (lcom->refcnt) lcom->refcnt--; /* Pull off from hash. */ if (lcom->refcnt == 0) { /* Large community must be in the hash. */ ret = (struct lcommunity *) hash_release(inter_domain_routing_db->lcomhash, lcom); assert (ret != NULL); lcommunity_free(lcom); } } /* Utinity function to make hash key. */ unsigned int lcommunity_hash_make (void *arg) { const struct lcommunity *lcom = arg; int c; unsigned int key; u_int8_t *pnt; key = 0; pnt = lcom->val; for (c = 0; c < lcom->size * LCOMMUNITY_SIZE; c++) key += pnt[c]; return key; } /* Compare two Large Communities Attribute structure. */ int lcommunity_cmp (const void *arg1, const void *arg2) { const struct lcommunity *lcom1 = arg1; const struct lcommunity *lcom2 = arg2; return (lcom1->size == lcom2->size && memcmp (lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) == 0); } /* Initialize Large Comminities related hash. */ void lcommunity_init (int buckets, struct hash **loc_lcomhash) { (*loc_lcomhash) = hash_create (buckets, lcommunity_hash_make, lcommunity_cmp); } char * lcommunity_lcom2str (struct bgp_peer *peer, struct lcommunity *lcom) { struct bgp_misc_structs *bms; int idx, str_pnt, str_size, first = TRUE; u_int32_t npart1, npart2, npart3; u_int32_t hpart1, hpart2, hpart3; char *str_buf = NULL; u_int8_t *pnt; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; if (lcom->size == 0) { str_buf = malloc(1); if (!str_buf) goto exit_lane; str_buf[0] = '\0'; return str_buf; } for (idx = 0, str_pnt = 0, str_size = 0; idx < lcom->size; idx++) { str_size += (LCOMMUNITY_STR_DEFAULT_LEN + 1); if (!first) str_buf = realloc(str_buf, str_size); else str_buf = malloc(str_size); if (!str_buf) goto exit_lane; if (!first) str_buf[str_pnt++] = ' '; pnt = lcom->val + (idx * LCOMMUNITY_SIZE); memcpy(&npart1, pnt, LCOMMUNITY_PART_SIZE); memcpy(&npart2, (pnt + LCOMMUNITY_PART_SIZE), LCOMMUNITY_PART_SIZE); memcpy(&npart3, (pnt + LCOMMUNITY_PART_SIZE + LCOMMUNITY_PART_SIZE), LCOMMUNITY_PART_SIZE); hpart1 = ntohl(npart1); hpart2 = ntohl(npart2); hpart3 = ntohl(npart3); sprintf(&str_buf[str_pnt], "%u:%u:%u", hpart1, hpart2, hpart3); str_pnt = strlen(str_buf); first = FALSE; } return str_buf; exit_lane: Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (lcommunity_lcom2str). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); return NULL; /* silence compiler warning */ } struct lcommunity *lcommunity_dup(struct lcommunity *lcom) { struct lcommunity *new; new = malloc(sizeof(struct lcommunity)); new->size = lcom->size; if (new->size) { new->val = malloc(lcom->size * LCOMMUNITY_SIZE); memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE); } else new->val = NULL; return new; } pmacct-1.7.8/src/bgp/bgp_msg.c0000644000175000017500000013574314354105275015150 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp.h" #include "bgp_blackhole.h" int bgp_parse_msg(struct bgp_peer *peer, time_t now, int online) { struct bgp_misc_structs *bms; struct bgp_msg_data bmd; char *bgp_packet_ptr; char bgp_peer_str[INET6_ADDRSTRLEN]; struct bgp_header *bhdr; int ret, bgp_len = 0; if (!peer || !peer->buf.base) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; memset(&bmd, 0, sizeof(bmd)); bmd.peer = peer; for (bgp_packet_ptr = peer->buf.base; peer->msglen > 0; peer->msglen -= bgp_len, bgp_packet_ptr += bgp_len) { bhdr = (struct bgp_header *) bgp_packet_ptr; if (peer->msglen < BGP_HEADER_SIZE && bgp_packet_ptr == peer->buf.base) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP packet (incomplete header).\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_HEADER_ERR; } bgp_len = ntohs(bhdr->bgpo_len); if (bgp_max_msglen_check(bgp_len) == ERR) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP packet (packet length check failed).\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_HEADER_ERR; } if (bgp_marker_check(bhdr, BGP_MARKER_SIZE) == ERR) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP packet (marker check failed).\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_HEADER_ERR; } switch (bhdr->bgpo_type) { case BGP_OPEN: ret = bgp_parse_open_msg(&bmd, bgp_packet_ptr, now, online); if (ret < 0) return BGP_NOTIFY_OPEN_ERR; break; case BGP_NOTIFICATION: { u_int16_t shutdown_msglen = (BGP_NOTIFY_CEASE_SM_LEN + 1); u_int8_t res_maj = 0, res_min = 0; char shutdown_msg[shutdown_msglen]; memset(shutdown_msg, 0, shutdown_msglen); bgp_parse_notification_msg(&bmd, bgp_packet_ptr, &res_maj, &res_min, shutdown_msg, shutdown_msglen); bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] BGP_NOTIFICATION received (%u, %u). Shutdown Message: '%s'\n", config.name, bms->log_str, bgp_peer_str, res_maj, res_min, shutdown_msg); return ERR; } case BGP_KEEPALIVE: bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] BGP_KEEPALIVE received\n", config.name, bms->log_str, bgp_peer_str); if (peer->status >= OpenSent) { if (peer->status < Established) peer->status = Established; if (online) { char bgp_reply_pkt[BGP_BUFFER_SIZE], *bgp_reply_pkt_ptr; memset(bgp_reply_pkt, 0, BGP_BUFFER_SIZE); bgp_reply_pkt_ptr = bgp_reply_pkt; bgp_reply_pkt_ptr += bgp_write_keepalive_msg(bgp_reply_pkt_ptr); ret = send(peer->fd, bgp_reply_pkt, bgp_reply_pkt_ptr - bgp_reply_pkt, 0); peer->last_keepalive = now; bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] BGP_KEEPALIVE sent\n", config.name, bms->log_str, bgp_peer_str); } } /* If we didn't pass through a successful BGP OPEN exchange just yet let's temporarily silently discard BGP KEEPALIVEs */ break; case BGP_UPDATE: if (peer->status < Established) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] BGP UPDATE received (no neighbor). Discarding.\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_FSM_ERR; } ret = bgp_parse_update_msg(&bmd, bgp_packet_ptr); if (ret < 0) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] BGP UPDATE: malformed.\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_UPDATE_ERR; } break; case BGP_ROUTE_REFRESH: /* just ignore */ break; default: bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP packet (unsupported message type).\n", config.name, bms->log_str, bgp_peer_str); return BGP_NOTIFY_HEADER_ERR; } } return SUCCESS; } int bgp_parse_open_msg(struct bgp_msg_data *bmd, char *bgp_packet_ptr, time_t now, int online) { struct bgp_peer *peer = bmd->peer; struct bgp_misc_structs *bms; char bgp_reply_pkt[BGP_BUFFER_SIZE], *bgp_reply_pkt_ptr; char bgp_peer_str[INET6_ADDRSTRLEN]; struct bgp_open *bopen; int ret; u_int16_t remote_as = 0; u_int32_t remote_as4 = 0; if (!peer || !bgp_packet_ptr) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; if (!online || (peer->status < OpenSent)) { peer->status = Active; bopen = (struct bgp_open *) bgp_packet_ptr; if (bopen->bgpo_version == BGP_VERSION4) { char bgp_open_cap_reply[BGP_BUFFER_SIZE-BGP_MIN_OPEN_MSG_SIZE]; char *bgp_open_cap_reply_ptr = bgp_open_cap_reply, *bgp_open_cap_ptr; remote_as = ntohs(bopen->bgpo_myas); peer->ht = MAX(5, ntohs(bopen->bgpo_holdtime)); peer->id.family = AF_INET; peer->id.address.ipv4.s_addr = bopen->bgpo_id; peer->version = BGP_VERSION4; /* Check: duplicate Router-IDs; BGP only, ie. no BMP */ if (!config.bgp_disable_router_id_check && bms->bgp_msg_open_router_id_check) { int check_ret; check_ret = bms->bgp_msg_open_router_id_check(bmd); if (check_ret) return check_ret; } /* OPEN options parsing */ if (bopen->bgpo_optlen && bopen->bgpo_optlen >= 2) { u_int8_t len, opt_type, opt_len; char *ptr; /* pre-flight check */ if (ntohs(bopen->bgpo_len) < (BGP_MIN_OPEN_MSG_SIZE + bopen->bgpo_optlen)) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (too long option length).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } ptr = bgp_packet_ptr + BGP_MIN_OPEN_MSG_SIZE; if (online) memset(bgp_open_cap_reply, 0, sizeof(bgp_open_cap_reply)); for (len = bopen->bgpo_optlen; len > 0; len -= opt_len, ptr += opt_len) { opt_type = (u_int8_t) ptr[0]; opt_len = (u_int8_t) ptr[1]; if (opt_len > len) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (option length overrun).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } /* * If we stumble upon capabilities let's iterate through them to find * those that we do support (ie. MP-BGP, 4-bytes AS support, etc.) */ if (opt_type == BGP_OPTION_CAPABILITY) { char *optcap_ptr, *bgp_open_cap_len_reply_ptr, *bgp_open_cap_base_reply_ptr; int optcap_len; bgp_open_cap_ptr = ptr; memcpy(bgp_open_cap_reply_ptr, bgp_open_cap_ptr, 2); bgp_open_cap_len_reply_ptr = bgp_open_cap_reply_ptr + 1; bgp_open_cap_base_reply_ptr = bgp_open_cap_reply_ptr; bgp_open_cap_reply_ptr += 2; ptr += 2; len -= 2; optcap_ptr = ptr; optcap_len = opt_len; while (optcap_len > 0) { u_int8_t cap_len = optcap_ptr[1]; u_int8_t cap_type = optcap_ptr[0]; if (cap_len > optcap_len) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (malformed capability: %u).\n", config.name, bms->log_str, bgp_peer_str, cap_type); return ERR; } if (cap_type == BGP_CAPABILITY_MULTIPROTOCOL) { char *cap_ptr = optcap_ptr+2; struct capability_mp_data cap_data; memcpy(&cap_data, cap_ptr, sizeof(cap_data)); if (online) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Capability: MultiProtocol [%u] AFI [%u] SAFI [%u]\n", config.name, bms->log_str, bgp_peer_str, cap_type, ntohs(cap_data.afi), cap_data.safi); } peer->cap_mp = TRUE; if (online) { memcpy(bgp_open_cap_reply_ptr, optcap_ptr, cap_len+2); bgp_open_cap_reply_ptr += cap_len+2; } } else if (cap_type == BGP_CAPABILITY_4_OCTET_AS_NUMBER) { char *cap_ptr = optcap_ptr+2; u_int32_t as4_ptr; if (cap_len == CAPABILITY_CODE_AS4_LEN) { struct capability_as4 cap_data; memcpy(&cap_data, cap_ptr, sizeof(cap_data)); if (online) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Capability: 4-bytes AS [%u] ASN [%u]\n", config.name, bms->log_str, bgp_peer_str, cap_type, ntohl(cap_data.as4)); } memcpy(&as4_ptr, cap_ptr, 4); remote_as4 = ntohl(as4_ptr); if (online) { memcpy(bgp_open_cap_reply_ptr, optcap_ptr, cap_len+2); peer->cap_4as = bgp_open_cap_reply_ptr+2; bgp_open_cap_reply_ptr += cap_len+2; } else peer->cap_4as = bgp_open_cap_ptr+4; } else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (malformed AS4 option).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } } else if (cap_type == BGP_CAPABILITY_ADD_PATHS) { if (!bms->cap_add_path_ignore) { char *cap_ptr = (optcap_ptr + 2); struct capability_add_paths cap_data; int cap_set = FALSE; u_int8_t *cap_newlen_ptr; /* ptr to field of outbound cap_len */ int cap_idx; /* check for each AFI.SAFI included if remote can send - only then reply with receive */ for (cap_idx = 0; cap_idx < cap_len; cap_idx += sizeof(struct capability_add_paths)) { memcpy(&cap_data, cap_ptr+cap_idx, sizeof(cap_data)); if (online) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Capability: ADD-PATHs [%u] AFI [%u] SAFI [%u] SEND_RECEIVE [%u]\n", config.name, bms->log_str, bgp_peer_str, cap_type, ntohs(cap_data.afi), cap_data.safi, cap_data.sndrcv); } if ((cap_data.sndrcv == 2 /* send */) || (cap_data.sndrcv == 3 /* send and receive */)) { afi_t cap_add_paths_afi = ntohs(cap_data.afi); if (cap_add_paths_afi < AFI_MAX && cap_data.safi < SAFI_MAX) { peer->cap_add_paths.cap[cap_add_paths_afi][cap_data.safi] = TRUE; if (cap_add_paths_afi > peer->cap_add_paths.afi_max) { peer->cap_add_paths.afi_max = cap_add_paths_afi; } if (cap_data.safi > peer->cap_add_paths.safi_max) { peer->cap_add_paths.safi_max = cap_data.safi; } } if (online) { if (!cap_set) { /* we need to send BGP_CAPABILITY_ADD_PATHS first */ cap_set = TRUE; memcpy(bgp_open_cap_reply_ptr, optcap_ptr, 2); cap_newlen_ptr = (u_char *)(bgp_open_cap_reply_ptr + 1); (*cap_newlen_ptr) = 0; bgp_open_cap_reply_ptr += 2; } cap_data.sndrcv = 1; /* we can receive */ (*cap_newlen_ptr) += sizeof(cap_data); memcpy(bgp_open_cap_reply_ptr, &cap_data, sizeof(cap_data)); bgp_open_cap_reply_ptr += sizeof(cap_data); } } } } } else if (cap_type == BGP_CAPABILITY_ROUTE_REFRESH) { if (config.tmp_bgp_daemon_route_refresh) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Capability: Route Refresh [%u]\n", config.name, bms->log_str, bgp_peer_str, cap_type); memcpy(bgp_open_cap_reply_ptr, optcap_ptr, cap_len+2); bgp_open_cap_reply_ptr += cap_len+2; } } optcap_ptr += (cap_len + 2); optcap_len -= (cap_len + 2); } /* writing the new capability length */ if (bgp_open_cap_reply_ptr > bgp_open_cap_base_reply_ptr + 2) { (*bgp_open_cap_len_reply_ptr) = ((bgp_open_cap_reply_ptr - bgp_open_cap_base_reply_ptr) - 2); } /* otherwise rollback */ else { bgp_open_cap_reply_ptr = bgp_open_cap_base_reply_ptr; } } else { ptr += 2; len -= 2; } } } /* Let's grasp the remote ASN */ if (remote_as == BGP_AS_TRANS) { if (remote_as4 && remote_as4 != BGP_AS_TRANS) peer->as = remote_as4; /* It is not valid to use the transitional ASN in the BGP OPEN and present an ASN == 0 or ASN == 23456 in the 4AS capability */ else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (invalid AS4 option).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } } else { if (remote_as4 == 0 || remote_as4 == remote_as) peer->as = remote_as; /* It is not valid to not use the transitional ASN in the BGP OPEN and present an ASN != remote_as in the 4AS capability */ else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (mismatching AS4 option).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } } if (online) { bgp_reply_pkt_ptr = bgp_reply_pkt; /* Replying to OPEN message */ if (!config.bgp_daemon_as) peer->myas = peer->as; else peer->myas = config.bgp_daemon_as; bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] BGP_OPEN: Local AS: %u Remote AS: %u HoldTime: %u\n", config.name, bms->log_str, bgp_peer_str, peer->myas, peer->as, peer->ht); ret = bgp_write_open_msg(bgp_reply_pkt_ptr, bgp_open_cap_reply, bgp_open_cap_reply_ptr-bgp_open_cap_reply, peer); if (ret > 0) bgp_reply_pkt_ptr += ret; else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Local peer is 4AS while remote peer is 2AS: unsupported configuration.\n", config.name, bms->log_str, bgp_peer_str); return ERR; } /* sticking a KEEPALIVE to it */ bgp_reply_pkt_ptr += bgp_write_keepalive_msg(bgp_reply_pkt_ptr); ret = send(peer->fd, bgp_reply_pkt, bgp_reply_pkt_ptr - bgp_reply_pkt, 0); peer->last_keepalive = now; } } else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_INFO, "INFO ( %s/%s ): [%s] Received malformed BGP Open packet (unsupported version).\n", config.name, bms->log_str, bgp_peer_str); return ERR; } peer->status = Established; return (BGP_MIN_OPEN_MSG_SIZE + bopen->bgpo_optlen); } return ERR; } int bgp_max_msglen_check(u_int32_t length) { if (length <= BGP_MAX_MSGLEN) return SUCCESS; else return ERR; } /* Marker check. */ int bgp_marker_check(struct bgp_header *bhdr, int length) { int i; for (i = 0; i < length; i++) if (bhdr->bgpo_marker[i] != 0xff) return ERR; return SUCCESS; } /* write BGP KEEPALIVE msg */ int bgp_write_keepalive_msg(char *msg) { struct bgp_header bhdr; memset(&bhdr.bgpo_marker, 0xff, BGP_MARKER_SIZE); bhdr.bgpo_type = BGP_KEEPALIVE; bhdr.bgpo_len = htons(BGP_HEADER_SIZE); memcpy(msg, &bhdr, sizeof(bhdr)); return BGP_HEADER_SIZE; } /* write BGP OPEN msg */ int bgp_write_open_msg(char *msg, char *cp_msg, int cp_msglen, struct bgp_peer *peer) { struct bgp_open *bopen_reply = (struct bgp_open *) msg; char my_id_static[] = "1.2.3.4", *my_id = my_id_static; struct host_addr my_id_addr, bgp_ip, bgp_id; u_int16_t local_as; u_int32_t *local_as4; memset(bopen_reply->bgpo_marker, 0xff, BGP_MARKER_SIZE); bopen_reply->bgpo_type = BGP_OPEN; bopen_reply->bgpo_version = BGP_VERSION4; bopen_reply->bgpo_holdtime = htons(peer->ht); if (peer->myas > BGP_AS_MAX) { if (peer->cap_4as) { bopen_reply->bgpo_myas = htons(BGP_AS_TRANS); local_as4 = (u_int32_t *) peer->cap_4as; *local_as4 = htonl(peer->myas); } /* This is currently an unsupported configuration */ else return ERR; } else { local_as = peer->myas; bopen_reply->bgpo_myas = htons(local_as); if (peer->cap_4as) { local_as4 = (u_int32_t *) peer->cap_4as; *local_as4 = htonl(peer->myas); } } if (cp_msglen) bopen_reply->bgpo_optlen = cp_msglen; bopen_reply->bgpo_len = htons(BGP_MIN_OPEN_MSG_SIZE + bopen_reply->bgpo_optlen); if (config.bgp_daemon_ip) str_to_addr(config.bgp_daemon_ip, &bgp_ip); else memset(&bgp_ip, 0, sizeof(bgp_ip)); if (config.bgp_daemon_id) str_to_addr(config.bgp_daemon_id, &bgp_id); else memset(&bgp_id, 0, sizeof(bgp_id)); /* set BGP router-ID trial #1 */ memset(&my_id_addr, 0, sizeof(my_id_addr)); if (config.bgp_daemon_id && !is_any(&bgp_id) && !my_id_addr.family) { my_id = config.bgp_daemon_id; str_to_addr(my_id, &my_id_addr); if (my_id_addr.family != AF_INET) memset(&my_id_addr, 0, sizeof(my_id_addr)); } /* set BGP router-ID trial #2 */ if (config.bgp_daemon_ip && !is_any(&bgp_ip) && !my_id_addr.family) { my_id = config.bgp_daemon_ip; str_to_addr(my_id, &my_id_addr); if (my_id_addr.family != AF_INET) memset(&my_id_addr, 0, sizeof(my_id_addr)); } /* set BGP router-ID trial #3 */ if (!my_id_addr.family) { my_id = my_id_static; str_to_addr(my_id, &my_id_addr); } bopen_reply->bgpo_id = my_id_addr.address.ipv4.s_addr; memcpy(msg+BGP_MIN_OPEN_MSG_SIZE, cp_msg, cp_msglen); return BGP_MIN_OPEN_MSG_SIZE + cp_msglen; } int bgp_write_notification_msg(char *msg, int msglen, u_int8_t n_major, u_int8_t n_minor, char *shutdown_msg) { struct bgp_notification *bn_reply = (struct bgp_notification *) msg; struct bgp_notification_shutdown_msg *bnsm_reply; u_int16_t shutdown_msglen; int ret = FALSE; char *reply_msg_ptr; if (bn_reply && msglen >= BGP_MIN_NOTIFICATION_MSG_SIZE) { memset(bn_reply->bgpn_marker, 0xff, BGP_MARKER_SIZE); bn_reply->bgpn_len = ntohs(BGP_MIN_NOTIFICATION_MSG_SIZE); bn_reply->bgpn_type = BGP_NOTIFICATION; if (!n_major) bn_reply->bgpn_major = BGP_NOTIFY_CEASE; else bn_reply->bgpn_major = n_major; if (!n_minor) bn_reply->bgpn_minor = BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN; else bn_reply->bgpn_minor = n_minor; ret += BGP_MIN_NOTIFICATION_MSG_SIZE; /* rfc8203 */ if (shutdown_msg) { shutdown_msglen = strlen(shutdown_msg); if (shutdown_msglen <= BGP_NOTIFY_CEASE_SM_LEN) { if (msglen >= (BGP_MIN_NOTIFICATION_MSG_SIZE + shutdown_msglen)) { reply_msg_ptr = (char *) (msg + BGP_MIN_NOTIFICATION_MSG_SIZE); memset(reply_msg_ptr, 0, (msglen - BGP_MIN_NOTIFICATION_MSG_SIZE)); bnsm_reply = (struct bgp_notification_shutdown_msg *) reply_msg_ptr; bnsm_reply->bgpnsm_len = shutdown_msglen; strncpy(bnsm_reply->bgpnsm_data, shutdown_msg, shutdown_msglen); bn_reply->bgpn_len = htons(BGP_MIN_NOTIFICATION_MSG_SIZE + shutdown_msglen + 1 /* bgpnsm_len */); ret += (shutdown_msglen + 1 /* bgpnsm_len */); } } } } return ret; } int bgp_parse_notification_msg(struct bgp_msg_data *bmd, char *pkt, u_int8_t *res_maj, u_int8_t *res_min, char *shutdown_msg, u_int16_t shutdown_msglen) { struct bgp_peer *peer = bmd->peer; struct bgp_notification *bn = (struct bgp_notification *) pkt; struct bgp_notification_shutdown_msg *bnsm; char *pkt_ptr = pkt; u_int32_t rem_len; int ret = 0; if (!peer || !pkt || !shutdown_msg || peer->msglen < BGP_MIN_NOTIFICATION_MSG_SIZE) return ERR; rem_len = peer->msglen; ret += BGP_MIN_NOTIFICATION_MSG_SIZE; rem_len -= BGP_MIN_NOTIFICATION_MSG_SIZE; (*res_maj) = bn->bgpn_major; (*res_min) = bn->bgpn_minor; /* rfc8203 */ if (bn->bgpn_major == BGP_NOTIFY_CEASE && (bn->bgpn_minor == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN || bn->bgpn_minor == BGP_NOTIFY_CEASE_ADMIN_RESET)) { if (rem_len) { pkt_ptr = (pkt + BGP_MIN_NOTIFICATION_MSG_SIZE); bnsm = (struct bgp_notification_shutdown_msg *) pkt_ptr; if (bnsm->bgpnsm_len <= rem_len && bnsm->bgpnsm_len < shutdown_msglen) { memcpy(shutdown_msg, bnsm->bgpnsm_data, bnsm->bgpnsm_len); shutdown_msg[bnsm->bgpnsm_len] = '\0'; ret += (bnsm->bgpnsm_len + 1); rem_len -= (bnsm->bgpnsm_len + 1); } } } return ret; } int bgp_parse_update_msg(struct bgp_msg_data *bmd, char *pkt) { struct bgp_misc_structs *bms; struct bgp_peer *peer = bmd->peer; char bgp_peer_str[INET6_ADDRSTRLEN]; struct bgp_header bhdr; struct bgp_attr attr; struct bgp_attr_extra attr_extra; u_int16_t attribute_len; u_int16_t update_len; u_int16_t withdraw_len; u_int16_t end, tmp; struct bgp_nlri update; struct bgp_nlri withdraw; struct bgp_nlri mp_update; struct bgp_nlri mp_withdraw; int ret, parsed = FALSE; if (!peer || !pkt) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; /* Set initial values. */ memset(&attr, 0, sizeof (struct bgp_attr)); memset(&attr_extra, 0, sizeof (struct bgp_attr_extra)); memset(&update, 0, sizeof (struct bgp_nlri)); memset(&withdraw, 0, sizeof (struct bgp_nlri)); memset(&mp_update, 0, sizeof (struct bgp_nlri)); memset(&mp_withdraw, 0, sizeof (struct bgp_nlri)); memcpy(&bhdr, pkt, sizeof(bhdr)); end = ntohs(bhdr.bgpo_len); end -= BGP_HEADER_SIZE; pkt += BGP_HEADER_SIZE; /* handling Unfeasible routes */ memcpy(&tmp, pkt, 2); withdraw_len = ntohs(tmp); if (withdraw_len > end) return ERR; else { end -= withdraw_len; pkt += 2; end -= 2; } if (withdraw_len > 0) { withdraw.afi = AFI_IP; withdraw.safi = SAFI_UNICAST; withdraw.nlri = (u_char *) pkt; withdraw.length = withdraw_len; pkt += withdraw_len; } /* handling Attributes */ memcpy(&tmp, pkt, 2); attribute_len = ntohs(tmp); if (attribute_len > end) return ERR; else { end -= attribute_len; pkt += 2; end -= 2; } if (attribute_len > 0) { ret = bgp_attr_parse(peer, &attr, &attr_extra, pkt, attribute_len, &mp_update, &mp_withdraw); if (ret < 0) return ret; pkt += attribute_len; } update_len = end; end = 0; if (update_len > 0) { update.afi = AFI_IP; update.safi = SAFI_UNICAST; update.nlri = (u_char *) pkt; update.length = update_len; } /* NLRI parsing */ if (withdraw.length) { bgp_nlri_parse(bmd, NULL, &attr_extra, &withdraw, BGP_NLRI_WITHDRAW); parsed = TRUE; } if (update.length) { bgp_nlri_parse(bmd, &attr, &attr_extra, &update, BGP_NLRI_UPDATE); parsed = TRUE; } if (mp_update.length && mp_update.afi == AFI_IP && (mp_update.safi == SAFI_UNICAST || mp_update.safi == SAFI_MPLS_LABEL || mp_update.safi == SAFI_MPLS_VPN)) { bgp_nlri_parse(bmd, &attr, &attr_extra, &mp_update, BGP_NLRI_UPDATE); parsed = TRUE; } if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && (mp_withdraw.safi == SAFI_UNICAST || mp_withdraw.safi == SAFI_MPLS_LABEL || mp_withdraw.safi == SAFI_MPLS_VPN)) { bgp_nlri_parse (bmd, NULL, &attr_extra, &mp_withdraw, BGP_NLRI_WITHDRAW); parsed = TRUE; } if (mp_update.length && mp_update.afi == AFI_IP6 && (mp_update.safi == SAFI_UNICAST || mp_update.safi == SAFI_MPLS_LABEL || mp_update.safi == SAFI_MPLS_VPN)) { bgp_nlri_parse(bmd, &attr, &attr_extra, &mp_update, BGP_NLRI_UPDATE); parsed = TRUE; } if (mp_withdraw.length && mp_withdraw.afi == AFI_IP6 && (mp_withdraw.safi == SAFI_UNICAST || mp_withdraw.safi == SAFI_MPLS_LABEL || mp_withdraw.safi == SAFI_MPLS_VPN)) { bgp_nlri_parse(bmd, NULL, &attr_extra, &mp_withdraw, BGP_NLRI_WITHDRAW); parsed = TRUE; } if (mp_update.length && mp_update.afi == AFI_BGP_LS && (mp_update.safi == SAFI_LS_GLOBAL || mp_update.safi == SAFI_LS_VPN)) { bgp_nlri_parse(bmd, &attr, &attr_extra, &mp_update, BGP_NLRI_UPDATE); parsed = TRUE; } if (mp_withdraw.length && mp_withdraw.afi == AFI_BGP_LS && (mp_withdraw.safi == SAFI_LS_GLOBAL || mp_withdraw.safi == SAFI_LS_VPN)) { bgp_nlri_parse(bmd, &attr, &attr_extra, &mp_update, BGP_NLRI_WITHDRAW); parsed = TRUE; } /* Checking receipt of End-of-RIB */ if (!update_len && !withdraw_len) { int eor = FALSE; afi_t afi = FALSE; safi_t safi = FALSE; if (!attribute_len) { eor = TRUE; afi = AFI_IP; safi = SAFI_UNICAST; } else if (!mp_withdraw.length && mp_withdraw.afi && mp_withdraw.safi && !parsed) { eor = TRUE; afi = mp_withdraw.afi; safi = mp_withdraw.safi; } if (eor) { char event_type[] = "log"; struct bgp_info ri; bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] bgp_parse_update_msg() Received unsupported NLRI afi=%u safi=%u\n", config.name, bms->log_str, bgp_peer_str, afi, safi); memset(&ri, 0, sizeof(ri)); ri.peer = peer; ri.bmed = bmd->extra; bgp_peer_log_msg(NULL, &ri, afi, safi, bms->tag, event_type, bms->msglog_output, NULL, BGP_LOG_TYPE_EOR); } } if ((update_len || withdraw_len || mp_update.length || mp_withdraw.length) && !parsed) { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] bgp_parse_update_msg() Received unsupported NLRI afi=%u safi=%u\n", config.name, bms->log_str, bgp_peer_str, mp_update.length ? mp_update.afi : mp_withdraw.afi, mp_update.length ? mp_update.safi : mp_withdraw.safi); } /* Everything is done. We unintern temporary structures which interned in bgp_attr_parse(). */ if (attr.aspath) aspath_unintern(peer, attr.aspath); if (attr.community) community_unintern(peer, attr.community); if (attr.ecommunity) ecommunity_unintern(peer, attr.ecommunity); if (attr.lcommunity) lcommunity_unintern(peer, attr.lcommunity); ret = ntohs(bhdr.bgpo_len); return ret; } /* BGP UPDATE Attribute parsing */ int bgp_attr_parse(struct bgp_peer *peer, struct bgp_attr *attr, struct bgp_attr_extra *attr_extra, char *ptr, int len, struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw) { int to_the_end = len, ret; u_int8_t flag, type, *tmp; u_int16_t tmp16, attr_len; struct aspath *as4_path = NULL; if (!ptr) return ERR; while (to_the_end > 0) { if (to_the_end < BGP_ATTR_MIN_LEN) return ERR; tmp = (u_int8_t *) ptr++; to_the_end--; flag = *tmp; tmp = (u_int8_t *) ptr++; to_the_end--; type = *tmp; /* Attribute length */ if (flag & BGP_ATTR_FLAG_EXTLEN) { memcpy(&tmp16, ptr, 2); ptr += 2; to_the_end -= 2; attr_len = ntohs(tmp16); if (attr_len > to_the_end) return ERR; } else { tmp = (u_int8_t *) ptr++; to_the_end--; attr_len = *tmp; if (attr_len > to_the_end) return ERR; } switch (type) { case BGP_ATTR_AS_PATH: ret = bgp_attr_parse_aspath(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_AS4_PATH: ret = bgp_attr_parse_as4path(peer, attr_len, attr, ptr, flag, &as4_path); break; case BGP_ATTR_NEXT_HOP: ret = bgp_attr_parse_nexthop(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_COMMUNITIES: ret = bgp_attr_parse_community(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_EXT_COMMUNITIES: ret = bgp_attr_parse_ecommunity(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_LARGE_COMMUNITIES: ret = bgp_attr_parse_lcommunity(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_MULTI_EXIT_DISC: ret = bgp_attr_parse_med(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_LOCAL_PREF: ret = bgp_attr_parse_local_pref(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_ORIGIN: ret = bgp_attr_parse_origin(peer, attr_len, attr, ptr, flag); break; case BGP_ATTR_MP_REACH_NLRI: ret = bgp_attr_parse_mp_reach(peer, attr_len, attr, ptr, mp_update); break; case BGP_ATTR_MP_UNREACH_NLRI: ret = bgp_attr_parse_mp_unreach(peer, attr_len, attr, ptr, mp_withdraw); break; case BGP_ATTR_AIGP: ret = bgp_attr_parse_aigp(peer, attr_len, attr_extra, ptr, flag); break; case BGP_ATTR_PREFIX_SID: ret = bgp_attr_parse_prefix_sid(peer, attr_len, attr_extra, ptr, flag); break; default: ret = 0; break; } if (ret < 0) return ret; ptr += attr_len; to_the_end -= attr_len; } if (as4_path) { /* AS_PATH and AS4_PATH merge up */ ret = bgp_attr_munge_as4path(peer, attr, as4_path); /* AS_PATH and AS4_PATH info are now fully merged; hence we can free up temporary structures. */ aspath_unintern(peer, as4_path); if (ret < 0) return ret; } return SUCCESS; } int bgp_attr_parse_aspath(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_int8_t flag) { u_int8_t cap_4as = peer->cap_4as ? 1 : 0; attr->aspath = aspath_parse(peer, ptr, len, cap_4as); return SUCCESS; } int bgp_attr_parse_as4path(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_int8_t flag, struct aspath **aspath4) { *aspath4 = aspath_parse(peer, ptr, len, 1); return SUCCESS; } int bgp_attr_parse_nexthop(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_char flag) { u_int32_t tmp; /* Length check. */ if (len != 4) return ERR; memcpy(&tmp, ptr, 4); attr->nexthop.s_addr = tmp; ptr += 4; return SUCCESS; } int bgp_attr_parse_community(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_int8_t flag) { if (len == 0) attr->community = NULL; else attr->community = (struct community *) community_parse(peer, (u_int32_t *)ptr, len); return SUCCESS; } int bgp_attr_parse_ecommunity(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_int8_t flag) { if (len == 0) attr->ecommunity = NULL; else attr->ecommunity = (struct ecommunity *) ecommunity_parse(peer, (u_char *) ptr, len); return SUCCESS; } int bgp_attr_parse_lcommunity(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_int8_t flag) { if (len == 0) attr->lcommunity = NULL; else attr->lcommunity = (struct lcommunity *) lcommunity_parse(peer, (u_char *) ptr, len); return SUCCESS; } /* MED atrribute. */ int bgp_attr_parse_med(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_char flag) { u_int32_t tmp; /* Length check. */ if (len != 4) return ERR; memcpy(&tmp, ptr, 4); attr->med = ntohl(tmp); attr->bitmap |= BGP_BMAP_ATTR_MULTI_EXIT_DISC; ptr += 4; return SUCCESS; } /* Local preference attribute. */ int bgp_attr_parse_local_pref(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_char flag) { u_int32_t tmp; if (len != 4) return ERR; memcpy(&tmp, ptr, 4); attr->local_pref = ntohl(tmp); attr->bitmap |= BGP_BMAP_ATTR_LOCAL_PREF; ptr += 4; return SUCCESS; } /* Origin attribute. */ int bgp_attr_parse_origin(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, u_char flag) { if (len != 1) return ERR; memcpy(&attr->origin, ptr, 1); ptr += 1; return SUCCESS; } int bgp_attr_parse_mp_reach(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, struct bgp_nlri *mp_update) { struct bgp_misc_structs *bms; u_int16_t afi, tmp16, mpreachlen, mpnhoplen; u_int16_t nlri_len; u_char safi; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; /* length check */ #define BGP_MP_REACH_MIN_SIZE 5 if (len < BGP_MP_REACH_MIN_SIZE) return ERR; mpreachlen = len; memcpy(&tmp16, ptr, 2); afi = ntohs(tmp16); ptr += 2; safi = *ptr; ptr++; mpnhoplen = *ptr; ptr++; mpreachlen -= 4; /* 2+1+1 above */ /* IPv4 (4), RD+IPv4 (12), IPv6 (16), RD+IPv6 (24), IPv6 link-local+IPv6 global (32) */ if (mpnhoplen == 4 || mpnhoplen == 12 || mpnhoplen == 16 || mpnhoplen == 24 || mpnhoplen == 32) { if (mpreachlen > mpnhoplen) { memset(&attr->mp_nexthop, 0, sizeof(struct host_addr)); switch (mpnhoplen) { case 4: attr->mp_nexthop.family = AF_INET; memcpy(&attr->mp_nexthop.address.ipv4, ptr, 4); break; case 12: // XXX: make any use of RD ? attr->mp_nexthop.family = AF_INET; memcpy(&attr->mp_nexthop.address.ipv4, ptr+8, 4); break; case 16: case 32: attr->mp_nexthop.family = AF_INET6; memcpy(&attr->mp_nexthop.address.ipv6, ptr, 16); break; case 24: // XXX: make any use of RD ? attr->mp_nexthop.family = AF_INET6; memcpy(&attr->mp_nexthop.address.ipv6, ptr+8, 16); break; default: memset(&attr->mp_nexthop, 0, sizeof(struct host_addr)); break; } mpreachlen -= mpnhoplen; ptr += mpnhoplen; /* Skipping SNPA info */ mpreachlen--; ptr++; } else return ERR; } else { char bgp_peer_str[INET6_ADDRSTRLEN]; bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] bgp_attr_parse_mp_reach(): Received malformed or unsupported afi=%u safi=%u\n", config.name, bms->log_str, bgp_peer_str, afi, safi); return ERR; } nlri_len = mpreachlen; /* length check once again */ if (!nlri_len || nlri_len > len) return ERR; /* XXX: perhaps sanity check (applies to: mp_reach, mp_unreach, update, withdraw) */ mp_update->afi = afi; mp_update->safi = safi; mp_update->nlri = (u_char *) ptr; mp_update->length = nlri_len; return SUCCESS; } int bgp_attr_parse_mp_unreach(struct bgp_peer *peer, u_int16_t len, struct bgp_attr *attr, char *ptr, struct bgp_nlri *mp_withdraw) { u_int16_t afi, mpunreachlen, tmp16; u_int16_t withdraw_len; u_char safi; /* length check */ #define BGP_MP_UNREACH_MIN_SIZE 3 if (len < BGP_MP_UNREACH_MIN_SIZE) return ERR; mpunreachlen = len; memcpy(&tmp16, ptr, 2); afi = ntohs(tmp16); ptr += 2; safi = *ptr; ptr++; mpunreachlen -= 3; /* 2+1 above */ withdraw_len = mpunreachlen; mp_withdraw->afi = afi; mp_withdraw->safi = safi; mp_withdraw->nlri = (u_char *) ptr; mp_withdraw->length = withdraw_len; return SUCCESS; } /* BGP UPDATE NLRI parsing */ int bgp_nlri_parse(struct bgp_msg_data *bmd, void *attr, struct bgp_attr_extra *attr_extra, struct bgp_nlri *info, int type) { struct bgp_misc_structs *bms; struct bgp_peer *peer = bmd->peer; char bgp_peer_str[INET6_ADDRSTRLEN]; u_char *pnt; u_char *lim; struct prefix p; int psize = 0, end; int ret, idx; u_int32_t tmp32; u_int16_t tmp16; struct rd_ip *rdi; struct rd_as *rda; struct rd_as4 *rda4; if (!peer) return ERR; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; memset(&p, 0, sizeof(struct prefix)); pnt = info->nlri; lim = pnt + info->length; end = info->length; for (idx = 0; pnt < lim; pnt += psize, idx++) { /* handle path identifier */ if (peer->cap_add_paths.cap[info->afi][info->safi]) { memcpy(&attr_extra->path_id, pnt, 4); attr_extra->path_id = ntohl(attr_extra->path_id); pnt += 4; } memset(&p, 0, sizeof(struct prefix)); /* Fetch prefix length and cross-check */ p.prefixlen = *pnt++; end--; p.family = bgp_afi2family (info->afi); if (info->safi == SAFI_UNICAST) { if ((info->afi == AFI_IP && p.prefixlen > 32) || (info->afi == AFI_IP6 && p.prefixlen > 128)) return ERR; psize = ((p.prefixlen+7)/8); if (psize > end) return ERR; /* Fetch prefix from NLRI packet. */ memcpy(&p.u.prefix, pnt, psize); } else if (info->safi == SAFI_MPLS_LABEL) { /* rfc3107 labeled unicast */ int labels_size = 0; u_char *label_ptr = NULL; if ((info->afi == AFI_IP && p.prefixlen > 56) || (info->afi == AFI_IP6 && p.prefixlen > 152)) return ERR; psize = ((p.prefixlen+7)/8); if (psize > end || psize < 3 /* one label */) return ERR; /* Fetch label(s) and prefix from NLRI packet */ label_ptr = pnt; if (type == BGP_NLRI_UPDATE) { while (((labels_size + 3) <= psize) && !check_bosbit(label_ptr)) { label_ptr += 3; labels_size += 3; } } if ((labels_size + 3) <= psize) { memcpy(attr_extra->label, label_ptr, 3); label_ptr += 3; labels_size += 3; } else return ERR; memcpy(&p.u.prefix, (pnt + labels_size), (psize - labels_size)); p.prefixlen -= (8 * labels_size); } else if (info->safi == SAFI_MPLS_VPN) { /* rfc4364 BGP/MPLS IP Virtual Private Networks */ int labels_size = 0; u_char *label_ptr = NULL; if ((info->afi == AFI_IP && p.prefixlen > 120) || (info->afi == AFI_IP6 && p.prefixlen > 216)) return ERR; psize = ((p.prefixlen+7)/8); if (psize > end || psize < 3 /* one label */) return ERR; /* Fetch label (3), RD (8) and prefix from NLRI packet */ label_ptr = pnt; if (type == BGP_NLRI_UPDATE) { while (((labels_size + 3) <= psize) && !check_bosbit(label_ptr)) { label_ptr += 3; labels_size += 3; } } if ((labels_size + 3) <= psize) { memcpy(attr_extra->label, label_ptr, 3); label_ptr += 3; labels_size += 3; } else return ERR; if (labels_size + 8 /* RD */ > psize) return ERR; memcpy(&attr_extra->rd.type, (pnt + labels_size), 2); attr_extra->rd.type = ntohs(attr_extra->rd.type); switch(attr_extra->rd.type) { case RD_TYPE_AS: rda = (struct rd_as *) &attr_extra->rd; memcpy(&tmp16, (pnt + labels_size + 2 /* RD type */), 2); memcpy(&tmp32, (pnt + labels_size + 2 /* RD type */ + 2 /* RD AS */), 4); rda->as = ntohs(tmp16); rda->val = ntohl(tmp32); break; case RD_TYPE_IP: rdi = (struct rd_ip *) &attr_extra->rd; memcpy(&rdi->ip.s_addr, (pnt + labels_size + 2 /* RD type */), 4); memcpy(&tmp16, (pnt + labels_size + 2 /* RD type */ + 4 /* RD IP */), 2); rdi->val = ntohs(tmp16); break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) &attr_extra->rd; memcpy(&tmp32, (pnt + labels_size + 2 /* RD type */), 4); memcpy(&tmp16, (pnt + labels_size + 2 /* RD type */ + 4 /* RD AS4 */), 2); rda4->as = ntohl(tmp32); rda4->val = ntohs(tmp16); break; default: return ERR; break; } bgp_rd_origin_set(&attr_extra->rd, RD_ORIGIN_BGP); memcpy(&p.u.prefix, (pnt + labels_size + 8 /* RD */), (psize - (labels_size + 8 /* RD */))); p.prefixlen -= (8 * (labels_size + 8 /* RD */)); } else { bgp_peer_print(peer, bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] bgp_nlri_parse() Received unsupported NLRI afi=%u safi=%u\n", config.name, bms->log_str, bgp_peer_str, info->afi, info->safi); continue; } // XXX: check prefix correctnesss now that we have it? #if defined WITH_ZMQ if (config.bgp_blackhole_stdcomm_list) { bmd->is_blackhole = bgp_blackhole_evaluate_comms(attr); /* let's process withdraws before withdrawing */ if (!attr && bmd->is_blackhole) { bgp_blackhole_instrument(peer, &p, attr, info->afi, info->safi); } } #endif /* Let's do our job now! */ if (attr) { ret = bgp_process_update(bmd, &p, attr, attr_extra, info->afi, info->safi, idx); } else { ret = bgp_process_withdraw(bmd, &p, attr, attr_extra, info->afi, info->safi, idx); (void)ret; //Treat error? } #if defined WITH_ZMQ if (config.bgp_blackhole_stdcomm_list) { /* let's process updates after installing */ if (attr && bmd->is_blackhole) { bgp_blackhole_instrument(peer, &p, attr, info->afi, info->safi); } } #endif } return SUCCESS; } /* AIGP attribute. */ int bgp_attr_parse_aigp(struct bgp_peer *peer, u_int16_t len, struct bgp_attr_extra *attr_extra, char *ptr, u_char flag) { u_int64_t tmp64; int ret = SUCCESS; /* Length check. */ if (len < 3) return ERR; /* XXX: skipping type check as only type 1 is defined */ switch (len) { case 3: attr_extra->aigp = 0; break; /* rfc7311: [If present] The value field of the AIGP TLV is always 8 octets long */ case 11: memcpy(&tmp64, (ptr + 3), 8); attr_extra->aigp = pm_ntohll(tmp64); attr_extra->bitmap |= BGP_BMAP_ATTR_AIGP; break; default: /* unsupported */ attr_extra->aigp = 0; ret = ERR; break; } ptr += len; return ret; } /* Prefix-SID attribute */ int bgp_attr_parse_prefix_sid(struct bgp_peer *peer, u_int16_t len, struct bgp_attr_extra *attr_extra, char *ptr, u_char flag) { u_int8_t tlv_type; u_int16_t tlv_len; u_int32_t tmp; /* Length check. */ if (len < 3) return ERR; tlv_type = (u_int8_t) (*ptr); memcpy(&tlv_len, (ptr + 1), 2); tlv_len = ntohs(tlv_len); if (tlv_type == BGP_PREFIX_SID_LI_TLV) { if (tlv_len == 7) { memcpy(&tmp, (ptr + 6), 4); attr_extra->psid_li = ntohl(tmp); } else { return ERR; } } /* XXX: Originator SRGB TLV not decoded yet */ ptr += len; return SUCCESS; } int bgp_process_update(struct bgp_msg_data *bmd, struct prefix *p, void *attr, struct bgp_attr_extra *attr_extra, afi_t afi, safi_t safi, int idx) { struct bgp_peer *peer = bmd->peer; struct bgp_rt_structs *inter_domain_routing_db; struct bgp_misc_structs *bms; struct bgp_node *route = NULL, route_local; struct bgp_info *ri = NULL, *new = NULL, ri_local; struct bgp_attr *attr_new = NULL; u_int32_t modulo; if (!peer) return ERR; inter_domain_routing_db = bgp_select_routing_db(peer->type); bms = bgp_select_misc_db(peer->type); if (!inter_domain_routing_db || !bms) return ERR; if (!bms->skip_rib) { modulo = bms->route_info_modulo(peer, &attr_extra->path_id, bms->table_per_peer_buckets); route = bgp_node_get(peer, inter_domain_routing_db->rib[afi][safi], p); /* Check previously received route. */ for (ri = route->info[modulo]; ri; ri = ri->next) { if (ri->peer == peer) { if (safi == SAFI_MPLS_VPN) { if (ri->attr_extra && !memcmp(&ri->attr_extra->rd, &attr_extra->rd, sizeof(rd_t))); else continue; } if (peer->cap_add_paths.cap[afi][safi]) { if (ri->attr_extra && (attr_extra->path_id == ri->attr_extra->path_id)); else continue; } if (ri->bmed.id) { if (bms->bgp_extra_data_cmp && !(*bms->bgp_extra_data_cmp)(&bmd->extra, &ri->bmed)); else continue; } break; } } attr_new = bgp_attr_intern(peer, attr); if (ri) { /* Received same information */ if (attrhash_cmp(ri->attr, attr_new)) { bgp_unlock_node(peer, route); bgp_attr_unintern(peer, attr_new); if (bms->msglog_backend_methods) goto log_update; return SUCCESS; } else { /* Update to new attribute. */ bgp_attr_unintern(peer, ri->attr); ri->attr = attr_new; bgp_attr_extra_process(peer, ri, afi, safi, attr_extra); if (bms->bgp_extra_data_process) (*bms->bgp_extra_data_process)(&bmd->extra, ri, idx, BGP_NLRI_UPDATE); bgp_unlock_node (peer, route); if (bms->msglog_backend_methods) goto log_update; return SUCCESS; } } /* Make new BGP info. */ new = bgp_info_new(peer); if (new) { new->peer = peer; new->attr = attr_new; bgp_attr_extra_process(peer, new, afi, safi, attr_extra); if (bms->bgp_extra_data_process) (*bms->bgp_extra_data_process)(&bmd->extra, new, idx, BGP_NLRI_UPDATE); } else return ERR; /* Register new BGP information. */ bgp_info_add(peer, route, new, modulo); /* route_node_get lock */ bgp_unlock_node(peer, route); if (bms->msglog_backend_methods) { ri = new; goto log_update; } } else { if (bms->msglog_backend_methods) { route = &route_local; memset(&route_local, 0, sizeof(struct bgp_node)); memcpy(&route_local.p, p, sizeof(struct prefix)); ri = &ri_local; memset(&ri_local, 0, sizeof(struct bgp_info)); ri->peer = peer; ri->attr = bgp_attr_intern(peer, attr); bgp_attr_extra_process(peer, ri, afi, safi, attr_extra); if (bms->bgp_extra_data_process) (*bms->bgp_extra_data_process)(&bmd->extra, ri, idx, BGP_NLRI_UPDATE); goto log_update; } } return SUCCESS; log_update: { char event_type[] = "log"; bgp_peer_log_msg(route, ri, afi, safi, bms->tag, event_type, bms->msglog_output, NULL, BGP_LOG_TYPE_UPDATE); } if (bms->skip_rib) { if (ri->attr_extra) bgp_attr_extra_free(peer, &ri->attr_extra); if (bms->bgp_extra_data_free) (*bms->bgp_extra_data_free)(&ri->bmed); bgp_attr_unintern(peer, ri->attr); } return SUCCESS; } int bgp_process_withdraw(struct bgp_msg_data *bmd, struct prefix *p, void *attr, struct bgp_attr_extra *attr_extra, afi_t afi, safi_t safi, int idx) { struct bgp_peer *peer = bmd->peer; struct bgp_rt_structs *inter_domain_routing_db; struct bgp_misc_structs *bms; struct bgp_node *route = NULL, route_local; struct bgp_info *ri = NULL, ri_local; u_int32_t modulo = 0; if (!peer) return ERR; inter_domain_routing_db = bgp_select_routing_db(peer->type); bms = bgp_select_misc_db(peer->type); if (!inter_domain_routing_db || !bms) return ERR; if (!bms->skip_rib) { modulo = bms->route_info_modulo(peer, &attr_extra->path_id, bms->table_per_peer_buckets); /* Lookup node. */ route = bgp_node_get(peer, inter_domain_routing_db->rib[afi][safi], p); /* Check previously received route. */ for (ri = route->info[modulo]; ri; ri = ri->next) { if (ri->peer == peer) { if (safi == SAFI_MPLS_VPN) { if (ri->attr_extra && !memcmp(&ri->attr_extra->rd, &attr_extra->rd, sizeof(rd_t))); else continue; } if (peer->cap_add_paths.cap[afi][safi]) { if (ri->attr_extra && (attr_extra->path_id == ri->attr_extra->path_id)); else continue; } if (ri->bmed.id) { if (bms->bgp_extra_data_cmp && !(*bms->bgp_extra_data_cmp)(&bmd->extra, &ri->bmed)); else continue; } break; } } } else { if (bms->msglog_backend_methods) { route = &route_local; memset(&route_local, 0, sizeof(struct bgp_node)); memcpy(&route_local.p, p, sizeof(struct prefix)); ri = &ri_local; memset(&ri_local, 0, sizeof(struct bgp_info)); ri->peer = peer; bgp_attr_extra_process(peer, ri, afi, safi, attr_extra); if (bms->bgp_extra_data_process) (*bms->bgp_extra_data_process)(&bmd->extra, ri, idx, BGP_NLRI_WITHDRAW); } } if (ri && bms->msglog_backend_methods) { char event_type[] = "log"; bgp_peer_log_msg(route, ri, afi, safi, bms->tag, event_type, bms->msglog_output, NULL, BGP_LOG_TYPE_WITHDRAW); } if (!bms->skip_rib) { /* Withdraw specified route from routing table. */ if (ri) bgp_info_delete(peer, route, ri, modulo); /* Unlock bgp_node_get() lock. */ bgp_unlock_node(peer, route); } else { if (bms->msglog_backend_methods) { if (ri->attr_extra) bgp_attr_extra_free(peer, &ri->attr_extra); if (bms->bgp_extra_data_free) (*bms->bgp_extra_data_free)(&ri->bmed); } } return SUCCESS; } pmacct-1.7.8/src/bgp/bgp_logdump.h0000644000175000017500000000677314354105275016036 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_LOGDUMP_H_ #define _BGP_LOGDUMP_H_ /* defines */ #define BGP_LOGDUMP_ET_NONE 0 #define BGP_LOGDUMP_ET_LOG 1 #define BGP_LOGDUMP_ET_DUMP 2 #define BGP_LOGDUMP_ET_LG 3 #define BGP_LOG_TYPE_MISC 0 #define BGP_LOG_TYPE_UPDATE 1 #define BGP_LOG_TYPE_WITHDRAW 2 #define BGP_LOG_TYPE_DELETE 3 #define BGP_LOG_TYPE_EOR 4 #define BGP_LOG_TYPE_LOGINIT 65500 #define BGP_LOG_TYPE_LOGCLOSE 65501 #define BGP_LOG_TYPE_DUMPINIT 65502 #define BGP_LOG_TYPE_DUMPCLOSE 65503 #define BGP_LOG_TYPE_MAX 65503 #define BGP_LOGSEQ_ROLLOVER_BIT 0x8000000000000000ULL #define BGP_LOGSEQ_MASK 0x7FFFFFFFFFFFFFFFULL struct bgp_peer_log { FILE *fd; int refcnt; char filename[SRVBUFLEN]; char partition_key[SRVBUFLEN]; void *amqp_host; void *kafka_host; }; struct bgp_dump_stats { u_int64_t entries; u_int32_t tables; }; /* prototypes */ extern int bgp_peer_log_init(struct bgp_peer *, bgp_tag_t *, int, int); extern int bgp_peer_log_close(struct bgp_peer *, bgp_tag_t *, int, int); extern int bgp_peer_log_dynname(char *, int, char *, struct bgp_peer *); extern int bgp_peer_log_msg(struct bgp_node *, struct bgp_info *, afi_t, safi_t, bgp_tag_t *, char *, int, char **, int); extern void bgp_peer_log_seq_init(u_int64_t *); extern void bgp_peer_log_seq_increment(u_int64_t *); extern u_int64_t bgp_peer_log_seq_get(u_int64_t *); extern void bgp_peer_log_seq_set(u_int64_t *, u_int64_t); extern int bgp_peer_log_seq_has_ro_bit(u_int64_t *); extern int bgp_peer_dump_init(struct bgp_peer *, bgp_tag_t *, int, int); extern int bgp_peer_dump_close(struct bgp_peer *, bgp_tag_t *, struct bgp_dump_stats *, int, int); extern void bgp_handle_dump_event(int); extern int bgp_table_dump_event_runner(struct pm_dump_runner *); extern void bgp_daemon_msglog_init_amqp_host(); extern void bgp_table_dump_init_amqp_host(void *); extern int bgp_daemon_msglog_init_kafka_host(); extern int bgp_table_dump_init_kafka_host(void *); #if defined WITH_JANSSON extern void bgp_tag_print_json(json_t *, bgp_tag_t *); #endif #if defined WITH_AVRO extern avro_schema_t p_avro_schema_build_bgp(int, char *); extern avro_schema_t p_avro_schema_build_bgp_log_initclose(int, char *); extern avro_schema_t p_avro_schema_build_bgp_dump_init(int, char *); extern avro_schema_t p_avro_schema_build_bgp_dump_close(int, char *); extern void p_avro_schema_init_bgp(avro_schema_t *, avro_schema_t *, avro_schema_t *, avro_schema_t *, int, char *); extern void p_avro_schema_build_bgp_common(avro_schema_t *, avro_schema_t *, avro_schema_t *, avro_schema_t *, int, int); extern void p_avro_schema_build_bgp_route(avro_schema_t *, avro_schema_t *, avro_schema_t *, avro_schema_t *); extern void bgp_tag_print_avro(avro_value_t, bgp_tag_t *); #endif #endif pmacct-1.7.8/src/bgp/bgp_packet.h0000644000175000017500000001621114354105275015622 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* * Definitions for BGP packet disassembly structures and routine * * Baselined from: * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_PACKET_H_ #define _BGP_PACKET_H_ /* some handy things to know */ #define BGP_BUFFER_SIZE 100000 #define BGP_MARKER_SIZE 16 /* size of BGP marker */ #define BGP_HEADER_SIZE 19 /* size of BGP header, including marker */ #define BGP_MIN_OPEN_MSG_SIZE 29 #define BGP_MIN_UPDATE_MSG_SIZE 23 #define BGP_MIN_NOTIFICATION_MSG_SIZE 21 #define BGP_MIN_KEEPALVE_MSG_SIZE BGP_HEADER_SIZE #define BGP_TCP_PORT 179 #define BGP_VERSION4 4 #define BGP_MAX_MSGLEN 4096 #define CAPABILITY_CODE_AS4_LEN 4 /* BGP message types */ #define BGP_OPEN 1 #define BGP_UPDATE 2 #define BGP_NOTIFICATION 3 #define BGP_KEEPALIVE 4 #define BGP_ROUTE_REFRESH 5 #define BGP_CAPABILITY 6 #define BGP_ROUTE_REFRESH_CISCO 0x80 static const char __attribute__((unused)) *bgp_msg_types[] = { "Unknown", "Open", "Update", "Notification", "Keepalive", "Route Refresh" }; #define BGP_MSG_TYPE_MAX 5 /* Address family numbers */ #define AFI_IP 1 #define AFI_IP6 2 #define AFI_BGP_LS 16388 #define AFI_MAX 3 /* XXX: hotfix */ /* Subsequent Address Family Identifier. */ #define SAFI_UNICAST 1 #define SAFI_MULTICAST 2 #define SAFI_UNICAST_MULTICAST 3 #define SAFI_MPLS_LABEL 4 #define SAFI_LS_GLOBAL 71 #define SAFI_LS_VPN 72 #define SAFI_MPLS_VPN 128 #define SAFI_MAX 129 struct bgp_header { u_int8_t bgpo_marker[BGP_MARKER_SIZE]; u_int16_t bgpo_len; u_int8_t bgpo_type; }; /* BGP OPEN message */ struct bgp_open { u_int8_t bgpo_marker[BGP_MARKER_SIZE]; u_int16_t bgpo_len; u_int8_t bgpo_type; u_int8_t bgpo_version; u_int16_t bgpo_myas; u_int16_t bgpo_holdtime; u_int32_t bgpo_id; u_int8_t bgpo_optlen; /* options should follow */ }; /* BGP NOTIFICATION message */ /* BGP notify message codes. */ #define BGP_NOTIFY_HEADER_ERR 1 #define BGP_NOTIFY_OPEN_ERR 2 #define BGP_NOTIFY_UPDATE_ERR 3 #define BGP_NOTIFY_HOLD_ERR 4 #define BGP_NOTIFY_FSM_ERR 5 #define BGP_NOTIFY_CEASE 6 #define BGP_NOTIFY_CAPABILITY_ERR 7 #define BGP_NOTIFY_MAX 8 #define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0 /* BGP_NOTIFY_CEASE sub codes (RFC 4486). */ #define BGP_NOTIFY_CEASE_MAX_PREFIX 1 #define BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN 2 #define BGP_NOTIFY_CEASE_PEER_UNCONFIG 3 #define BGP_NOTIFY_CEASE_ADMIN_RESET 4 #define BGP_NOTIFY_CEASE_CONNECT_REJECT 5 #define BGP_NOTIFY_CEASE_CONFIG_CHANGE 6 #define BGP_NOTIFY_CEASE_COLLISION_RESOLUTION 7 #define BGP_NOTIFY_CEASE_OUT_OF_RESOURCE 8 #define BGP_NOTIFY_CEASE_MAX 9 struct bgp_notification { u_int8_t bgpn_marker[BGP_MARKER_SIZE]; u_int16_t bgpn_len; u_int8_t bgpn_type; u_int8_t bgpn_major; u_int8_t bgpn_minor; /* data should follow */ }; /* based on: rfc8203 */ /* #define BGP_NOTIFY_CEASE_SM_LEN 128 */ /* based on: draft-ietf-idr-rfc8203bis */ #define BGP_NOTIFY_CEASE_SM_LEN 255 struct bgp_notification_shutdown_msg { u_int8_t bgpnsm_len; char bgpnsm_data[BGP_NOTIFY_CEASE_SM_LEN]; }; /* BGP ROUTE-REFRESH message */ struct bgp_route_refresh { u_int8_t bgpr_marker[BGP_MARKER_SIZE]; u_int16_t bgpr_len; u_int8_t bgpr_type; u_int16_t bgpr_afi; u_int8_t bgpr_reserved; u_int8_t bgpr_safi; }; struct capability_mp_data { u_int16_t afi; u_char reserved; u_char safi; }; struct capability_as4 { uint32_t as4; }; struct capability_add_paths { u_int16_t afi; u_char safi; u_char sndrcv; }; /* attribute flags, from RFC1771 */ #define BGP_ATTR_FLAG_OPTIONAL 0x80 #define BGP_ATTR_FLAG_TRANSITIVE 0x40 #define BGP_ATTR_FLAG_PARTIAL 0x20 #define BGP_ATTR_FLAG_EXTENDED_LENGTH 0x10 /* AS_PATH segment types */ #define AS_SET 1 /* RFC1771 */ #define AS_SEQUENCE 2 /* RFC1771 */ #define AS_CONFED_SET 4 /* RFC1965 has the wrong values, corrected in */ #define AS_CONFED_SEQUENCE 3 /* RFC3065 */ /* OPEN message Optional Parameter types */ #define BGP_OPTION_AUTHENTICATION 1 /* RFC1771 */ #define BGP_OPTION_CAPABILITY 2 /* RFC2842 */ /* BGP capability code */ #define BGP_CAPABILITY_RESERVED 0 /* RFC2434 */ #define BGP_CAPABILITY_MULTIPROTOCOL 1 /* RFC2858 */ #define BGP_CAPABILITY_ROUTE_REFRESH 2 /* RFC2918 */ #define BGP_CAPABILITY_4_OCTET_AS_NUMBER 0x41 /* RFC4893 */ #define BGP_CAPABILITY_ADD_PATHS 0x45 /* RFC7911 */ /* well-known communities, from RFC1997 */ #define BGP_COMM_NO_EXPORT 0xFFFFFF01 #define BGP_COMM_NO_ADVERTISE 0xFFFFFF02 #define BGP_COMM_NO_EXPORT_SUBCONFED 0xFFFFFF03 #define FOURHEX0 0x00000000 #define FOURHEXF 0xFFFF0000 /* Extended community type */ #define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */ #define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */ #define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_LINKBAND 0x0004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */ /* -2 version of the draft */ #define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domin ID / VPN of Origin */ /* draft-rosen-vpns-ospf-bgp-mpls */ #define BGP_EXT_COM_OSPF_RTYPE 0X8000 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */ #define BGP_EXT_COM_OSPF_RID 0x8001 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */ #define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */ /* Extended community & Route dinstinguisher formats */ #define FORMAT_AS2_LOC 0x00 /* Format AS(2bytes):AN(4bytes) */ #define FORMAT_IP_LOC 0x01 /* Format IP address:AN(2bytes) */ #define FORMAT_AS4_LOC 0x02 /* Format AS(4bytes):AN(2bytes) */ #ifndef offsetof #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif #endif pmacct-1.7.8/src/bgp/bgp_logdump.c0000644000175000017500000025630414354105275016026 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp.h" #include "rpki/rpki.h" #include "thread_pool.h" #include "plugin_common.h" #include "plugin_cmn_json.h" #include "util.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #ifdef WITH_AVRO #include "plugin_cmn_avro.h" #endif /* functions */ int bgp_peer_log_msg(struct bgp_node *route, struct bgp_info *ri, afi_t afi, safi_t safi, bgp_tag_t *tag, char *event_type, int output, char **output_data, int log_type) { struct bgp_misc_structs *bms; struct bgp_peer *peer; int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = BGP_LOGDUMP_ET_NONE; if (!ri || !ri->peer || !event_type) return ERR; /* missing required parameters */ if (!ri->peer->log && !output_data) return ERR; /* missing any output method */ peer = ri->peer; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP; else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG; else if (!strcmp(event_type, "lglass")) etype = BGP_LOGDUMP_ET_LG; if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_RABBITMQ p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif } if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_KAFKA p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); if (bms->msglog_kafka_partition_key && etype == BGP_LOGDUMP_ET_LOG) { p_kafka_set_key(peer->log->kafka_host, peer->log->partition_key, strlen(peer->log->partition_key)); } #endif } if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON struct bgp_attr *attr = ri->attr; struct bgp_attr_extra *attr_extra = ri->attr_extra; char ip_address[INET6_ADDRSTRLEN], log_type_str[SUPERSHORTBUFLEN]; json_t *obj = json_object(); char empty[] = ""; char prefix_str[PREFIX_STRLEN], nexthop_str[INET6_ADDRSTRLEN]; char *aspath; if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); switch (log_type) { case BGP_LOG_TYPE_UPDATE: json_object_set_new_nocheck(obj, "log_type", json_string("update")); break; case BGP_LOG_TYPE_WITHDRAW: json_object_set_new_nocheck(obj, "log_type", json_string("withdraw")); break; case BGP_LOG_TYPE_DELETE: json_object_set_new_nocheck(obj, "log_type", json_string("delete")); break; case BGP_LOG_TYPE_EOR: json_object_set_new_nocheck(obj, "log_type", json_string("end-of-rib")); break; default: snprintf(log_type_str, SUPERSHORTBUFLEN, "%d", log_type); json_object_set_new_nocheck(obj, "log_type", json_string(log_type_str)); break; } } else if (etype == BGP_LOGDUMP_ET_DUMP) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); } if (etype == BGP_LOGDUMP_ET_LOG) json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); else if (etype == BGP_LOGDUMP_ET_DUMP) json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str)); if (ri && ri->bmed.id && bms->bgp_peer_logdump_extra_data) bms->bgp_peer_logdump_extra_data(&ri->bmed, output, obj); if (!bms->bgp_peer_log_msg_extras) { addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); if (bms->peer_port_str) json_object_set_new_nocheck(obj, bms->peer_port_str, json_integer((json_int_t)peer->tcp_port)); } if (config.tmp_bgp_lookup_compare_ports) { addr_to_str(ip_address, &peer->id); json_object_set_new_nocheck(obj, "peer_id", json_string(ip_address)); } if (bms->tag_map && tag) { bgp_tag_print_json(obj, tag); } json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); json_object_set_new_nocheck(obj, "afi", json_integer((json_int_t)afi)); json_object_set_new_nocheck(obj, "safi", json_integer((json_int_t)safi)); if (route) { memset(prefix_str, 0, PREFIX_STRLEN); prefix2str(&route->p, prefix_str, PREFIX_STRLEN); json_object_set_new_nocheck(obj, "ip_prefix", json_string(prefix_str)); } if (peer->cap_add_paths.cap[afi][safi] && ri && ri->attr_extra) { json_object_set_new_nocheck(obj, "as_path_id", json_integer((json_int_t)ri->attr_extra->path_id)); } if (attr) { memset(nexthop_str, 0, INET6_ADDRSTRLEN); if (attr->mp_nexthop.family) addr_to_str2(nexthop_str, &attr->mp_nexthop, bgp_afi2family(afi)); else inet_ntop(AF_INET, &attr->nexthop, nexthop_str, INET6_ADDRSTRLEN); json_object_set_new_nocheck(obj, "bgp_nexthop", json_string(nexthop_str)); aspath = attr->aspath ? attr->aspath->str : empty; json_object_set_new_nocheck(obj, "as_path", json_string(aspath)); if (attr->community) json_object_set_new_nocheck(obj, "comms", json_string(attr->community->str)); if (attr->ecommunity) json_object_set_new_nocheck(obj, "ecomms", json_string(attr->ecommunity->str)); if (attr->lcommunity) json_object_set_new_nocheck(obj, "lcomms", json_string(attr->lcommunity->str)); if (!config.tmp_bgp_daemon_origin_type_int) { json_object_set_new_nocheck(obj, "origin", json_string(bgp_origin_print(attr->origin))); } else { json_object_set_new_nocheck(obj, "origin", json_integer((json_int_t)attr->origin)); } if (attr->bitmap & BGP_BMAP_ATTR_LOCAL_PREF) json_object_set_new_nocheck(obj, "local_pref", json_integer((json_int_t)attr->local_pref)); if (attr->bitmap & BGP_BMAP_ATTR_MULTI_EXIT_DISC) json_object_set_new_nocheck(obj, "med", json_integer((json_int_t)attr->med)); if (attr_extra && (attr_extra->bitmap & BGP_BMAP_ATTR_AIGP)) json_object_set_new_nocheck(obj, "aigp", json_integer((json_int_t)attr_extra->aigp)); if (attr_extra && attr_extra->psid_li) json_object_set_new_nocheck(obj, "psid_li", json_integer((json_int_t)attr_extra->psid_li)); if ((config.rpki_roas_file || config.rpki_rtr_cache) && route) { u_int8_t roa; if (etype == BGP_LOGDUMP_ET_LOG) { bms->bnv->entries = 1; bms->bnv->v[0].p = &route->p; bms->bnv->v[0].info = ri; } else if (etype == BGP_LOGDUMP_ET_DUMP) { bgp_lookup_node_vector_unicast(&route->p, peer, bms->bnv); } roa = rpki_vector_prefix_lookup(bms->bnv); json_object_set_new_nocheck(obj, "roa", json_string(rpki_roa_print(roa))); } } if ((safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) && ri && ri->attr_extra) { char label_str[SHORTSHORTBUFLEN]; if (safi == SAFI_MPLS_VPN) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &ri->attr_extra->rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(ri->attr_extra->rd.type))); } bgp_label2str(label_str, ri->attr_extra->label); json_object_set_new_nocheck(obj, "mpls_label", json_string(label_str)); } if (bms->bgp_peer_log_msg_extras) bms->bgp_peer_log_msg_extras(peer, etype, log_type, output, obj); if ((bms->msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_file && etype == BGP_LOGDUMP_ET_DUMP)) { write_and_free_json(peer->log->fd, obj); } if (output_data && etype == BGP_LOGDUMP_ET_LG) { (*output_data) = compose_json_str(obj); } if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); #ifdef WITH_RABBITMQ amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); #endif } if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); #ifdef WITH_KAFKA kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); #endif } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; struct bgp_attr *attr = ri->attr; struct bgp_attr_extra *attr_extra = ri->attr_extra; char ip_address[INET6_ADDRSTRLEN], log_type_str[SUPERSHORTBUFLEN]; char prefix_str[PREFIX_STRLEN], nexthop_str[INET6_ADDRSTRLEN]; char empty_string[] = "", *aspath = NULL; void *p_avro_local_buf = NULL; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); if (etype == BGP_LOGDUMP_ET_LOG) { p_avro_iface = avro_generic_class_from_schema(bms->msglog_avro_schema[0]); } else if (etype == BGP_LOGDUMP_ET_DUMP) { p_avro_iface = avro_generic_class_from_schema(bms->dump_avro_schema[0]); } pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); if (etype == BGP_LOGDUMP_ET_LOG) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "log_type", &p_avro_field, NULL)); switch (log_type) { case BGP_LOG_TYPE_UPDATE: pm_avro_check(avro_value_set_string(&p_avro_field, "update")); break; case BGP_LOG_TYPE_WITHDRAW: pm_avro_check(avro_value_set_string(&p_avro_field, "withdraw")); break; case BGP_LOG_TYPE_DELETE: pm_avro_check(avro_value_set_string(&p_avro_field, "delete")); break; case BGP_LOG_TYPE_EOR: pm_avro_check(avro_value_set_string(&p_avro_field, "end-of-rib")); break; default: sprintf(log_type_str, "%u", log_type); pm_avro_check(avro_value_set_string(&p_avro_field, log_type_str)); break; } } else if (etype == BGP_LOGDUMP_ET_DUMP) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); } if (etype == BGP_LOGDUMP_ET_LOG) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->log_tstamp_str)); } else if (etype == BGP_LOGDUMP_ET_DUMP) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->dump.tstamp_str)); } if (ri && ri->bmed.id && bms->bgp_peer_logdump_extra_data) bms->bgp_peer_logdump_extra_data(&ri->bmed, output, &p_avro_obj); if (!bms->bgp_peer_log_msg_extras) { addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } if (bms->tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } if (config.tmp_bgp_lookup_compare_ports) { addr_to_str(ip_address, &peer->id); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "peer_id", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "afi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, afi)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "safi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, safi)); if (route) { memset(prefix_str, 0, PREFIX_STRLEN); prefix2str(&route->p, prefix_str, PREFIX_STRLEN); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "ip_prefix", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, prefix_str)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "ip_prefix", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr) { memset(nexthop_str, 0, INET6_ADDRSTRLEN); if (attr->mp_nexthop.family) addr_to_str2(nexthop_str, &attr->mp_nexthop, bgp_afi2family(afi)); else inet_ntop(AF_INET, &attr->nexthop, nexthop_str, INET6_ADDRSTRLEN); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "bgp_nexthop", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, nexthop_str)); aspath = attr->aspath ? attr->aspath->str : empty_string; pm_avro_check(avro_value_get_by_name(&p_avro_obj, "as_path", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, aspath)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); if (!config.tmp_bgp_daemon_origin_type_int) { pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_origin_print(attr->origin))); } else { pm_avro_check(avro_value_set_long(&p_avro_branch, attr->origin)); } if (attr->bitmap & BGP_BMAP_ATTR_LOCAL_PREF) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "local_pref", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, attr->local_pref)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "local_pref", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr->community) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "comms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, attr->community->str)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "comms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr->ecommunity) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "ecomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, attr->ecommunity->str)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "ecomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr->lcommunity) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "lcomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, attr->lcommunity->str)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "lcomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr->bitmap & BGP_BMAP_ATTR_MULTI_EXIT_DISC) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "med", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, attr->med)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "med", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr_extra && (attr_extra->bitmap & BGP_BMAP_ATTR_AIGP)) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "aigp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, attr_extra->aigp)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "aigp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (attr_extra && attr_extra->psid_li) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "psid_li", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, attr_extra->psid_li)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "psid_li", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "bgp_nexthop", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "as_path", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "local_pref", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "comms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "ecomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "lcomms", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "med", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "aigp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "psid_li", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (peer->cap_add_paths.cap[afi][safi] && ri && ri->attr_extra) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "as_path_id", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, ri->attr_extra->path_id)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "as_path_id", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if ((safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) && ri && ri->attr_extra) { char label_str[SHORTSHORTBUFLEN]; if (safi == SAFI_MPLS_VPN) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &ri->attr_extra->rd); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, rd_str)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_rd_origin_print(ri->attr_extra->rd.type))); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } bgp_label2str(label_str, ri->attr_extra->label); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "mpls_label", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, label_str)); } else { int disc = FALSE; pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd", &p_avro_field, NULL)); avro_value_get_discriminant(&p_avro_field, &disc); if (disc != TRUE) { pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "mpls_label", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (bms->bgp_peer_log_msg_extras) bms->bgp_peer_log_msg_extras(peer, etype, log_type, output, &p_avro_obj); if ((config.rpki_roas_file || config.rpki_rtr_cache) && route) { u_int8_t roa; if (etype == BGP_LOGDUMP_ET_LOG) { bms->bnv->entries = 1; bms->bnv->v[0].p = &route->p; bms->bnv->v[0].info = ri; } else if (etype == BGP_LOGDUMP_ET_DUMP) { bgp_lookup_node_vector_unicast(&route->p, peer, bms->bnv); } roa = rpki_vector_prefix_lookup(bms->bnv); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "roa", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, rpki_roa_print(roa))); } add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (((bms->msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_file && etype == BGP_LOGDUMP_ET_DUMP) || (bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP) || (bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG && !bms->msglog_kafka_avro_schema_registry) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP && !bms->dump_kafka_avro_schema_registry)) && (output == PRINT_OUTPUT_AVRO_BIN)) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_msg(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if ((bms->msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_file && etype == BGP_LOGDUMP_ET_DUMP)) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_RABBITMQ if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); #endif } if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_KAFKA if ((bms->msglog_kafka_avro_schema_registry && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_avro_schema_registry && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[0]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[0], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_msg(): serdes_schema_serialize_avro() failed: %s\n", config.name, bms->log_str, kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); #endif } avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } return (ret | amqp_ret | kafka_ret); } int bgp_peer_log_init(struct bgp_peer *peer, bgp_tag_t *tag, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); int peer_idx, have_it, ret = 0, amqp_ret = 0, kafka_ret = 0; char log_filename[SRVBUFLEN], log_partname[SRVBUFLEN]; if (!bms || !peer) return ERR; if (bms->msglog_file) { bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_file, peer); } if (bms->msglog_amqp_routing_key) { bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_amqp_routing_key, peer); } if (bms->msglog_kafka_topic) { bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_kafka_topic, peer); } if (bms->msglog_kafka_partition_key) { bgp_peer_log_dynname(log_partname, SRVBUFLEN, bms->msglog_kafka_partition_key, peer); } for (peer_idx = 0, have_it = 0; peer_idx < bms->max_peers; peer_idx++) { if (!bms->peers_log[peer_idx].refcnt) { if (bms->msglog_file) { bms->peers_log[peer_idx].fd = open_output_file(log_filename, "a", FALSE); setlinebuf(bms->peers_log[peer_idx].fd); } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { bms->peers_log[peer_idx].amqp_host = bms->msglog_amqp_host; } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { bms->peers_log[peer_idx].kafka_host = bms->msglog_kafka_host; } if (bms->msglog_kafka_partition_key) { strcpy(bms->peers_log[peer_idx].partition_key, log_partname); } #endif strcpy(bms->peers_log[peer_idx].filename, log_filename); have_it = TRUE; break; } else if (!strcmp(log_filename, bms->peers_log[peer_idx].filename)) { if (bms->msglog_kafka_partition_key) { if (!strcmp(log_partname, bms->peers_log[peer_idx].partition_key)) { have_it = TRUE; } } else { have_it = TRUE; } if (have_it) break; } } if (have_it) { peer->log = &bms->peers_log[peer_idx]; bms->peers_log[peer_idx].refcnt++; #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); if (bms->msglog_amqp_routing_key_rr && !p_amqp_get_routing_key_rr(peer->log->amqp_host)) { p_amqp_init_routing_key_rr(peer->log->amqp_host); p_amqp_set_routing_key_rr(peer->log->amqp_host, bms->msglog_amqp_routing_key_rr); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); } if (bms->msglog_kafka_topic_rr && !p_kafka_get_topic_rr(peer->log->kafka_host)) { p_kafka_init_topic_rr(peer->log->kafka_host); p_kafka_set_topic_rr(peer->log->kafka_host, bms->msglog_kafka_topic_rr); } if (bms->msglog_kafka_partition_key) { p_kafka_set_key(peer->log->kafka_host, peer->log->partition_key, strlen(peer->log->partition_key)); } #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char event_type[] = "log_init"; char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); if (bms->tag_map && tag) { bgp_tag_print_json(obj, tag); } if (bms->peer_port_str) json_object_set_new_nocheck(obj, bms->peer_port_str, json_integer((json_int_t)peer->tcp_port)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, obj); } if (bms->msglog_file) { write_and_free_json(peer->log->fd, obj); } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO char event_type[] = "log_init"; char ip_address[INET6_ADDRSTRLEN]; avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; void *p_avro_local_buf = NULL; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); p_avro_iface = avro_generic_class_from_schema(bms->msglog_avro_schema[BGP_LOG_TYPE_LOGINIT]); pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (bms->tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, &p_avro_obj); } if (!bms->msglog_kafka_avro_schema_registry && output == PRINT_OUTPUT_AVRO_BIN) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_init(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if (bms->msglog_file) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { if (bms->msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[BGP_LOG_TYPE_LOGINIT]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[BGP_LOG_TYPE_LOGINIT], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_init(): serdes_schema_serialize_avro() failed: %s\n", config.name, bms->log_str, kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); } #endif avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } } return (ret | amqp_ret | kafka_ret); } int bgp_peer_log_close(struct bgp_peer *peer, bgp_tag_t *tag, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); struct bgp_peer_log *log_ptr; int ret = 0, amqp_ret = 0, kafka_ret = 0; #if defined WITH_RABBITMQ void *amqp_log_ptr = NULL; #endif #if defined WITH_KAFKA void *kafka_log_ptr = NULL; #endif if (!bms || !peer || !peer->log) return ERR; #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); } if (bms->msglog_kafka_partition_key) { p_kafka_set_key(peer->log->kafka_host, peer->log->partition_key, strlen(peer->log->partition_key)); } #endif log_ptr = peer->log; #ifdef WITH_RABBITMQ amqp_log_ptr = peer->log->amqp_host; #endif #ifdef WITH_KAFKA kafka_log_ptr = peer->log->kafka_host; #endif assert(peer->log->refcnt); peer->log->refcnt--; peer->log = NULL; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); char event_type[] = "log_close"; json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); if (bms->tag_map && tag) { bgp_tag_print_json(obj, tag); } if (bms->peer_port_str) json_object_set_new_nocheck(obj, bms->peer_port_str, json_integer((json_int_t)peer->tcp_port)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, obj); } if (bms->msglog_file) { write_and_free_json(log_ptr->fd, obj); } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); amqp_ret = write_and_free_json_amqp(amqp_log_ptr, obj); p_amqp_unset_routing_key(amqp_log_ptr); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); kafka_ret = write_and_free_json_kafka(kafka_log_ptr, obj); p_kafka_unset_topic(kafka_log_ptr); } #endif #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO char event_type[] = "log_close"; char ip_address[INET6_ADDRSTRLEN]; avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; void *p_avro_local_buf = NULL; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); p_avro_iface = avro_generic_class_from_schema(bms->msglog_avro_schema[BGP_LOG_TYPE_LOGCLOSE]); pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (bms->tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, &p_avro_obj); } if (!bms->msglog_kafka_avro_schema_registry && output == PRINT_OUTPUT_AVRO_BIN) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_close(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if (bms->msglog_file) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { if (peer->log) { if (bms->msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[BGP_LOG_TYPE_LOGCLOSE]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[BGP_LOG_TYPE_LOGCLOSE], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_log_close(): serdes_schema_serialize_avro() failed: %s\n", config.name, bms->log_str, kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); } else { char peer_str[INET6_ADDRSTRLEN]; addr_to_str(peer_str, &peer->addr); Log(LOG_WARNING, "WARNING ( %s/%s ): Unable to get kafka_host: %s\n", config.name, bms->log_str, peer_str); } } #endif avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } if (!log_ptr->refcnt) { if (bms->msglog_file && !log_ptr->refcnt) { fclose(log_ptr->fd); memset(log_ptr, 0, sizeof(struct bgp_peer_log)); } } return (ret | amqp_ret | kafka_ret); } void bgp_peer_log_seq_init(u_int64_t *seq) { if (seq) (*seq) = 0; } void bgp_peer_log_seq_increment(u_int64_t *seq) { /* Jansson does not support unsigned 64 bit integers, let's wrap at 2^63-1 */ if (seq) { if ((*seq) == INT64T_THRESHOLD) (*seq) = 0; else (*seq)++; } } u_int64_t bgp_peer_log_seq_get(u_int64_t *seq) { u_int64_t ret = 0; if (seq) ret = (*seq); return ret; } void bgp_peer_log_seq_set(u_int64_t *seq, u_int64_t value) { if (seq) (*seq) = value; } int bgp_peer_log_seq_has_ro_bit(u_int64_t *seq) { if ((*seq) & BGP_LOGSEQ_ROLLOVER_BIT) return TRUE; else return FALSE; } /* XXX: 1) inefficient string testing and 2) string aliases can be mixed and matched. But as long as this is used for determining filenames for large outputs this is fine. To be refined in future */ int bgp_peer_log_dynname(char *new, int newlen, char *old, struct bgp_peer *peer) { int oldlen, is_dyn = FALSE; char psi_string[] = "$peer_src_ip", ptp_string[] = "$peer_tcp_port"; char br_string[] = "$bmp_router", brp_string[] = "$bmp_router_port"; char tn_string[] = "$telemetry_node", tnp_string[] = "$telemetry_node_port"; char *ptr_start, *ptr_end, *string_ptr; if (!new || !old || !peer) return FALSE; oldlen = strlen(old); if (oldlen <= newlen) strcpy(new, old); ptr_start = NULL; string_ptr = NULL; if (!ptr_start) { ptr_start = strstr(new, psi_string); string_ptr = psi_string; } if (!ptr_start) { ptr_start = strstr(new, br_string); string_ptr = br_string; } if (!ptr_start) { ptr_start = strstr(new, tn_string); string_ptr = tn_string; } if (ptr_start) { char empty_peer_src_ip[] = "null"; char peer_src_ip[SRVBUFLEN]; char buf[newlen]; int len; is_dyn = TRUE; len = strlen(ptr_start); ptr_end = ptr_start; ptr_end += strlen(string_ptr); len -= strlen(string_ptr); if (peer->addr.family) addr_to_str(peer_src_ip, &peer->addr); else strlcpy(peer_src_ip, empty_peer_src_ip, strlen(peer_src_ip)); escape_ip_uscores(peer_src_ip); snprintf(buf, newlen, "%s", peer_src_ip); strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; strncat(new, buf, newlen); } ptr_start = NULL; string_ptr = NULL; if (!ptr_start) { ptr_start = strstr(new, ptp_string); string_ptr = ptp_string; } if (!ptr_start) { ptr_start = strstr(new, brp_string); string_ptr = brp_string; } if (!ptr_start) { ptr_start = strstr(new, tnp_string); string_ptr = tnp_string; } if (ptr_start) { char buf[newlen]; int len; is_dyn = TRUE; len = strlen(ptr_start); ptr_end = ptr_start; ptr_end += strlen(string_ptr); len -= strlen(string_ptr); snprintf(buf, newlen, "%u", peer->tcp_port); strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; strncat(new, buf, newlen); } return is_dyn; } int bgp_peer_dump_init(struct bgp_peer *peer, bgp_tag_t *tag, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); int ret = 0, amqp_ret = 0, kafka_ret = 0; if (!bms || !peer || !peer->log) return ERR; #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); } if (bms->dump_amqp_routing_key_rr && !p_amqp_get_routing_key_rr(peer->log->amqp_host)) { p_amqp_init_routing_key_rr(peer->log->amqp_host); p_amqp_set_routing_key_rr(peer->log->amqp_host, bms->dump_amqp_routing_key_rr); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); } if (bms->dump_kafka_topic_rr && !p_kafka_get_topic_rr(peer->log->kafka_host)) { p_kafka_init_topic_rr(peer->log->kafka_host); p_kafka_set_topic_rr(peer->log->kafka_host, bms->dump_kafka_topic_rr); } #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); char event_type[] = "dump_init"; json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str)); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); if (bms->peer_port_str) json_object_set_new_nocheck(obj, bms->peer_port_str, json_integer((json_int_t)peer->tcp_port)); if (bms->tag_map && tag) { bgp_tag_print_json(obj, tag); } json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); json_object_set_new_nocheck(obj, "dump_period", json_integer((json_int_t)bms->dump.period)); json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, obj); } if (bms->dump_file) { write_and_free_json(peer->log->fd, obj); } #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO char event_type[] = "dump_init"; char ip_address[INET6_ADDRSTRLEN]; avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; void *p_avro_local_buf = NULL; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); p_avro_iface = avro_generic_class_from_schema(bms->dump_avro_schema[BGP_LOG_TYPE_DUMPINIT]); pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (bms->tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "dump_period", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bms->dump.period)); add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, &p_avro_obj); } if (!bms->dump_kafka_avro_schema_registry && output == PRINT_OUTPUT_AVRO_BIN) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_dump_init(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if (bms->dump_file) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { if (bms->dump_kafka_avro_schema_registry) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[BGP_LOG_TYPE_DUMPINIT]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[BGP_LOG_TYPE_DUMPINIT], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_dump_init(): serdes_schema_serialize_avro() failed: %s\n", config.name, bms->log_str, kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); } #endif avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } return (ret | amqp_ret | kafka_ret); } int bgp_peer_dump_close(struct bgp_peer *peer, bgp_tag_t *tag, struct bgp_dump_stats *bds, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); int ret = 0, amqp_ret = 0, kafka_ret = 0; if (!bms || !peer || !peer->log) return ERR; #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); } #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char event_type[] = "dump_close"; char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str)); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); if (bms->peer_port_str) json_object_set_new_nocheck(obj, bms->peer_port_str, json_integer((json_int_t)peer->tcp_port)); if (bms->tag_map && tag) { bgp_tag_print_json(obj, tag); } json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (bds) { json_object_set_new_nocheck(obj, "entries", json_integer((json_int_t)bds->entries)); json_object_set_new_nocheck(obj, "tables", json_integer((json_int_t)bds->tables)); } json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, obj); } if (bms->dump_file) { write_and_free_json(peer->log->fd, obj); } #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO char event_type[] = "dump_close"; char ip_address[INET6_ADDRSTRLEN]; avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; void *p_avro_local_buf = NULL; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); p_avro_iface = avro_generic_class_from_schema(bms->dump_avro_schema[BGP_LOG_TYPE_DUMPCLOSE]); pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->log_tstamp_str)); addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, bms->peer_port_str, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (bms->tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); if (bds) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "entries", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, bds->entries)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "tables", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bds->tables)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "entries", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "tables", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (bms->bgp_peer_logdump_initclose_extras) { bms->bgp_peer_logdump_initclose_extras(peer, output, &p_avro_obj); } if (!bms->dump_kafka_avro_schema_registry && output == PRINT_OUTPUT_AVRO_BIN) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_dump_close(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if (bms->dump_file) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } #ifdef WITH_RABBITMQ if (bms->dump_amqp_routing_key) { if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->dump_kafka_topic) { if (bms->dump_kafka_avro_schema_registry) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[BGP_LOG_TYPE_DUMPCLOSE]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[BGP_LOG_TYPE_DUMPCLOSE], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bgp_peer_dump_close(): serdes_schema_serialize_avro() failed: %s\n", config.name, bms->log_str, kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); } #endif avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } return (ret | amqp_ret | kafka_ret); } void bgp_handle_dump_event(int max_peers_idx) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BGP); thread_pool_t *bgp_table_dump_workers_pool; struct pm_dump_runner pdr[config.bgp_table_dump_workers]; u_int64_t dump_seqno; int idx, ret; /* pre-flight check */ if (!bms->dump_backend_methods || !config.bgp_table_dump_refresh_time) { return; } /* Sequencing the dump event */ dump_seqno = bgp_peer_log_seq_get(&bms->log_seq); bgp_peer_log_seq_increment(&bms->log_seq); switch (ret = fork()) { case 0: /* Child */ /* we have to ignore signals to avoid loops: because we are already forked */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); pm_setproctitle("%s %s [%s]", config.type, "Core Process -- BGP Dump Writer", config.name, bms->log_str); config.is_forked = TRUE; /* setting ourselves as read-only */ bms->is_readonly = TRUE; /* Arranging workers data */ distribute_work(pdr, dump_seqno, config.bgp_table_dump_workers, max_peers_idx); /* creating the thread pool */ bgp_table_dump_workers_pool = allocate_thread_pool(config.bgp_table_dump_workers); assert(bgp_table_dump_workers_pool); for (idx = 0; idx < config.bgp_table_dump_workers; idx++) { if (!pdr[idx].noop) { send_to_pool(bgp_table_dump_workers_pool, bgp_table_dump_event_runner, &pdr[idx]); } } deallocate_thread_pool(&bgp_table_dump_workers_pool); exit_gracefully(0); default: /* Parent */ if (ret == -1) { /* Something went wrong */ Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork BGP table dump writer: %s\n", config.name, bms->log_str, strerror(errno)); } break; } bgp_misc_db->current_slot = (bgp_misc_db->current_slot + 1) % config.bgp_table_dump_time_slots; } int bgp_table_dump_event_runner(struct pm_dump_runner *pdr) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BGP); char current_filename[SRVBUFLEN], last_filename[SRVBUFLEN], tmpbuf[SRVBUFLEN]; char latest_filename[SRVBUFLEN], dump_partition_key[SRVBUFLEN]; char event_type[] = "dump", *fd_buf = NULL; int peers_idx, duration, tables_num; struct bgp_rt_structs *inter_domain_routing_db; struct bgp_peer *peer, *saved_peer; struct bgp_table *table; struct bgp_node *node; struct bgp_peer_log peer_log; struct bgp_dump_stats bds; afi_t afi; safi_t safi; pid_t dumper_pid; time_t start; u_int64_t dump_elems = 0, dump_seqno = pdr->seq; #ifdef WITH_RABBITMQ struct p_amqp_host bgp_table_dump_amqp_host; #endif #ifdef WITH_KAFKA struct p_kafka_host bgp_table_dump_kafka_host; #endif memset(last_filename, 0, sizeof(last_filename)); memset(current_filename, 0, sizeof(current_filename)); memset(&peer_log, 0, sizeof(struct bgp_peer_log)); memset(&bds, 0, sizeof(struct bgp_dump_stats)); fd_buf = malloc(OUTPUT_FILE_BUFSZ); bgp_peer_log_seq_set(&bms->log_seq, dump_seqno); #ifdef WITH_RABBITMQ if (config.bgp_table_dump_amqp_routing_key) { int ret; bgp_table_dump_init_amqp_host(&bgp_table_dump_amqp_host); ret = p_amqp_connect_to_publish(&bgp_table_dump_amqp_host); if (ret) exit_gracefully(ret); } #endif #ifdef WITH_KAFKA if (config.bgp_table_dump_kafka_topic) { int ret; ret = bgp_table_dump_init_kafka_host(&bgp_table_dump_kafka_host); if (ret) exit_gracefully(ret); } #endif dumper_pid = getpid(); Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BGP tables - START (PID: %u RID: %u) ***\n", config.name, bms->log_str, dumper_pid, pdr->id); start = time(NULL); tables_num = 0; #ifdef WITH_SERDES if (config.bgp_table_dump_kafka_avro_schema_registry) { if (strchr(config.bgp_table_dump_kafka_topic, '$')) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'bgp_table_dump_kafka_topic' is not compatible with 'bgp_table_dump_kafka_avro_schema_registry'. Exiting.\n", config.name, bms->log_str); exit_gracefully(1); } bgp_table_dump_kafka_host.sd_schema[0] = compose_avro_schema_registry_name_2(config.bgp_table_dump_kafka_topic, FALSE, bms->dump_avro_schema[0], "bgp", "dump", config.bgp_table_dump_kafka_avro_schema_registry); bgp_table_dump_kafka_host.sd_schema[BGP_LOG_TYPE_DUMPINIT] = compose_avro_schema_registry_name_2(config.bgp_table_dump_kafka_topic, FALSE, bms->dump_avro_schema[BGP_LOG_TYPE_DUMPINIT], "bgp", "dumpinit", config.bgp_table_dump_kafka_avro_schema_registry); bgp_table_dump_kafka_host.sd_schema[BGP_LOG_TYPE_DUMPCLOSE] = compose_avro_schema_registry_name_2(config.bgp_table_dump_kafka_topic, FALSE, bms->dump_avro_schema[BGP_LOG_TYPE_DUMPCLOSE], "bgp", "dumpclose", config.bgp_table_dump_kafka_avro_schema_registry); } #endif if (config.bgp_table_dump_time_slots > 1) { Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BGP tables - SLOT %d / %d ***\n", config.name, bms->log_str, bms->current_slot + 1, config.bgp_table_dump_time_slots); } for (peer = NULL, saved_peer = NULL, peers_idx = pdr->first; peers_idx <= pdr->last; peers_idx++) { if (peers[peers_idx].fd) { peer = &peers[peers_idx]; char peer_addr[INET6_ADDRSTRLEN]; addr_to_str(peer_addr, &(peer->addr)); int bgp_router_slot = abs((int) pm_djb2_string_hash((unsigned char*) peer_addr)) % config.bgp_table_dump_time_slots; if (bgp_router_slot == bms->current_slot) { peer->log = &peer_log; /* abusing struct bgp_peer a bit, but we are in a child */ if (config.bgp_table_dump_file) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bgp_table_dump_file, peer); } if (config.bgp_table_dump_amqp_routing_key) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bgp_table_dump_amqp_routing_key, peer); } if (config.bgp_table_dump_kafka_topic) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bgp_table_dump_kafka_topic, peer); } if (config.bgp_table_dump_kafka_partition_key) { memset(dump_partition_key, 0, SRVBUFLEN); bgp_peer_log_dynname(dump_partition_key, SRVBUFLEN, config.bgp_table_dump_kafka_partition_key, peer); } pm_strftime_same(current_filename, SRVBUFLEN, tmpbuf, &bms->dump.tstamp.tv_sec, config.timestamps_utc); /* we close last_filename and open current_filename in case they differ; we are safe with this approach until time and BGP peer (IP, port) are the only variables supported as part of bgp_table_dump_file. */ if (config.bgp_table_dump_file) { if (strcmp(last_filename, current_filename)) { if (saved_peer && saved_peer->log && strlen(last_filename)) { close_output_file(saved_peer->log->fd); if (config.bgp_table_dump_latest_file) { bgp_peer_log_dynname(latest_filename, SRVBUFLEN, config.bgp_table_dump_latest_file, saved_peer); link_latest_output_file(latest_filename, last_filename); } } peer->log->fd = open_output_file(current_filename, "w", TRUE); if (fd_buf) { if (setvbuf(peer->log->fd, fd_buf, _IOFBF, OUTPUT_FILE_BUFSZ)) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] setvbuf() failed: %s\n", config.name, bms->log_str, current_filename, strerror(errno)); else memset(fd_buf, 0, OUTPUT_FILE_BUFSZ); } } } /* a bit pedantic maybe but should come at little cost and emulating bgp_table_dump_file behaviour will work */ #ifdef WITH_RABBITMQ if (config.bgp_table_dump_amqp_routing_key) { peer->log->amqp_host = &bgp_table_dump_amqp_host; strcpy(peer->log->filename, current_filename); } #endif #ifdef WITH_KAFKA if (config.bgp_table_dump_kafka_topic) { peer->log->kafka_host = &bgp_table_dump_kafka_host; strcpy(peer->log->filename, current_filename); if (config.bgp_table_dump_kafka_partition_key) { p_kafka_set_key(peer->log->kafka_host, dump_partition_key, strlen(dump_partition_key)); } } #endif /* Being bgp_daemon_tag_map limited to 'ip' key lookups, this is finely placed here. Should further lookups be possible, this may be very possibly moved inside the loop */ if (config.bgp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bgp_logdump_tag_peer, &bgp_logdump_tag); bgp_tag_find((struct id_table *)bgp_logdump_tag.tag_table, &bgp_logdump_tag, &bgp_logdump_tag.tag, NULL); } bgp_peer_dump_init(peer, &bgp_logdump_tag, config.bgp_table_dump_output, FUNC_TYPE_BGP); inter_domain_routing_db = bgp_select_routing_db(FUNC_TYPE_BGP); bds.entries = 0; bds.tables = 0; if (!inter_domain_routing_db) return ERR; for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { table = inter_domain_routing_db->rib[afi][safi]; node = bgp_table_top(peer, table); while (node) { u_int32_t modulo = bgp_route_info_modulo(peer, NULL, bms->table_per_peer_buckets); u_int32_t peer_buckets; struct bgp_info *ri; for (peer_buckets = 0; peer_buckets < config.bgp_table_per_peer_buckets; peer_buckets++) { for (ri = node->info[modulo+peer_buckets]; ri; ri = ri->next) { if (ri->peer == peer) { bgp_peer_log_msg(node, ri, afi, safi, &bgp_logdump_tag, event_type, config.bgp_table_dump_output, NULL, BGP_LOG_TYPE_MISC); dump_elems++; bds.entries++; } } } node = bgp_route_next(peer, node); } } } saved_peer = peer; tables_num++; bds.tables++; strlcpy(last_filename, current_filename, SRVBUFLEN); bgp_peer_dump_close(peer, &bgp_logdump_tag, &bds, config.bgp_table_dump_output, FUNC_TYPE_BGP); } } } #ifdef WITH_RABBITMQ if (config.bgp_table_dump_amqp_routing_key) { p_amqp_close(&bgp_table_dump_amqp_host, FALSE); } #endif #ifdef WITH_KAFKA if (config.bgp_table_dump_kafka_topic) { p_kafka_close(&bgp_table_dump_kafka_host, FALSE); } #endif if (config.bgp_table_dump_latest_file && peer) { bgp_peer_log_dynname(latest_filename, SRVBUFLEN, config.bgp_table_dump_latest_file, peer); link_latest_output_file(latest_filename, last_filename); } duration = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BGP tables - END (PID: %u RID: %u TABLES: %u ENTRIES: %" PRIu64 " ET: %u) ***\n", config.name, bms->log_str, dumper_pid, pdr->id, tables_num, dump_elems, duration); return FALSE; } #ifdef WITH_RABBITMQ struct p_amqp_host bgp_table_dump_amqp_host; #endif #ifdef WITH_KAFKA struct p_kafka_host bgp_table_dump_kafka_host; #endif #if defined WITH_RABBITMQ void bgp_daemon_msglog_init_amqp_host() { p_amqp_init_host(&bgp_daemon_msglog_amqp_host); if (!config.bgp_daemon_msglog_amqp_user) config.bgp_daemon_msglog_amqp_user = rabbitmq_user; if (!config.bgp_daemon_msglog_amqp_passwd) config.bgp_daemon_msglog_amqp_passwd = rabbitmq_pwd; if (!config.bgp_daemon_msglog_amqp_exchange) config.bgp_daemon_msglog_amqp_exchange = default_amqp_exchange; if (!config.bgp_daemon_msglog_amqp_exchange_type) config.bgp_daemon_msglog_amqp_exchange_type = default_amqp_exchange_type; if (!config.bgp_daemon_msglog_amqp_host) config.bgp_daemon_msglog_amqp_host = default_amqp_host; if (!config.bgp_daemon_msglog_amqp_vhost) config.bgp_daemon_msglog_amqp_vhost = default_amqp_vhost; if (!config.bgp_daemon_msglog_amqp_retry) config.bgp_daemon_msglog_amqp_retry = AMQP_DEFAULT_RETRY; p_amqp_set_user(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_user); p_amqp_set_passwd(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_passwd); p_amqp_set_exchange(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_exchange); p_amqp_set_exchange_type(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_exchange_type); p_amqp_set_host(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_host); p_amqp_set_vhost(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_vhost); p_amqp_set_persistent_msg(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_persistent_msg); p_amqp_set_frame_max(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_frame_max); p_amqp_set_content_type_json(&bgp_daemon_msglog_amqp_host); p_amqp_set_heartbeat_interval(&bgp_daemon_msglog_amqp_host, config.bgp_daemon_msglog_amqp_heartbeat_interval); P_broker_timers_set_retry_interval(&bgp_daemon_msglog_amqp_host.btimers, config.bgp_daemon_msglog_amqp_retry); } #else void bgp_daemon_msglog_init_amqp_host() { } #endif #if defined WITH_RABBITMQ void bgp_table_dump_init_amqp_host(void *btdah) { struct p_amqp_host *bgp_table_dump_amqp_host = btdah; p_amqp_init_host(bgp_table_dump_amqp_host); if (!config.bgp_table_dump_amqp_user) config.bgp_table_dump_amqp_user = rabbitmq_user; if (!config.bgp_table_dump_amqp_passwd) config.bgp_table_dump_amqp_passwd = rabbitmq_pwd; if (!config.bgp_table_dump_amqp_exchange) config.bgp_table_dump_amqp_exchange = default_amqp_exchange; if (!config.bgp_table_dump_amqp_exchange_type) config.bgp_table_dump_amqp_exchange_type = default_amqp_exchange_type; if (!config.bgp_table_dump_amqp_host) config.bgp_table_dump_amqp_host = default_amqp_host; if (!config.bgp_table_dump_amqp_vhost) config.bgp_table_dump_amqp_vhost = default_amqp_vhost; p_amqp_set_user(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_user); p_amqp_set_passwd(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_passwd); p_amqp_set_exchange(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_exchange); p_amqp_set_exchange_type(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_exchange_type); p_amqp_set_host(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_host); p_amqp_set_vhost(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_vhost); p_amqp_set_persistent_msg(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_persistent_msg); p_amqp_set_frame_max(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_frame_max); p_amqp_set_content_type_json(bgp_table_dump_amqp_host); p_amqp_set_heartbeat_interval(bgp_table_dump_amqp_host, config.bgp_table_dump_amqp_heartbeat_interval); } #else void bgp_table_dump_init_amqp_host(void *btdah) { } #endif #if defined WITH_KAFKA int bgp_daemon_msglog_init_kafka_host() { int ret; p_kafka_init_host(&bgp_daemon_msglog_kafka_host, config.bgp_daemon_msglog_kafka_config_file); ret = p_kafka_connect_to_produce(&bgp_daemon_msglog_kafka_host); if (!config.bgp_daemon_msglog_kafka_broker_host) config.bgp_daemon_msglog_kafka_broker_host = default_kafka_broker_host; if (!config.bgp_daemon_msglog_kafka_broker_port) config.bgp_daemon_msglog_kafka_broker_port = default_kafka_broker_port; if (!config.bgp_daemon_msglog_kafka_retry) config.bgp_daemon_msglog_kafka_retry = PM_KAFKA_DEFAULT_RETRY; p_kafka_set_broker(&bgp_daemon_msglog_kafka_host, config.bgp_daemon_msglog_kafka_broker_host, config.bgp_daemon_msglog_kafka_broker_port); p_kafka_set_topic(&bgp_daemon_msglog_kafka_host, config.bgp_daemon_msglog_kafka_topic); p_kafka_set_partition(&bgp_daemon_msglog_kafka_host, config.bgp_daemon_msglog_kafka_partition); p_kafka_set_key(&bgp_daemon_msglog_kafka_host, config.bgp_daemon_msglog_kafka_partition_key, config.bgp_daemon_msglog_kafka_partition_keylen); p_kafka_set_content_type(&bgp_daemon_msglog_kafka_host, PM_KAFKA_CNT_TYPE_STR); P_broker_timers_set_retry_interval(&bgp_daemon_msglog_kafka_host.btimers, config.bgp_daemon_msglog_kafka_retry); #ifdef WITH_SERDES P_broker_timers_set_retry_interval(&bgp_daemon_msglog_kafka_host.sd_schema_timers, config.bgp_daemon_msglog_kafka_retry); #endif return ret; } #else int bgp_daemon_msglog_init_kafka_host() { return ERR; } #endif #if defined WITH_KAFKA int bgp_table_dump_init_kafka_host(void *btdkh) { struct p_kafka_host *bgp_table_dump_kafka_host = btdkh; int ret; p_kafka_init_host(bgp_table_dump_kafka_host, config.bgp_table_dump_kafka_config_file); ret = p_kafka_connect_to_produce(bgp_table_dump_kafka_host); if (!config.bgp_table_dump_kafka_broker_host) config.bgp_table_dump_kafka_broker_host = default_kafka_broker_host; if (!config.bgp_table_dump_kafka_broker_port) config.bgp_table_dump_kafka_broker_port = default_kafka_broker_port; p_kafka_set_broker(bgp_table_dump_kafka_host, config.bgp_table_dump_kafka_broker_host, config.bgp_table_dump_kafka_broker_port); p_kafka_set_topic(bgp_table_dump_kafka_host, config.bgp_table_dump_kafka_topic); p_kafka_set_partition(bgp_table_dump_kafka_host, config.bgp_table_dump_kafka_partition); p_kafka_set_key(bgp_table_dump_kafka_host, config.bgp_table_dump_kafka_partition_key, config.bgp_table_dump_kafka_partition_keylen); p_kafka_set_content_type(bgp_table_dump_kafka_host, PM_KAFKA_CNT_TYPE_STR); return ret; } #else int bgp_table_dump_init_kafka_host(void *btdkh) { return ERR; } #endif #if defined WITH_AVRO avro_schema_t p_avro_schema_build_bgp(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_LOG && log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BGP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BGP); avro_schema_record_field_append(schema, "peer_ip_src", avro_schema_string()); avro_schema_record_field_append(schema, "peer_tcp_port", optint_s); if (config.tmp_bgp_lookup_compare_ports) { avro_schema_record_field_append(schema, "peer_id", avro_schema_string()); } p_avro_schema_build_bgp_route(&schema, &optlong_s, &optstr_s, &optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bgp_log_initclose(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_LOG) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BGP, schema_name); /* prevent log_type from being added to Avro schema */ log_type = BGP_LOGDUMP_ET_NONE; p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BGP); log_type = BGP_LOGDUMP_ET_LOG; avro_schema_record_field_append(schema, "peer_ip_src", avro_schema_string()); avro_schema_record_field_append(schema, "peer_tcp_port", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bgp_dump_init(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BGP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BGP); avro_schema_record_field_append(schema, "peer_ip_src", avro_schema_string()); avro_schema_record_field_append(schema, "peer_tcp_port", optint_s); avro_schema_record_field_append(schema, "dump_period", avro_schema_long()); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bgp_dump_close(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BGP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BGP); avro_schema_record_field_append(schema, "peer_ip_src", avro_schema_string()); avro_schema_record_field_append(schema, "peer_tcp_port", optint_s); avro_schema_record_field_append(schema, "entries", optlong_s); avro_schema_record_field_append(schema, "tables", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } void p_avro_schema_init_bgp(avro_schema_t *schema, avro_schema_t *optlong_s, avro_schema_t *optstr_s, avro_schema_t *optint_s, int type, char *schema_name) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); (*schema) = avro_schema_record(schema_name, NULL); Log(LOG_INFO, "INFO ( %s/%s ): p_avro_schema_init_bgp(): building %s schema.\n", config.name, bms->log_str, schema_name); avro_schema_union_append((*optlong_s), avro_schema_null()); avro_schema_union_append((*optlong_s), avro_schema_long()); avro_schema_union_append((*optstr_s), avro_schema_null()); avro_schema_union_append((*optstr_s), avro_schema_string()); avro_schema_union_append((*optint_s), avro_schema_null()); avro_schema_union_append((*optint_s), avro_schema_int()); } void p_avro_schema_build_bgp_common(avro_schema_t *schema, avro_schema_t *optlong_s, avro_schema_t *optstr_s, avro_schema_t *optint_s, int log_type, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); if (log_type == BGP_LOGDUMP_ET_LOG) { avro_schema_record_field_append((*schema), "log_type", avro_schema_string()); } avro_schema_record_field_append((*schema), "seq", avro_schema_long()); avro_schema_record_field_append((*schema), "timestamp", avro_schema_string()); avro_schema_record_field_append((*schema), "event_type", avro_schema_string()); avro_schema_record_field_append((*schema), "writer_id", avro_schema_string()); if (bms->tag_map) { avro_schema_record_field_append((*schema), "tag", (*optlong_s)); if (config.pretag_label_encode_as_map) { compose_label_avro_schema_opt((*schema)); } else { avro_schema_record_field_append((*schema), "label", (*optstr_s)); } } } void p_avro_schema_build_bgp_route(avro_schema_t *schema, avro_schema_t *optlong_s, avro_schema_t *optstr_s, avro_schema_t *optint_s) { avro_schema_record_field_append((*schema), "afi", avro_schema_int()); avro_schema_record_field_append((*schema), "safi", avro_schema_int()); avro_schema_record_field_append((*schema), "ip_prefix", (*optstr_s)); avro_schema_record_field_append((*schema), "rd", (*optstr_s)); avro_schema_record_field_append((*schema), "rd_origin", (*optstr_s)); avro_schema_record_field_append((*schema), "bgp_nexthop", (*optstr_s)); avro_schema_record_field_append((*schema), "as_path", (*optstr_s)); avro_schema_record_field_append((*schema), "as_path_id", (*optlong_s)); avro_schema_record_field_append((*schema), "comms", (*optstr_s)); avro_schema_record_field_append((*schema), "ecomms", (*optstr_s)); avro_schema_record_field_append((*schema), "lcomms", (*optstr_s)); if (!config.tmp_bgp_daemon_origin_type_int) { avro_schema_record_field_append((*schema), "origin", (*optstr_s)); } else { avro_schema_record_field_append((*schema), "origin", (*optlong_s)); } avro_schema_record_field_append((*schema), "local_pref", (*optlong_s)); avro_schema_record_field_append((*schema), "med", (*optlong_s)); avro_schema_record_field_append((*schema), "aigp", (*optlong_s)); avro_schema_record_field_append((*schema), "psid_li", (*optlong_s)); avro_schema_record_field_append((*schema), "mpls_label", (*optstr_s)); if (config.rpki_roas_file || config.rpki_rtr_cache) { avro_schema_record_field_append((*schema), "roa", avro_schema_string()); } } #endif #ifdef WITH_JANSSON void bgp_tag_print_json(json_t *obj, bgp_tag_t *tag) { bgp_tag_cache_t tag_cache; memset(&tag_cache, 0, sizeof(tag_cache)); if (tag->have_tag) { tag_cache.primitives.tag = tag->tag; compose_json_tag(obj, &tag_cache); } else if (tag->have_label) { tag_cache.pvlen = malloc(sizeof(struct pkt_vlen_hdr_primitives) + PmLabelTSz + tag->label.len + 1); vlen_prims_init(tag_cache.pvlen, 0); vlen_prims_insert(tag_cache.pvlen, COUNT_INT_LABEL, tag->label.len, (u_char *) tag->label.val, PM_MSG_STR_COPY_ZERO); if (config.pretag_label_encode_as_map) { compose_json_map_label(obj, &tag_cache); } else { compose_json_label(obj, &tag_cache); } vlen_prims_free(tag_cache.pvlen); } } #endif #ifdef WITH_AVRO void bgp_tag_print_avro(avro_value_t obj, bgp_tag_t *tag) { avro_value_t p_avro_field, p_avro_branch; if (tag->have_tag) { pm_avro_check(avro_value_get_by_name(&obj, "tag", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_long(&p_avro_branch, tag->tag)); } else { pm_avro_check(avro_value_get_by_name(&obj, "tag", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (tag->have_label) { if (config.pretag_label_encode_as_map) { compose_label_avro_data_opt(tag->label.val, obj); } else { pm_avro_check(avro_value_get_by_name(&obj, "label", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, tag->label.val)); } } else { pm_avro_check(avro_value_get_by_name(&obj, "label", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } #endif pmacct-1.7.8/src/bgp/bgp_hash.h0000644000175000017500000000400014354105275015267 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on Quagga hash routine which is: Copyright (C) 1998 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_HASH_H_ #define _BGP_HASH_H_ /* Default hash table size. */ #define HASHTABSIZE 65535 struct hash_backet { /* Linked list. */ struct hash_backet *next; /* Hash key. */ unsigned int key; /* Data. */ void *data; }; struct hash { /* Hash backet. */ struct hash_backet **index; /* Hash table size. */ unsigned int size; /* Key make function. */ unsigned int (*hash_key) (void *); /* Data compare function. */ int (*hash_cmp) (const void *, const void *); /* Backet alloc. */ unsigned long count; }; extern struct hash *hash_create (int, unsigned int (*) (void *), int (*) (const void *, const void *)); extern struct hash *hash_create_size (unsigned int, unsigned int (*) (void *), int (*) (const void *, const void *)); extern void *hash_get (struct bgp_peer *, struct hash *, void *, void * (*) (void *)); extern void *hash_alloc_intern (void *); extern void *hash_release (struct hash *, void *); extern void hash_iterate (struct hash *, void (*) (struct hash_backet *, void *), void *); extern void hash_clean (struct hash *, void (*) (void *)); extern void hash_free (struct hash *); #endif pmacct-1.7.8/src/bgp/bgp_blackhole.c0000644000175000017500000001753014354105275016277 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp.h" #include "bgp_blackhole.h" #include "thread_pool.h" #if defined WITH_ZMQ #include "zmq_common.h" #endif /* Global variables */ thread_pool_t *bgp_blackhole_pool; struct bgp_rt_structs *bgp_blackhole_db; struct bgp_misc_structs *bgp_blackhole_misc_db; struct bgp_peer bgp_blackhole_peer; struct bloom *bgp_blackhole_filter; struct community *bgp_blackhole_comms; /* Functions */ void bgp_blackhole_daemon_wrapper() { #if defined WITH_ZMQ struct p_zmq_host *bgp_blackhole_zmq_host = NULL; char inproc_blackhole_str[] = "inproc://bgp_blackhole"; /* initialize threads pool */ bgp_blackhole_pool = allocate_thread_pool(1); assert(bgp_blackhole_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/BH ): %d thread(s) initialized\n", config.name, 1); bgp_blackhole_prepare_filter(); bgp_blackhole_prepare_thread(); bgp_blackhole_zmq_host = malloc(sizeof(struct p_zmq_host)); if (!bgp_blackhole_zmq_host) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() bgp_blackhole_zmq_host. Terminating thread.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); } else memset(bgp_blackhole_zmq_host, 0, sizeof(struct p_zmq_host)); p_zmq_set_log_id(bgp_blackhole_zmq_host, bgp_blackhole_misc_db->log_str); p_zmq_set_address(bgp_blackhole_zmq_host, inproc_blackhole_str); p_zmq_ctx_setup(bgp_blackhole_zmq_host); bgp_blackhole_misc_db->bgp_blackhole_zmq_host = bgp_blackhole_zmq_host; /* giving a kick to the BGP blackhole thread */ send_to_pool(bgp_blackhole_pool, bgp_blackhole_daemon, NULL); #else Log(LOG_ERR, "ERROR ( %s/%s ): BGP BlackHole feature requires compiling with --enable-zmq.\n", config.name, bgp_misc_db->log_str); exit_gracefully(1); #endif } #if defined WITH_ZMQ void bgp_blackhole_prepare_thread() { bgp_blackhole_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_BGP_BLACKHOLE]; memset(bgp_blackhole_misc_db, 0, sizeof(struct bgp_misc_structs)); bgp_blackhole_misc_db->is_thread = TRUE; bgp_blackhole_misc_db->log_str = malloc(strlen("core/BH") + 1); strcpy(bgp_blackhole_misc_db->log_str, "core/BH"); } void bgp_blackhole_init_dummy_peer(struct bgp_peer *peer) { memset(peer, 0, sizeof(struct bgp_peer)); peer->type = FUNC_TYPE_BGP_BLACKHOLE; } void bgp_blackhole_prepare_filter() { char *stdcomms, *token; bgp_blackhole_filter = malloc(sizeof(struct bloom)); bloom_init(bgp_blackhole_filter, BGP_BLACKHOLE_DEFAULT_BF_ENTRIES, 0.01); stdcomms = strdup(config.bgp_blackhole_stdcomm_list); bgp_blackhole_comms = community_new(&bgp_blackhole_peer); while ((token = extract_token(&stdcomms, ','))) { u_int32_t stdcomm; int ret; ret = community_str2com_simple(token, &stdcomm); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): Invalid community '%s' in 'bgp_blackhole_stdcomm_list'.\n", config.name, bgp_blackhole_misc_db->log_str, token); exit_gracefully(1); } bloom_add(bgp_blackhole_filter, &stdcomm, sizeof(stdcomm)); community_add_val(&bgp_blackhole_peer, bgp_blackhole_comms, stdcomm); } } int bgp_blackhole_daemon() { struct bgp_misc_structs *m_data = bgp_blackhole_misc_db; struct bgp_blackhole_itc bbitc; int bh_state; afi_t afi; safi_t safi; int ret; /* ZeroMQ stuff */ struct p_zmq_host *bgp_blackhole_zmq_host; bgp_blackhole_zmq_host = m_data->bgp_blackhole_zmq_host; p_zmq_pull_bind_setup(bgp_blackhole_zmq_host); bgp_blackhole_init_dummy_peer(&bgp_blackhole_peer); bgp_blackhole_db = &inter_domain_routing_dbs[FUNC_TYPE_BGP_BLACKHOLE]; memset(bgp_blackhole_db, 0, sizeof(struct bgp_rt_structs)); bgp_attr_init(HASHTABSIZE, bgp_blackhole_db); /* Let's initialize clean shared RIB */ for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { bgp_blackhole_db->rib[afi][safi] = bgp_table_init(afi, safi); } } bgp_blackhole_link_misc_structs(m_data); for (;;) { ret = p_zmq_recv_poll(&bgp_blackhole_zmq_host->sock_inproc, (DEFAULT_SLOTH_SLEEP_TIME * 1000)); switch (ret) { case TRUE: /* got data */ ret = p_zmq_recv_bin(&bgp_blackhole_zmq_host->sock_inproc, &bbitc, sizeof(bbitc)); if (ret < 0) continue; /* ZMQ_RECONNECT_IVL */ break; case FALSE: /* timeout */ continue; break; case ERR: /* error */ default: continue; /* ZMQ_RECONNECT_IVL */ break; } ret = bgp_lookup_node_vector_unicast(bbitc.p, bbitc.peer, m_data->bnv); bh_state = bgp_blackhole_validate(bbitc.p, bbitc.peer, bbitc.attr, m_data->bnv); (void)bh_state; // XXX: process state // XXX: free not needed alloc'd structs } return SUCCESS; } int bgp_blackhole_evaluate_comms(void *a) { struct bgp_attr *attr = (struct bgp_attr *) a; struct community *comm; int idx, idx2, ret, ret2; u_int32_t val, val2; if (attr && attr->community && attr->community->val) { comm = attr->community; for (idx = 0; idx < comm->size; idx++) { val = community_val_get(comm, idx); ret = bloom_check(bgp_blackhole_filter, &val, sizeof(val)); if (ret) { /* let's make sure it is not a false positive */ for (idx2 = 0; idx2 < bgp_blackhole_comms->size; idx2++) { val2 = community_val_get(bgp_blackhole_comms, idx2); ret2 = community_compare(&val, &val2); if (!ret2) return ret; } /* if we are here it was a false positive; let's continue our quest */ } } } return FALSE; } int bgp_blackhole_instrument(struct bgp_peer *peer, struct prefix *p, void *a, afi_t afi, safi_t safi) { struct bgp_misc_structs *m_data = bgp_blackhole_misc_db; struct bgp_attr *acopy, *attr = (struct bgp_attr *) a; struct prefix *pcopy; struct bgp_peer *peer_copy; struct bgp_blackhole_itc bbitc; struct p_zmq_host *bgp_blackhole_zmq_host; int ret; pcopy = prefix_new(); prefix_copy(pcopy, p); acopy = malloc(sizeof(struct bgp_attr)); memcpy(acopy, attr, sizeof(struct bgp_attr)); peer_copy = malloc(sizeof(struct bgp_peer)); memcpy(peer_copy, peer, sizeof(struct bgp_peer)); if (attr->aspath) acopy->aspath = aspath_dup(attr->aspath); if (attr->community) acopy->community = community_dup(attr->community); if (attr->ecommunity) acopy->ecommunity = ecommunity_dup(attr->ecommunity); if (attr->lcommunity) acopy->lcommunity = lcommunity_dup(attr->lcommunity); memset(&bbitc, 0, sizeof(bbitc)); bbitc.peer = peer_copy; bbitc.afi = afi; bbitc.safi = safi; bbitc.p = pcopy; bbitc.attr = acopy; bgp_blackhole_zmq_host = m_data->bgp_blackhole_zmq_host; ret = p_zmq_send_bin(&bgp_blackhole_zmq_host->sock_inproc, &bbitc, sizeof(bbitc), FALSE); if (ret <= 0) return ERR; return FALSE; } int bgp_blackhole_validate(struct prefix *p, struct bgp_peer *peer, struct bgp_attr *attr, struct bgp_node_vector *bnv) { int idx, bh_state = BGP_BLACKHOLE_STATE_UNKNOWN; if (!bnv || !bnv->entries) return bh_state; /* (bnv->entries - 1) is the blackhole itself (bnv->entries - 2) is the covering prefix */ if (bnv->entries >= 2) { idx = (bnv->entries - 2); (void)idx; // XXX } else { // XXX } return bh_state; } #endif pmacct-1.7.8/src/bgp/bgp_xcs.c0000644000175000017500000001013414354105275015141 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "bgp.h" #include "bgp_xcs.h" void bgp_xcs_map_validate(char *filename, struct plugin_requests *req) { struct bgp_xconnects *table = (struct bgp_xconnects *) req->key_value_table; int valid = FALSE; /* IF we have got 1) AF for _only one_ of src and src_addr, and dst AND 2) AFs of src_addr and src_mask are consistent THEN we are good to go */ if (table && table->pool) { if (sa_has_family((struct sockaddr *) &table->pool[table->num].src) && sa_has_family((struct sockaddr *) &table->pool[table->num].dst)) valid = TRUE; if (table->pool[table->num].src_addr.family && table->pool[table->num].src_mask.family && sa_has_family((struct sockaddr *) &table->pool[table->num].dst)) valid = TRUE; if (table->pool[table->num].src_addr.family == table->pool[table->num].src_mask.family) valid = TRUE; if (sa_has_family((struct sockaddr *) &table->pool[table->num].src) && (table->pool[table->num].src_addr.family || table->pool[table->num].src_mask.family)) valid = FALSE; if (valid && table->num < req->map_entries) { table->num++; table->pool[table->num].id = table->num; } else memset(&table->pool[table->num], 0, sizeof(struct bgp_xconnect)); } } int bgp_xcs_parse_hostport(const char *s, struct sockaddr *addr, socklen_t *len) { return Tee_parse_hostport(s, addr, len, TRUE); } int bgp_xcs_map_dst_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct bgp_xconnects *table = (struct bgp_xconnects *) req->key_value_table; struct bgp_xconnect *target = NULL; if (table && table->pool) { if (table->num < req->map_entries) { target = &table->pool[table->num]; target->dst_len = sizeof(target->dst); if (bgp_xcs_parse_hostport(value, (struct sockaddr *)&target->dst, &target->dst_len)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Invalid BGP xconnect destination.\n", config.name, config.type, filename); return TRUE; } } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] BGP xconnect table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int bgp_xcs_map_src_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct bgp_xconnects *table = (struct bgp_xconnects *) req->key_value_table; struct bgp_xconnect *target = NULL; if (table && table->pool) { if (table->num < req->map_entries) { target = &table->pool[table->num]; target->src_len = sizeof(target->src); if (bgp_xcs_parse_hostport(value, (struct sockaddr *)&target->src, &target->src_len)) { memset(&target->src, 0, sizeof(target->src)); target->src_len = 0; if (!str_to_addr_mask(value, &target->src_addr, &target->src_mask)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Invalid BGP xconnect source.\n", config.name, config.type, filename); return TRUE; } } } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] BGP xconnect table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } void bgp_xcs_map_destroy() { int idx; for (idx = 0; idx < bgp_xcs_map.num; idx++) memset(&bgp_xcs_map.pool[idx], 0, sizeof(struct bgp_xconnect)); bgp_xcs_map.num = 0; } pmacct-1.7.8/src/bgp/bgp.h0000644000175000017500000002754114354105275014303 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include #include #include "bgp_prefix.h" #include "bgp_packet.h" #include "bgp_table.h" #ifndef _BGP_H_ #define _BGP_H_ /* defines */ /* BGP finite state machine status. */ #define Idle 1 #define Connect 2 #define Active 3 #define OpenSent 4 #define OpenConfirm 5 #define Established 6 #define Clearing 7 #define Deleted 8 #define BGP_ATTR_MIN_LEN 3 /* Attribute flag, type length. */ /* BGP4 attribute type codes. */ #define BGP_ATTR_ORIGIN 1 #define BGP_ATTR_AS_PATH 2 #define BGP_ATTR_NEXT_HOP 3 #define BGP_ATTR_MULTI_EXIT_DISC 4 #define BGP_ATTR_LOCAL_PREF 5 #define BGP_ATTR_ATOMIC_AGGREGATE 6 #define BGP_ATTR_AGGREGATOR 7 #define BGP_ATTR_COMMUNITIES 8 #define BGP_ATTR_ORIGINATOR_ID 9 #define BGP_ATTR_CLUSTER_LIST 10 #define BGP_ATTR_DPA 11 #define BGP_ATTR_ADVERTISER 12 #define BGP_ATTR_RCID_PATH 13 #define BGP_ATTR_MP_REACH_NLRI 14 #define BGP_ATTR_MP_UNREACH_NLRI 15 #define BGP_ATTR_EXT_COMMUNITIES 16 #define BGP_ATTR_AS4_PATH 17 #define BGP_ATTR_AS4_AGGREGATOR 18 #define BGP_ATTR_AS_PATHLIMIT 21 #define BGP_ATTR_AIGP 26 #define BGP_ATTR_LARGE_COMMUNITIES 32 /* rfc8092 */ #define BGP_ATTR_PREFIX_SID 40 /* BGP4 internal bitmap type codes. */ #define BGP_BMAP_ATTR_MULTI_EXIT_DISC 0x01 #define BGP_BMAP_ATTR_LOCAL_PREF 0x02 #define BGP_BMAP_ATTR_AIGP 0x04 #define BGP_NLRI_UNDEFINED 0 #define BGP_NLRI_UPDATE 1 #define BGP_NLRI_WITHDRAW 2 /* BGP Attribute flags. */ #define BGP_ATTR_FLAG_OPTIONAL 0x80 /* Attribute is optional. */ #define BGP_ATTR_FLAG_TRANS 0x40 /* Attribute is transitive. */ #define BGP_ATTR_FLAG_PARTIAL 0x20 /* Attribute is partial. */ #define BGP_ATTR_FLAG_EXTLEN 0x10 /* Extended length flag. */ /* BGP misc */ #define MAX_BGP_PEERS_DEFAULT 4 #define MAX_HOPS_FOLLOW_NH 20 #define MAX_NH_SELF_REFERENCES 1 #define BGP_XCONNECT_STRLEN (2 * (INET6_ADDRSTRLEN + PORT_STRLEN + 1) + 4) /* Maximum BGP community patterns supported: bgp_daemon_stdcomm_pattern, bgp_daemon_extcomm_pattern, bgp_blackhole_stdcomm_list, etc. */ #define MAX_BGP_COMM_PATTERNS 16 #define MAX_BGP_COMM_ELEMS MAX_BGP_COMM_PATTERNS #define BGP_DAEMON_NONE 0 #define BGP_DAEMON_TRUE 1 #define BGP_DAEMON_ONLINE 1 #define BGP_MSG_EXTRA_DATA_NONE 0 #define BGP_MSG_EXTRA_DATA_BMP 1 #define BGP_LOOKUP_NOPEER 2 #define BGP_LOOKUP_NOPREFIX 1 #define BGP_LOOKUP_OK 0 #define BGP_LOOKUP_ERR -1 #define BGP_ORIGIN_IGP 0 #define BGP_ORIGIN_EGP 1 #define BGP_ORIGIN_INCOMPLETE 2 #define BGP_ORIGIN_MAX 2 #define BGP_ORIGIN_UNKNOWN 3 #define BGP_PREFIX_SID_LI_TLV 1 #define BGP_PREFIX_SID_OSRGB_TLV 2 /* structures */ struct bgp_dump_event { struct timeval tstamp; char tstamp_str[SRVBUFLEN]; u_int32_t period; }; struct bgp_rt_structs { struct hash *attrhash; struct hash *ashash; struct hash *comhash; struct hash *ecomhash; struct hash *lcomhash; struct bgp_table *rib[AFI_MAX][SAFI_MAX]; }; struct bgp_peer_cache { struct bgp_peer *ptr; struct bgp_peer_cache *next; }; struct bgp_peer_cache_bucket { pthread_mutex_t mutex; struct bgp_peer_cache *e; }; struct bgp_xconnect { u_int32_t id; struct sockaddr_storage dst; /* BGP receiver IP address and port */ socklen_t dst_len; struct sockaddr_storage src; /* BGP peer IP address and port */ socklen_t src_len; struct host_addr src_addr; /* IP prefix to match multiple BGP peers */ struct host_mask src_mask; }; struct bgp_xconnects { struct bgp_xconnect *pool; int num; }; struct bgp_peer_stats { u_int64_t packets; /* Datagrams received */ u_int64_t packet_bytes; /* Bytes read off the socket */ u_int64_t msg_bytes; /* Bytes in the decoded messages */ u_int64_t msg_errors; /* Errors detected in message content */ time_t last_check; /* Timestamp when stats were last checked */ }; struct bgp_peer_buf { char *base; u_int32_t tot_len; /* total buffer length */ u_int32_t cur_len; /* current message consumed length (for segmented reads) */ u_int32_t exp_len; /* current message expected length */ #if defined WITH_KAFKA void *kafka_msg; #endif }; struct cap_per_af { u_int8_t cap[AFI_MAX][SAFI_MAX]; afi_t afi_max; safi_t safi_max; }; struct bgp_peer { int idx; int fd; int lock; int type; /* ie. BGP vs BMP */ u_int8_t status; u_int8_t version; as_t myas; as_t as; u_int16_t ht; time_t last_keepalive; struct host_addr id; struct host_addr addr; char addr_str[INET6_ADDRSTRLEN]; u_int16_t tcp_port; u_int8_t cap_mp; char *cap_4as; struct cap_per_af cap_add_paths; u_int32_t msglen; struct bgp_peer_stats stats; struct bgp_peer_buf buf; struct bgp_peer_log *log; /* bmp_peer.self.bmp_se: pointer to struct bmp_dump_se_ll bmp_peer.bgp_peers[n].bmp_se: backpointer to parent struct bmp_peer */ void *bmp_se; struct bgp_xconnect xc; struct bgp_peer_buf xbuf; int xconnect_fd; int parsed_proxy_header; }; struct bgp_msg_data { struct bgp_peer *peer; struct bgp_msg_extra_data extra; int is_blackhole; }; typedef struct packet_ptrs bgp_tag_t; typedef struct chained_cache bgp_tag_cache_t; struct bgp_misc_structs { struct bgp_peer_log *peers_log; u_int64_t log_seq; struct timeval log_tstamp; char log_tstamp_str[SRVBUFLEN]; struct bgp_node_vector *bnv; struct bgp_dump_event dump; char *peer_str; /* "bmp_router", "peer_src_ip", "peer_ip", etc. */ char *peer_port_str; /* "bmp_router_port", "peer_src_ip_port", etc. */ char *log_str; /* BGP, BMP, thread, daemon, etc. */ int is_thread; int is_readonly; /* disables locking! set to true only in a dump child process */ int has_lglass; int has_blackhole; int skip_rib; int cap_add_path_ignore; #if defined WITH_RABBITMQ struct p_amqp_host *msglog_amqp_host; #endif #if defined WITH_KAFKA struct p_kafka_host *msglog_kafka_host; #endif void *peers; int max_peers; void *peers_cache; void *peers_port_cache; struct log_notification *peers_limit_log; void *xconnects; char *neighbors_file; char *dump_file; char *dump_amqp_routing_key; int dump_amqp_routing_key_rr; char *dump_kafka_topic; int dump_kafka_topic_rr; char *dump_kafka_partition_key; #if defined WITH_AVRO avro_schema_t dump_avro_schema[MAX_AVRO_SCHEMA]; #endif char *dump_kafka_avro_schema_registry; char *msglog_file; int msglog_output; char *msglog_amqp_routing_key; int msglog_amqp_routing_key_rr; char *msglog_kafka_topic; int msglog_kafka_topic_rr; char *msglog_kafka_partition_key; #if defined WITH_AVRO avro_schema_t msglog_avro_schema[MAX_AVRO_SCHEMA]; #endif char *msglog_kafka_avro_schema_registry; char *avro_buf; void (*bgp_peer_log_msg_extras)(struct bgp_peer *, int, int, int, void *); void (*bgp_peer_logdump_initclose_extras)(struct bgp_peer *, int, void *); void (*bgp_peer_logdump_extra_data)(struct bgp_msg_extra_data *, int, void *); int (*bgp_extra_data_process)(struct bgp_msg_extra_data *, struct bgp_info *, int, int); int (*bgp_extra_data_cmp)(struct bgp_msg_extra_data *, struct bgp_msg_extra_data *); void (*bgp_extra_data_free)(struct bgp_msg_extra_data *); int table_peer_buckets; int table_per_peer_buckets; int table_attr_hash_buckets; int table_per_peer_hash; u_int32_t (*route_info_modulo)(struct bgp_peer *, path_id_t *, int); struct bgp_peer *(*bgp_lookup_find_peer)(struct sockaddr *, struct xflow_status_entry *, u_int16_t, int); int (*bgp_lookup_node_match_cmp)(struct bgp_info *, struct node_match_cmp_term2 *); int msglog_backend_methods; int dump_backend_methods; int dump_input_backend_methods; int (*bgp_msg_open_router_id_check)(struct bgp_msg_data *); void *bgp_blackhole_zmq_host; char *tag_map; bgp_tag_t *tag; int current_slot; struct sockaddr_storage *tag_peer; void (*bgp_table_info_delete_tag_find)(struct bgp_peer *); struct dynname_tokens writer_id_tokens; }; /* these includes require definition of bgp_rt_structs and bgp_peer */ #include "bgp_logdump.h" #include "bgp_aspath.h" #include "bgp_community.h" #include "bgp_ecommunity.h" #include "bgp_lcommunity.h" /* this include requires definition of bgp_peer */ #include "bgp_hash.h" struct bgp_peer_batch { int num; int num_current; time_t base_stamp; int interval; }; struct bgp_nlri { afi_t afi; safi_t safi; u_char *nlri; u_int16_t length; }; struct bgp_attr { struct aspath *aspath; struct community *community; struct ecommunity *ecommunity; struct lcommunity *lcommunity; unsigned long refcnt; u_int32_t flag; struct in_addr nexthop; struct host_addr mp_nexthop; u_int32_t med; u_int32_t local_pref; u_int8_t origin; u_int8_t bitmap; }; struct bgp_comm_range { u_int32_t first; u_int32_t last; }; /* Looking Glass */ struct bgp_lg_req { u_int32_t type; u_int32_t num; void *data; }; struct bgp_lg_rep_data { void *ptr; struct bgp_lg_rep_data *next; }; struct bgp_lg_rep { u_int32_t type; u_int32_t results; struct bgp_lg_rep_data *data; }; struct bgp_lg_req_ipl_data { struct sockaddr peer; struct prefix pref; rd_t rd; }; struct bgp_lg_rep_ipl_data { afi_t afi; safi_t safi; struct prefix *pref; struct bgp_info *info; }; struct bgp_lg_rep_gp_data { struct bgp_peer *peer; }; #include "bgp_msg.h" #include "bgp_lookup.h" #include "bgp_util.h" /* prototypes */ extern void bgp_daemon_wrapper(); extern int skinny_bgp_daemon(); extern void skinny_bgp_daemon_online(); extern void bgp_prepare_thread(); extern void bgp_prepare_daemon(); extern void bgp_daemon_msglog_prepare_sd_schemas(); extern void bgp_tag_init_find(struct bgp_peer *, struct sockaddr *, bgp_tag_t *); extern int bgp_tag_find(struct id_table *, bgp_tag_t *, pm_id_t *, pm_id_t *); /* global variables */ extern struct bgp_peer *peers; extern struct bgp_peer_cache_bucket *peers_cache, *peers_port_cache; extern char *std_comm_patterns[MAX_BGP_COMM_PATTERNS]; extern char *ext_comm_patterns[MAX_BGP_COMM_PATTERNS]; extern char *lrg_comm_patterns[MAX_BGP_COMM_PATTERNS]; extern char *std_comm_patterns_to_asn[MAX_BGP_COMM_PATTERNS]; extern char *lrg_comm_patterns_to_asn[MAX_BGP_COMM_PATTERNS]; extern struct bgp_comm_range peer_src_as_ifrange; extern struct bgp_comm_range peer_src_as_asrange; extern u_int32_t (*bgp_route_info_modulo)(struct bgp_peer *, path_id_t *, int); extern struct bgp_rt_structs inter_domain_routing_dbs[FUNC_TYPE_MAX], *bgp_routing_db; extern struct bgp_misc_structs inter_domain_misc_dbs[FUNC_TYPE_MAX], *bgp_misc_db; extern bgp_tag_t bgp_logdump_tag; extern struct sockaddr_storage bgp_logdump_tag_peer; extern struct bgp_xconnects bgp_xcs_map; #endif pmacct-1.7.8/src/bgp/bgp_xcs.h0000644000175000017500000000266414354105275015157 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BGP_XCS_H #define BGP_XCS_H /* includes */ /* defines */ /* structures */ /* prototypes */ extern int bgp_xcs_map_src_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int bgp_xcs_map_dst_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern void bgp_xcs_map_validate(char *, struct plugin_requests *); extern int bgp_xcs_parse_hostport(const char *, struct sockaddr *, socklen_t *); extern void bgp_xcs_map_destroy(); /* global variables */ extern int Tee_parse_hostport(const char *, struct sockaddr *, socklen_t *, int); #endif //BGP_XCS_H pmacct-1.7.8/src/bgp/bgp_lookup.c0000644000175000017500000007470414354105275015672 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_hooks.h" #include "pmacct-data.h" #include "pkt_handlers.h" #include "bgp.h" #include "pmbgpd.h" #include "rpki/rpki.h" void bgp_srcdst_lookup(struct packet_ptrs *pptrs, int type) { struct bgp_misc_structs *bms; struct bgp_rt_structs *inter_domain_routing_db; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent, sa_local; struct xflow_status_entry *xs_entry = (struct xflow_status_entry *) pptrs->f_status; struct bgp_peer *peer; struct bgp_node *default_node, *result; struct bgp_info *info = NULL; struct node_match_cmp_term2 nmct2; struct prefix default_prefix; int compare_bgp_port = config.tmp_bgp_lookup_compare_ports; int follow_default = config.bgp_daemon_follow_default; struct in_addr pref4; struct in6_addr pref6; safi_t safi; rd_t rd; bms = bgp_select_misc_db(type); inter_domain_routing_db = bgp_select_routing_db(type); if (!bms || !inter_domain_routing_db) return; pptrs->bgp_src = NULL; pptrs->bgp_dst = NULL; pptrs->bgp_src_info = NULL; pptrs->bgp_dst_info = NULL; pptrs->bgp_peer = NULL; pptrs->bgp_nexthop_info = NULL; safi = SAFI_UNICAST; memset(&rd, 0, sizeof(rd)); if (pptrs->bta || pptrs->bta2) { sa = &sa_local; if (pptrs->bta_af == ETHERTYPE_IP) { sa->sa_family = AF_INET; ((struct sockaddr_in *)sa)->sin_addr.s_addr = pptrs->bta; if (pptrs->lookup_bgp_port.set) { ((struct sockaddr_in *)sa)->sin_port = pptrs->lookup_bgp_port.n; compare_bgp_port = TRUE; } } else if (pptrs->bta_af == ETHERTYPE_IPV6) { sa->sa_family = AF_INET6; ip6_addr_32bit_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &pptrs->bta, 0, 0, 1); ip6_addr_32bit_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &pptrs->bta2, 2, 0, 1); if (pptrs->lookup_bgp_port.set) { ((struct sockaddr_in6 *)sa)->sin6_port = pptrs->lookup_bgp_port.n; compare_bgp_port = TRUE; } } } start_again_follow_default: peer = bms->bgp_lookup_find_peer(sa, xs_entry, pptrs->l3_proto, compare_bgp_port); pptrs->bgp_peer = (char *) peer; if (peer) { struct host_addr peer_dst_ip; memset(&peer_dst_ip, 0, sizeof(peer_dst_ip)); if ((peer->cap_add_paths.cap[AFI_IP][SAFI_UNICAST] || peer->cap_add_paths.cap[AFI_IP6][SAFI_UNICAST]) && (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF)) { /* administrativia */ struct pkt_bgp_primitives pbgp, *pbgp_ptr = &pbgp; memset(&pbgp, 0, sizeof(struct pkt_bgp_primitives)); /* note: call to [NF|SF]_peer_dst_ip_handler for the purpose of code re-use effectively is defeating the concept of libbgp */ if (config.acct_type == ACCT_NF) NF_peer_dst_ip_handler(NULL, pptrs, (char **)&pbgp_ptr); else if (config.acct_type == ACCT_SF) SF_peer_dst_ip_handler(NULL, pptrs, (char **)&pbgp_ptr); memcpy(&peer_dst_ip, &pbgp.peer_dst_ip, sizeof(struct host_addr)); } if (pptrs->bitr) { safi = SAFI_MPLS_VPN; memcpy(&rd, &pptrs->bitr, sizeof(rd)); if (type <= RD_ORIGIN_FUNC_TYPE_MAX) { bgp_rd_origin_set(&rd, lookup_type_to_bgp_rd_origin[type]); } } /* XXX: can be further optimized for the case of no SAFI_UNICAST rib */ start_again_mpls_vpn: start_again_mpls_label: if (pptrs->l3_proto == ETHERTYPE_IP) { if (!pptrs->bgp_src) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.afi = AFI_IP; nmct2.safi = safi; nmct2.rd = &rd; nmct2.peer_dst_ip = NULL; memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][safi], &pref4, (struct bgp_peer *) pptrs->bgp_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, bms->bnv, &result, &info); } if (!pptrs->bgp_src_info && result) { pptrs->bgp_src = (char *) result; pptrs->bgp_src_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_BGP; if (config.rpki_roas_file || config.rpki_rtr_cache) { pptrs->src_roa = rpki_vector_prefix_lookup(bms->bnv); } } } if (!pptrs->bgp_dst) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.afi = AFI_IP; nmct2.safi = safi; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][safi], &pref4, (struct bgp_peer *) pptrs->bgp_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, bms->bnv, &result, &info); } if (!pptrs->bgp_dst_info && result) { pptrs->bgp_dst = (char *) result; pptrs->bgp_dst_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_BGP; if (config.rpki_roas_file || config.rpki_rtr_cache) { pptrs->dst_roa = rpki_vector_prefix_lookup(bms->bnv); } } } } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { if (!pptrs->bgp_src) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.afi = AFI_IP6; nmct2.safi = safi; nmct2.rd = &rd; nmct2.peer_dst_ip = NULL; memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][safi], &pref6, (struct bgp_peer *) pptrs->bgp_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, bms->bnv, &result, &info); } if (!pptrs->bgp_src_info && result) { pptrs->bgp_src = (char *) result; pptrs->bgp_src_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_BGP; if (config.rpki_roas_file || config.rpki_rtr_cache) { pptrs->src_roa = rpki_vector_prefix_lookup(bms->bnv); } } } if (!pptrs->bgp_dst) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.afi = AFI_IP6; nmct2.safi = safi; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][safi], &pref6, (struct bgp_peer *) pptrs->bgp_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, bms->bnv, &result, &info); } if (!pptrs->bgp_dst_info && result) { pptrs->bgp_dst = (char *) result; pptrs->bgp_dst_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_BGP; if (config.rpki_roas_file || config.rpki_rtr_cache) { pptrs->dst_roa = rpki_vector_prefix_lookup(bms->bnv); } } } } /* XXX: tackle the case of Peer Distinguisher from BMP header probably needs deeper thoughts for a cleaner approach */ if ((!pptrs->bgp_src || !pptrs->bgp_dst) && safi == SAFI_MPLS_VPN && type == FUNC_TYPE_BMP) { safi = SAFI_UNICAST; goto start_again_mpls_vpn; } if ((!pptrs->bgp_src || !pptrs->bgp_dst) && safi != SAFI_MPLS_LABEL) { if (pptrs->l3_proto == ETHERTYPE_IP && inter_domain_routing_db->rib[AFI_IP][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } else if (pptrs->l3_proto == ETHERTYPE_IPV6 && inter_domain_routing_db->rib[AFI_IP6][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } } if (follow_default && safi != SAFI_MPLS_VPN) { default_node = NULL; if (pptrs->l3_proto == ETHERTYPE_IP) { memset(&default_prefix, 0, sizeof(default_prefix)); default_prefix.family = AF_INET; result = (struct bgp_node *) pptrs->bgp_src; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_src = NULL; pptrs->bgp_src_info = NULL; } result = (struct bgp_node *) pptrs->bgp_dst; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_dst = NULL; pptrs->bgp_dst_info = NULL; } } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memset(&default_prefix, 0, sizeof(default_prefix)); default_prefix.family = AF_INET6; result = (struct bgp_node *) pptrs->bgp_src; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_src = NULL; pptrs->bgp_src_info = NULL; } result = (struct bgp_node *) pptrs->bgp_dst; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_dst = NULL; pptrs->bgp_dst_info = NULL; } } if (!pptrs->bgp_src || !pptrs->bgp_dst) { follow_default--; compare_bgp_port = FALSE; // XXX: fixme: follow default in NAT traversal scenarios if (default_node) { if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->mp_nexthop.address.ipv4, 4); goto start_again_follow_default; } else if (info->attr->mp_nexthop.family == AF_INET6) { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET6; ip6_addr_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &info->attr->mp_nexthop.address.ipv6); goto start_again_follow_default; } else { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->nexthop, 4); goto start_again_follow_default; } } } } } if (config.bgp_daemon_follow_nexthop[0].family && pptrs->bgp_dst && safi != SAFI_MPLS_VPN) bgp_follow_nexthop_lookup(pptrs, type); } } void bgp_follow_nexthop_lookup(struct packet_ptrs *pptrs, int type) { struct bgp_misc_structs *bms; struct bgp_rt_structs *inter_domain_routing_db; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent, sa_local; struct bgp_peer *nh_peer; struct bgp_node *result_node = NULL; struct bgp_info *info = NULL; struct node_match_cmp_term2 nmct2; char *saved_info = NULL; int peers_idx, ttl = MAX_HOPS_FOLLOW_NH, self = MAX_NH_SELF_REFERENCES; int nh_idx, matched = 0; struct prefix nh, ch; struct in_addr pref4; struct in6_addr pref6; u_char *saved_agent = pptrs->f_agent; pm_id_t bta; u_int32_t modulo, local_modulo, modulo_idx, modulo_max; bms = bgp_select_misc_db(type); inter_domain_routing_db = bgp_select_routing_db(type); if (!bms || !inter_domain_routing_db) return; start_again: if (config.bgp_daemon_to_xflow_agent_map && (*find_id_func)) { bta = 0; (*find_id_func)((struct id_table *)pptrs->bta_table, pptrs, &bta, NULL); if (bta) { sa = &sa_local; sa->sa_family = AF_INET; ((struct sockaddr_in *)sa)->sin_addr.s_addr = bta; } } for (nh_peer = NULL, peers_idx = 0; peers_idx < bms->max_peers; peers_idx++) { if (!sa_addr_cmp(sa, &peers[peers_idx].addr) || (!config.bgp_disable_router_id_check && !sa_addr_cmp(sa, &peers[peers_idx].id))) { nh_peer = &peers[peers_idx]; break; } } if (nh_peer) { modulo = bms->route_info_modulo(nh_peer, NULL, bms->table_per_peer_buckets); // XXX: to be optimized if (bms->table_per_peer_hash == BGP_ASPATH_HASH_PATHID) modulo_max = bms->table_per_peer_buckets; else modulo_max = 1; memset(&ch, 0, sizeof(ch)); ch.family = AF_INET; ch.prefixlen = 32; memcpy(&ch.u.prefix4, &nh_peer->addr.address.ipv4, 4); if (!result_node) { struct host_addr peer_dst_ip; rd_t rd; /* XXX: SAFI_MPLS_LABEL, SAFI_MPLS_VPN and peer_dst_ip (add_paths capability) not supported */ memset(&peer_dst_ip, 0, sizeof(peer_dst_ip)); memset(&rd, 0, sizeof(rd)); memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) nh_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; if (pptrs->l3_proto == ETHERTYPE_IP) { memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][SAFI_UNICAST], &pref4, nh_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, NULL, &result_node, &info); } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][SAFI_UNICAST], &pref6, nh_peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, NULL, &result_node, &info); } } memset(&nh, 0, sizeof(nh)); // XXX: to be optimized if (result_node) { for (local_modulo = modulo, modulo_idx = 0; modulo_idx < modulo_max; local_modulo++, modulo_idx++) { for (info = result_node->info[modulo]; info; info = info->next) { if (info->peer == nh_peer) break; } } } else info = NULL; if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { nh.family = AF_INET; nh.prefixlen = 32; memcpy(&nh.u.prefix4, &info->attr->mp_nexthop.address.ipv4, 4); for (nh_idx = 0; config.bgp_daemon_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.bgp_daemon_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (u_char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->mp_nexthop.address.ipv4, 4); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.bgp_daemon_follow_nexthop_external) saved_info = (char *) info; goto end; } } else if (info->attr->mp_nexthop.family == AF_INET6) { nh.family = AF_INET6; nh.prefixlen = 128; memcpy(&nh.u.prefix6, &info->attr->mp_nexthop.address.ipv6, 16); for (nh_idx = 0; config.bgp_daemon_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.bgp_daemon_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (u_char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET6; ip6_addr_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &info->attr->mp_nexthop.address.ipv6); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.bgp_daemon_follow_nexthop_external) saved_info = (char *) info; goto end; } } else { nh.family = AF_INET; nh.prefixlen = 32; memcpy(&nh.u.prefix4, &info->attr->nexthop, 4); for (nh_idx = 0; config.bgp_daemon_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.bgp_daemon_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (u_char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->nexthop, 4); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.bgp_daemon_follow_nexthop_external) saved_info = (char *) info; goto end; } } } } end: if (saved_info) pptrs->bgp_nexthop_info = saved_info; pptrs->f_agent = saved_agent; } struct bgp_peer *bgp_lookup_find_bgp_peer(struct sockaddr *sa, struct xflow_status_entry *xs_entry, u_int16_t l3_proto, int compare_bgp_port) { struct bgp_peer *peer; u_int32_t peer_idx, *peer_idx_ptr; int peers_idx; peer_idx = 0; peer_idx_ptr = NULL; if (xs_entry) { if (l3_proto == ETHERTYPE_IP) { peer_idx = xs_entry->peer_v4_idx; peer_idx_ptr = &xs_entry->peer_v4_idx; } else if (l3_proto == ETHERTYPE_IPV6) { peer_idx = xs_entry->peer_v6_idx; peer_idx_ptr = &xs_entry->peer_v6_idx; } } if (xs_entry && peer_idx) { if ((!config.bgp_disable_router_id_check && !sa_addr_cmp(sa, &peers[peer_idx].id)) || (!sa_addr_cmp(sa, &peers[peer_idx].addr) && (!compare_bgp_port || !sa_port_cmp(sa, peers[peer_idx].tcp_port)))) { peer = &peers[peer_idx]; } /* If no match then let's invalidate the entry */ else { *peer_idx_ptr = 0; peer = NULL; } } else { for (peer = NULL, peers_idx = 0; peers_idx < config.bgp_daemon_max_peers; peers_idx++) { if ((!config.bgp_disable_router_id_check && !sa_addr_cmp(sa, &peers[peers_idx].id)) || (!sa_addr_cmp(sa, &peers[peers_idx].addr) && (!compare_bgp_port || !sa_port_cmp(sa, peers[peer_idx].tcp_port)))) { peer = &peers[peers_idx]; if (xs_entry && peer_idx_ptr) *peer_idx_ptr = peers_idx; break; } } } return peer; } int bgp_lookup_node_match_cmp_bgp(struct bgp_info *info, struct node_match_cmp_term2 *nmct2) { int no_match = FALSE; if (info->peer == nmct2->peer) { if (nmct2->safi == SAFI_MPLS_VPN) no_match++; if (nmct2->peer->cap_add_paths.cap[nmct2->afi][nmct2->safi] && nmct2->peer_dst_ip) no_match++; if (nmct2->safi == SAFI_MPLS_VPN) { if (info->attr_extra && !memcmp(&info->attr_extra->rd, nmct2->rd, sizeof(rd_t))) no_match--; } if (nmct2->peer->cap_add_paths.cap[nmct2->afi][nmct2->safi]) { if (nmct2->peer_dst_ip && info->attr) { if (info->attr->mp_nexthop.family) { if (!host_addr_cmp(&info->attr->mp_nexthop, nmct2->peer_dst_ip)) { no_match--; } } else if (info->attr->nexthop.s_addr && nmct2->peer_dst_ip->family == AF_INET) { if (info->attr->nexthop.s_addr == nmct2->peer_dst_ip->address.ipv4.s_addr) { no_match--; } } } } if (!no_match) return FALSE; } return TRUE; } int bgp_lookup_node_vector_unicast(struct prefix *p, struct bgp_peer *peer, struct bgp_node_vector *bnv) { struct bgp_rt_structs *inter_domain_routing_db; struct bgp_misc_structs *bms; struct node_match_cmp_term2 nmct2; struct bgp_node *result = NULL; struct bgp_info *info = NULL; afi_t afi; safi_t safi; if (!p || !peer || !bnv) return ERR; bms = bgp_select_misc_db(peer->type); inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!bms || !inter_domain_routing_db) return ERR; afi = family2afi(p->family); safi = SAFI_UNICAST; memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = peer; nmct2.afi = afi; nmct2.safi = safi; nmct2.p = p; bgp_node_match(inter_domain_routing_db->rib[afi][safi], p, peer, bms->route_info_modulo, bms->bgp_lookup_node_match_cmp, &nmct2, bnv, &result, &info); return SUCCESS; } void pkt_to_cache_legacy_bgp_primitives(struct cache_legacy_bgp_primitives *c, struct pkt_legacy_bgp_primitives *p, pm_cfgreg_t what_to_count, pm_cfgreg_t what_to_count_2) { if (c && p) { if (what_to_count & COUNT_STD_COMM) { if (!c->std_comms) { c->std_comms = malloc(MAX_BGP_STD_COMMS); if (!c->std_comms) goto malloc_failed; } memcpy(c->std_comms, p->std_comms, MAX_BGP_STD_COMMS); } else { if (c->std_comms) { free(c->std_comms); c->std_comms = NULL; } } if (what_to_count & COUNT_EXT_COMM) { if (!c->ext_comms) { c->ext_comms = malloc(MAX_BGP_EXT_COMMS); if (!c->ext_comms) goto malloc_failed; } memcpy(c->ext_comms, p->ext_comms, MAX_BGP_EXT_COMMS); } else { if (c->ext_comms) { free(c->ext_comms); c->ext_comms = NULL; } } if (what_to_count_2 & COUNT_LRG_COMM) { if (!c->lrg_comms) { c->lrg_comms = malloc(MAX_BGP_LRG_COMMS); if (!c->lrg_comms) goto malloc_failed; } memcpy(c->lrg_comms, p->lrg_comms, MAX_BGP_LRG_COMMS); } else { if (c->lrg_comms) { free(c->lrg_comms); c->lrg_comms = NULL; } } if (what_to_count & COUNT_AS_PATH) { if (!c->as_path) { c->as_path = malloc(MAX_BGP_ASPATH); if (!c->as_path) goto malloc_failed; } memcpy(c->as_path, p->as_path, MAX_BGP_ASPATH); } else { if (c->as_path) { free(c->as_path); c->as_path = NULL; } } if (what_to_count & COUNT_SRC_STD_COMM) { if (!c->src_std_comms) { c->src_std_comms = malloc(MAX_BGP_STD_COMMS); if (!c->src_std_comms) goto malloc_failed; } memcpy(c->src_std_comms, p->src_std_comms, MAX_BGP_STD_COMMS); } else { if (c->src_std_comms) { free(c->src_std_comms); c->src_std_comms = NULL; } } if (what_to_count & COUNT_SRC_EXT_COMM) { if (!c->src_ext_comms) { c->src_ext_comms = malloc(MAX_BGP_EXT_COMMS); if (!c->src_ext_comms) goto malloc_failed; } memcpy(c->src_ext_comms, p->src_ext_comms, MAX_BGP_EXT_COMMS); } else { if (c->src_ext_comms) { free(c->src_ext_comms); c->src_ext_comms = NULL; } } if (what_to_count_2 & COUNT_SRC_LRG_COMM) { if (!c->src_lrg_comms) { c->src_lrg_comms = malloc(MAX_BGP_LRG_COMMS); if (!c->src_lrg_comms) goto malloc_failed; } memcpy(c->src_lrg_comms, p->src_lrg_comms, MAX_BGP_LRG_COMMS); } else { if (c->src_lrg_comms) { free(c->src_lrg_comms); c->src_lrg_comms = NULL; } } if (what_to_count & COUNT_SRC_AS_PATH) { if (!c->src_as_path) { c->src_as_path = malloc(MAX_BGP_ASPATH); if (!c->src_as_path) goto malloc_failed; } memcpy(c->src_as_path, p->src_as_path, MAX_BGP_ASPATH); } else { if (c->src_as_path) { free(c->src_as_path); c->src_as_path = NULL; } } return; malloc_failed: Log(LOG_WARNING, "WARN ( %s/%s ): malloc() failed (pkt_to_cache_legacy_bgp_primitives).\n", config.name, config.type); } } void cache_to_pkt_legacy_bgp_primitives(struct pkt_legacy_bgp_primitives *p, struct cache_legacy_bgp_primitives *c) { if (c && p) { memset(p, 0, PlbgpSz); if (c->std_comms) memcpy(p->std_comms, c->std_comms, MAX_BGP_STD_COMMS); if (c->ext_comms) memcpy(p->ext_comms, c->ext_comms, MAX_BGP_EXT_COMMS); if (c->lrg_comms) memcpy(p->lrg_comms, c->lrg_comms, MAX_BGP_LRG_COMMS); if (c->as_path) memcpy(p->as_path, c->as_path, MAX_BGP_ASPATH); if (c->src_std_comms) memcpy(p->src_std_comms, c->src_std_comms, MAX_BGP_STD_COMMS); if (c->src_ext_comms) memcpy(p->src_ext_comms, c->src_ext_comms, MAX_BGP_EXT_COMMS); if (c->src_lrg_comms) memcpy(p->src_lrg_comms, c->src_lrg_comms, MAX_BGP_LRG_COMMS); if (c->src_as_path) memcpy(p->src_as_path, c->src_as_path, MAX_BGP_ASPATH); } } void free_cache_legacy_bgp_primitives(struct cache_legacy_bgp_primitives **c) { struct cache_legacy_bgp_primitives *clbgp = *c; if (c && *c) { if (clbgp->std_comms) free(clbgp->std_comms); if (clbgp->ext_comms) free(clbgp->ext_comms); if (clbgp->lrg_comms) free(clbgp->lrg_comms); if (clbgp->as_path) free(clbgp->as_path); if (clbgp->src_std_comms) free(clbgp->src_std_comms); if (clbgp->src_ext_comms) free(clbgp->src_ext_comms); if (clbgp->src_lrg_comms) free(clbgp->src_lrg_comms); if (clbgp->src_as_path) free(clbgp->src_as_path); memset(clbgp, 0, sizeof(struct cache_legacy_bgp_primitives)); free(*c); *c = NULL; } } u_int32_t bgp_route_info_modulo_pathid(struct bgp_peer *peer, path_id_t *path_id, int per_peer_buckets) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); path_id_t local_path_id = 1; if (path_id && *path_id) local_path_id = *path_id; return (((peer->fd * per_peer_buckets) + ((local_path_id - 1) % per_peer_buckets)) % (bms->table_peer_buckets * per_peer_buckets)); } int bgp_lg_daemon_ip_lookup(struct bgp_lg_req_ipl_data *req, struct bgp_lg_rep *rep, int type) { struct bgp_misc_structs *bms; struct bgp_rt_structs *inter_domain_routing_db; struct bgp_peer *peer; struct bgp_node *result; struct bgp_info *info; struct node_match_cmp_term2 nmct2; struct host_addr peer_ha; u_int16_t l3_proto = 0, peer_port = 0; u_int32_t bucket; int ret = BGP_LOOKUP_OK; struct rd_as4 *rd_as4_ptr; safi_t safi; bms = bgp_select_misc_db(type); inter_domain_routing_db = bgp_select_routing_db(type); if (!req || !rep || !bms || !inter_domain_routing_db) return BGP_LOOKUP_ERR; memset(&peer_ha, 0, sizeof(peer_ha)); memset(rep, 0, sizeof(struct bgp_lg_rep)); safi = SAFI_UNICAST; if (req->pref.family == AF_INET) l3_proto = ETHERTYPE_IP; else if (req->pref.family == AF_INET6) l3_proto = ETHERTYPE_IPV6; sa_to_addr(&req->peer, &peer_ha, &peer_port); if (!peer_port) { bucket = addr_hash(&peer_ha, bms->max_peers); peer = bgp_peer_cache_search(bms->peers_cache, bucket, &peer_ha, FALSE); } else { bucket = addr_port_hash(&peer_ha, peer_port, bms->max_peers); peer = bgp_peer_cache_search(bms->peers_port_cache, bucket, &peer_ha, peer_port); } if (peer) { // XXX: ADD-PATH code not currently supported rd_as4_ptr = (struct rd_as4 *) &req->rd; if (rd_as4_ptr->as) safi = SAFI_MPLS_VPN; start_again_mpls_label: memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = peer; nmct2.afi = AFI_IP; nmct2.safi = safi; nmct2.rd = &req->rd; if (l3_proto == ETHERTYPE_IP) { bgp_node_match(inter_domain_routing_db->rib[AFI_IP][safi], &req->pref, peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, NULL, &result, &info); if (result) { bgp_lg_rep_ipl_data_add(rep, AFI_IP, safi, &result->p, info); ret = BGP_LOOKUP_OK; } else ret = BGP_LOOKUP_NOPREFIX; } else if (l3_proto == ETHERTYPE_IPV6) { bgp_node_match(inter_domain_routing_db->rib[AFI_IP6][safi], &req->pref, peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, NULL, &result, &info); if (result) { bgp_lg_rep_ipl_data_add(rep, AFI_IP6, safi, &result->p, info); ret = BGP_LOOKUP_OK; } else ret = BGP_LOOKUP_NOPREFIX; } if (!result && safi != SAFI_MPLS_LABEL) { if (l3_proto == ETHERTYPE_IP && inter_domain_routing_db->rib[AFI_IP][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } else if (l3_proto == ETHERTYPE_IPV6 && inter_domain_routing_db->rib[AFI_IP6][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } } // XXX: bgp_follow_default code not currently supported } else ret = BGP_LOOKUP_NOPEER; return ret; } int bgp_lg_daemon_get_peers(struct bgp_lg_rep *rep, int type) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *peers; int idx, ret = BGP_LOOKUP_OK; bms = bgp_select_misc_db(type); if (!rep || !bms || !bms->peers) return BGP_LOOKUP_ERR; for (peers = bms->peers, idx = 0; idx < bms->max_peers; idx++) { peer = &peers[idx]; if (peer->fd) bgp_lg_rep_gp_data_add(rep, peer); } return ret; } void bgp_lg_rep_init(struct bgp_lg_rep *rep) { struct bgp_lg_rep_data *data, *next; u_int32_t idx; assert(rep); for (idx = 0, data = rep->data; idx < rep->results; idx++) { assert(data); assert(data->ptr); next = data->next; free(data->ptr); free(data); data = next; } memset(rep, 0, sizeof(struct bgp_lg_rep)); } struct bgp_lg_rep_data *bgp_lg_rep_data_add(struct bgp_lg_rep *rep) { struct bgp_lg_rep_data *data, *last; u_int32_t idx; assert(rep); for (idx = 0, data = rep->data, last = NULL; idx < rep->results; idx++) { last = data; data = data->next; } data = malloc(sizeof(struct bgp_lg_rep_data)); assert(data); data->ptr = NULL; data->next = NULL; if (last) last->next = data; else rep->data = data; rep->results++; return data; } void bgp_lg_rep_ipl_data_add(struct bgp_lg_rep *rep, afi_t afi, safi_t safi, struct prefix *pref, struct bgp_info *info) { struct bgp_lg_rep_data *data; struct bgp_lg_rep_ipl_data *ipl_data; data = bgp_lg_rep_data_add(rep); ipl_data = malloc(sizeof(struct bgp_lg_rep_ipl_data)); assert(ipl_data); data->ptr = ipl_data; ipl_data->afi = afi; ipl_data->safi = safi; ipl_data->pref = pref; ipl_data->info = info; } void bgp_lg_rep_gp_data_add(struct bgp_lg_rep *rep, struct bgp_peer *peer) { struct bgp_lg_rep_data *data; struct bgp_lg_rep_gp_data *gp_data; data = bgp_lg_rep_data_add(rep); gp_data = malloc(sizeof(struct bgp_lg_rep_gp_data)); assert(gp_data); data->ptr = gp_data; gp_data->peer = peer; } pmacct-1.7.8/src/bgp/bgp_blackhole.h0000644000175000017500000000374414354105275016306 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_BLACKHOLE_H_ #define _BGP_BLACKHOLE_H_ /* defines */ #define BGP_BLACKHOLE_DEFAULT_BF_ENTRIES 1000 #define BGP_BLACKHOLE_STATE_UNKNOWN 0 #define BGP_BLACKHOLE_STATE_VALID 1 #define BGP_BLACKHOLE_STATE_INVALID 2 /* structs */ struct bgp_blackhole_itc { struct bgp_peer *peer; afi_t afi; safi_t safi; struct prefix *p; struct bgp_attr *attr; }; /* prototypes */ extern void bgp_blackhole_daemon_wrapper(); #if defined WITH_ZMQ extern void bgp_blackhole_prepare_thread(); extern void bgp_blackhole_init_dummy_peer(struct bgp_peer *); extern void bgp_blackhole_prepare_filter(); extern int bgp_blackhole_daemon(); extern int bgp_blackhole_evaluate_comms(void *); extern int bgp_blackhole_instrument(struct bgp_peer *, struct prefix *, void *, afi_t, safi_t); extern int bgp_blackhole_validate(struct prefix *, struct bgp_peer *, struct bgp_attr *, struct bgp_node_vector *); #endif /* global variables */ extern struct bgp_rt_structs *bgp_blackhole_db; extern struct bgp_misc_structs *bgp_blackhole_misc_db; extern struct bgp_peer bgp_blackhole_peer; extern struct bloom *bgp_blackhole_filter; extern struct community *bgp_blackhole_comms; #endif pmacct-1.7.8/src/bgp/bgp_ecommunity.h0000644000175000017500000000551114354105275016545 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on Quagga BGP extended community attribute related functions which is: Copyright (C) 2000 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_ECOMMUNITY_H_ #define _BGP_ECOMMUNITY_H_ /* High-order octet of the Extended Communities type field. */ #define ECOMMUNITY_ENCODE_AS 0x00 #define ECOMMUNITY_ENCODE_IP 0x01 #define ECOMMUNITY_ENCODE_AS4 0x02 /* Low-order octet of the Extended Communityes type field. */ #define ECOMMUNITY_ROUTE_TARGET 0x02 #define ECOMMUNITY_SITE_ORIGIN 0x03 /* Extended communities attribute string format. */ #define ECOMMUNITY_FORMAT_ROUTE_MAP 0 #define ECOMMUNITY_FORMAT_COMMUNITY_LIST 1 #define ECOMMUNITY_FORMAT_DISPLAY 2 /* Extended Communities value is eight octet long. */ #define ECOMMUNITY_SIZE 8 /* Extended Communities type flag. */ #define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40 /* Extended Communities attribute. */ struct ecommunity { /* Reference counter. */ unsigned long refcnt; /* Size of Extended Communities attribute. */ int size; /* Extended Communities value. */ u_int8_t *val; /* Human readable format string. */ char *str; }; /* Extended community value is eight octet. */ struct ecommunity_val { char val[ECOMMUNITY_SIZE]; }; #define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE) extern void ecommunity_init (int, struct hash **); extern void ecommunity_free (struct ecommunity *); extern struct ecommunity *ecommunity_new (struct bgp_peer *); extern struct ecommunity *ecommunity_parse (struct bgp_peer *, u_int8_t *, u_short); extern struct ecommunity *ecommunity_intern (struct bgp_peer *, struct ecommunity *); extern int ecommunity_cmp (const void *, const void *); extern void ecommunity_unintern (struct bgp_peer *, struct ecommunity *); extern unsigned int ecommunity_hash_make (void *); extern char *ecommunity_ecom2str (struct bgp_peer *, struct ecommunity *, int); extern struct ecommunity *ecommunity_dup(struct ecommunity *); #endif pmacct-1.7.8/src/bgp/bgp_community.c0000644000175000017500000002540614354105275016400 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on Quagga BGP community attribute related functions which is: Copyright (C) 1998, 2001 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "bgp.h" /* Allocate a new communities value. */ struct community *community_new (struct bgp_peer *peer) { struct bgp_misc_structs *bms; void *tmp; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; tmp = malloc(sizeof (struct community)); if (!tmp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (community_new). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } memset(tmp, 0, sizeof (struct community)); return (struct community *) tmp; } /* Free communities value. */ void community_free (struct community *com) { if (com->val) free(com->val); if (com->str) free(com->str); free(com); } /* Add one community value to the community. */ void community_add_val (struct bgp_peer *peer, struct community *com, u_int32_t val) { struct bgp_misc_structs *bms; if (!peer) return; bms = bgp_select_misc_db(peer->type); if (!bms) return; com->size++; if (com->val) com->val = realloc(com->val, com_length (com)); else { com->val = malloc(com_length (com)); if (!com->val) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (community_add_val). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } } val = htonl (val); memcpy (com_lastval (com), &val, sizeof (u_int32_t)); } /* Delete one community. */ void community_del_val (struct community *com, u_int32_t *val) { int i = 0; int c = 0; if (! com->val) return; while (i < com->size) { if (memcmp (com->val + i, val, sizeof (u_int32_t)) == 0) { c = com->size -i -1; if (c > 0) memcpy (com->val + i, com->val + (i + 1), c * sizeof (val)); com->size--; if (com->size > 0) com->val = realloc(com->val, com_length (com)); else { free(com->val); com->val = NULL; } return; } i++; } } /* Delete all communities listed in com2 from com1 */ struct community * community_delete (struct community *com1, struct community *com2) { int i = 0; while(i < com2->size) { community_del_val (com1, com2->val + i); i++; } return com1; } /* Callback function from qsort(). */ int community_compare (const void *a1, const void *a2) { u_int32_t v1; u_int32_t v2; memcpy (&v1, a1, sizeof (u_int32_t)); memcpy (&v2, a2, sizeof (u_int32_t)); v1 = ntohl (v1); v2 = ntohl (v2); if (v1 < v2) return -1; if (v1 > v2) return 1; return 0; } int community_include (struct community *com, u_int32_t val) { int i; val = htonl (val); for (i = 0; i < com->size; i++) if (memcmp (&val, com_nthval (com, i), sizeof (u_int32_t)) == 0) return 1; return 0; } u_int32_t community_val_get(struct community *com, int i) { u_char *p; u_int32_t val; p = (u_char *) com->val; p += (i * 4); memcpy (&val, p, sizeof (u_int32_t)); return ntohl (val); } /* Sort and uniq given community. */ struct community * community_uniq_sort (struct bgp_peer *peer, struct community *com) { int i; struct community *new; u_int32_t val; if (! com) return NULL; new = community_new (peer); for (i = 0; i < com->size; i++) { val = community_val_get (com, i); if (! community_include (new, val)) community_add_val (peer, new, val); } qsort (new->val, new->size, sizeof (u_int32_t), community_compare); return new; } /* Convert communities attribute to string. For Well-known communities value, below keyword is used. 0x0 "internet" 0xFFFFFF01 "no-export" 0xFFFFFF02 "no-advertise" 0xFFFFFF03 "local-AS" For other values, "AS:VAL" format is used. */ static char * community_com2str (struct bgp_peer *peer, struct community *com) { struct bgp_misc_structs *bms; int i; char *str; char *pnt; int len; int first; u_int32_t comval; u_int16_t as; u_int16_t val; if (!com || !peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; /* When communities attribute is empty. */ if (com->size == 0) { str = malloc(1); if (!str) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (community_com2str). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } str[0] = '\0'; return str; } /* Memory allocation is time consuming work. So we calculate required string length first. */ len = 0; for (i = 0; i < com->size; i++) { memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); comval = ntohl (comval); switch (comval) { case COMMUNITY_INTERNET: len += strlen (" internet"); break; case COMMUNITY_NO_EXPORT: len += strlen (" no-export"); break; case COMMUNITY_NO_ADVERTISE: len += strlen (" no-advertise"); break; case COMMUNITY_LOCAL_AS: len += strlen (" local-AS"); break; default: len += strlen (" 65536:65535"); break; } } /* Allocate memory. */ str = pnt = malloc(len); if (!str) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (community_com2str). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } first = 1; /* Fill in string. */ for (i = 0; i < com->size; i++) { memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); comval = ntohl (comval); if (first) first = 0; else *pnt++ = ' '; switch (comval) { case COMMUNITY_INTERNET: strcpy (pnt, "internet"); pnt += strlen ("internet"); break; case COMMUNITY_NO_EXPORT: strcpy (pnt, "no-export"); pnt += strlen ("no-export"); break; case COMMUNITY_NO_ADVERTISE: strcpy (pnt, "no-advertise"); pnt += strlen ("no-advertise"); break; case COMMUNITY_LOCAL_AS: strcpy (pnt, "local-AS"); pnt += strlen ("local-AS"); break; default: as = (comval >> 16) & 0xFFFF; val = comval & 0xFFFF; sprintf (pnt, "%d:%d", as, val); pnt += strlen (pnt); break; } } *pnt = '\0'; return str; } /* Intern communities attribute. */ struct community * community_intern (struct bgp_peer *peer, struct community *com) { struct bgp_rt_structs *inter_domain_routing_db; struct community *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; /* Assert this community structure is not interned. */ assert (com->refcnt == 0); /* Lookup community hash. */ find = (struct community *) hash_get(peer, inter_domain_routing_db->comhash, com, hash_alloc_intern); /* Arguemnt com is allocated temporary. So when it is not used in hash, it should be freed. */ if (find != com) community_free (com); /* Increment refrence counter. */ find->refcnt++; /* Make string. */ if (! find->str) find->str = community_com2str (peer, find); return find; } /* Free community attribute. */ void community_unintern (struct bgp_peer *peer, struct community *com) { struct bgp_rt_structs *inter_domain_routing_db; struct community *ret = NULL; (void) ret; if (!peer) return; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return; if (com->refcnt) com->refcnt--; /* Pull off from hash. */ if (com->refcnt == 0) { /* Community value com must exist in hash. */ ret = (struct community *) hash_release(inter_domain_routing_db->comhash, com); assert (ret != NULL); community_free (com); } } /* Create new community attribute. */ struct community * community_parse (struct bgp_peer *peer, u_int32_t *pnt, u_short length) { struct community tmp; struct community *new; /* If length is malformed return NULL. */ if (length % 4) return NULL; /* Make temporary community for hash look up. */ tmp.size = length / 4; tmp.val = pnt; new = community_uniq_sort (peer, &tmp); return community_intern (peer, new); } /* Make hash value of community attribute. This function is used by hash package.*/ unsigned int community_hash_make (struct community *com) { int c; unsigned int key; unsigned char *pnt; key = 0; pnt = (unsigned char *)com->val; for(c = 0; c < com->size * 4; c++) key += pnt[c]; return key; } /* If two aspath have same value then return 1 else return 0. This function is used by hash package. */ int community_cmp (const struct community *com1, const struct community *com2) { if (com1 == NULL && com2 == NULL) return 1; if (com1 == NULL || com2 == NULL) return 0; if (com1->size == com2->size) if (memcmp (com1->val, com2->val, com1->size * 4) == 0) return 1; return 0; } /* Initialize comminity related hash. */ void community_init (int buckets, struct hash **loc_comhash) { (*loc_comhash) = hash_create (buckets, (unsigned int (*) (void *))community_hash_make, (int (*) (const void *, const void *))community_cmp); } int community_str2com_simple(const char *buf, u_int32_t *val) { const char *p = buf; /* Skip white space. */ while (isspace ((int) (*p))) p++; /* Check the end of the line. */ if (*p == '\0') return ERR; /* Community value. */ if (isdigit ((int) (*p))) { int separator = 0; int digit = 0; u_int32_t community_low = 0; u_int32_t community_high = 0; while (isdigit ((int) (*p)) || (*p) == ':') { if ((*p) == ':') { if (separator) return ERR; else { separator = TRUE; digit = FALSE; community_high = community_low << 16; community_low = 0; } } else { digit = TRUE; community_low *= 10; community_low += (*p - '0'); } p++; } if (!digit) return ERR; (*val) = community_high + community_low; return FALSE; } return ERR; } struct community *community_dup(struct community *com) { struct community *new; new = malloc(sizeof(struct community)); new->size = com->size; if (new->size) { new->val = malloc(com->size * 4); memcpy(new->val, com->val, com->size * 4); } else new->val = NULL; return new; } pmacct-1.7.8/src/bgp/bgp_prefix.c0000644000175000017500000003363714354105275015656 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* * Originally based on Quagga prefix related functions which is: * * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "bgp_packet.h" #include "bgp_prefix.h" /* Maskbit. */ static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; /* Number of bits in prefix type. */ #ifndef PNBBY #define PNBBY 8 #endif /* PNBBY */ #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) /* Address Famiy Identifier to Address Family converter. */ int afi2family (int afi) { if (afi == AFI_IP) return AF_INET; else if (afi == AFI_IP6) return AF_INET6; return 0; } int family2afi (int family) { if (family == AF_INET) return AFI_IP; else if (family == AF_INET6) return AFI_IP6; return 0; } /* If n includes p prefix then return 1 else return 0. */ int prefix_match (const struct prefix *n, const struct prefix *p) { int offset; int shift; /* Set both prefix's head pointer. */ const u_char *np = (const u_char *)&n->u.prefix; const u_char *pp = (const u_char *)&p->u.prefix; /* If n's prefix is longer than p's one return 0. */ if (n->prefixlen > p->prefixlen) return 0; offset = n->prefixlen / PNBBY; shift = n->prefixlen % PNBBY; if (shift) if (maskbit[shift] & (np[offset] ^ pp[offset])) return 0; while (offset--) if (np[offset] != pp[offset]) return 0; return 1; } /* Copy prefix from src to dest. */ void prefix_copy (struct prefix *dest, const struct prefix *src) { dest->family = src->family; dest->prefixlen = src->prefixlen; if (src->family == AF_INET) dest->u.prefix4 = src->u.prefix4; else if (src->family == AF_INET6) dest->u.prefix6 = src->u.prefix6; // XXX: "else if (src->family == AF_UNSPEC)" case // XXX: "else" case } /* * Return 1 if the address/netmask contained in the prefix structure * is the same, and else return 0. For this routine, 'same' requires * that not only the prefix length and the network part be the same, * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not * the same. Note that this routine has the same return value sense * as '==' (which is different from prefix_cmp). */ int prefix_same (const struct prefix *p1, const struct prefix *p2) { if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) { if (p1->family == AF_INET) if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) return 1; if (p1->family == AF_INET6 ) if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) return 1; } return 0; } /* * Return 0 if the network prefixes represented by the struct prefix * arguments are the same prefix, and 1 otherwise. Network prefixes * are considered the same if the prefix lengths are equal and the * network parts are the same. Host bits (which are considered masked * by the prefix length) are not significant. Thus, 10.0.0.1/8 and * 10.0.0.2/8 are considered equivalent by this routine. Note that * this routine has the same return sense as strcmp (which is different * from prefix_same). */ int prefix_cmp (const struct prefix *p1, const struct prefix *p2) { int offset; int shift; /* Set both prefix's head pointer. */ const u_char *pp1 = (const u_char *)&p1->u.prefix; const u_char *pp2 = (const u_char *)&p2->u.prefix; if (p1->family != p2->family || p1->prefixlen != p2->prefixlen) return 1; offset = p1->prefixlen / 8; shift = p1->prefixlen % 8; if (shift) if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) return 1; while (offset--) if (pp1[offset] != pp2[offset]) return 1; return 0; } /* Return prefix family type string. */ const char * prefix_family_str (const struct prefix *p) { if (p->family == AF_INET) return "inet"; if (p->family == AF_INET6) return "inet6"; return "unspec"; } /* Allocate new prefix_ipv4 structure. */ struct prefix_ipv4 * prefix_ipv4_new () { struct prefix_ipv4 *p; /* Call prefix_new to allocate a full-size struct prefix to avoid problems where the struct prefix_ipv4 is cast to struct prefix and unallocated bytes were being referenced (e.g. in structure assignments). */ p = (struct prefix_ipv4 *)prefix_new(); p->family = AF_INET; return p; } /* Free prefix_ipv4 structure. */ void prefix_ipv4_free (struct prefix_ipv4 *p) { prefix_free((struct prefix *)p); } /* When string format is invalid return 0. */ int str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) { int ret; int plen; char *pnt; char *cp; /* Find slash inside string. */ pnt = strchr (str, '/'); /* String doesn't contail slash. */ if (pnt == NULL) { /* Convert string to prefix. */ ret = inet_aton (str, &p->prefix); if (ret == 0) return 0; /* If address doesn't contain slash we assume it host address. */ p->family = AF_INET; p->prefixlen = IPV4_MAX_BITLEN; return ret; } else { cp = malloc ((pnt - str) + 1); if (!cp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (str2prefix_ipv4). Exiting ..\n", config.name, config.type); exit_gracefully(1); } strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_aton (cp, &p->prefix); free (cp); /* Get prefix length. */ plen = (u_char) atoi (++pnt); if (plen > IPV4_MAX_PREFIXLEN) return 0; p->family = AF_INET; p->prefixlen = plen; } return ret; } /* Convert masklen into IP address's netmask. */ void masklen2ip (int masklen, struct in_addr *netmask) { u_char *pnt; int bit; int offset; memset (netmask, 0, sizeof (struct in_addr)); pnt = (unsigned char *) netmask; offset = masklen / 8; bit = masklen % 8; while (offset--) *pnt++ = 0xff; if (bit) *pnt = maskbit[bit]; } /* Convert IP address's netmask into integer. We assume netmask is sequential one. Argument netmask should be network byte order. */ u_char ip_masklen (struct in_addr netmask) { u_char len; u_char *pnt; u_char *end; u_char val; len = 0; pnt = (u_char *) &netmask; end = pnt + 4; while ((pnt < end) && (*pnt == 0xff)) { len+= 8; pnt++; } if (pnt < end) { val = *pnt; while (val) { len++; val <<= 1; } } return len; } /* Apply mask to IPv4 prefix. */ void apply_mask_ipv4 (struct prefix_ipv4 *p) { u_char *pnt; int index; int offset; index = p->prefixlen / 8; if (index < 4) { pnt = (u_char *) &p->prefix; offset = p->prefixlen % 8; pnt[index] &= maskbit[offset]; index++; while (index < 4) pnt[index++] = 0; } } /* If prefix is 0.0.0.0/0 then return 1 else return 0. */ int prefix_ipv4_any (const struct prefix_ipv4 *p) { return (p->prefix.s_addr == 0 && p->prefixlen == 0); } /* Allocate a new ip version 6 route */ struct prefix_ipv6 * prefix_ipv6_new (void) { struct prefix_ipv6 *p; /* Allocate a full-size struct prefix to avoid problems with structure size mismatches. */ p = (struct prefix_ipv6 *)prefix_new(); p->family = AF_INET6; return p; } /* Free prefix for IPv6. */ void prefix_ipv6_free (struct prefix_ipv6 *p) { prefix_free((struct prefix *)p); } /* If given string is valid return pin6 else return NULL */ int str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) { char *pnt; char *cp; int ret; pnt = strchr (str, '/'); /* If string doesn't contain `/' treat it as host route. */ if (pnt == NULL) { ret = inet_pton (AF_INET6, str, &p->prefix); if (ret != 1) return 0; p->prefixlen = IPV6_MAX_BITLEN; } else { int plen; cp = malloc((pnt - str) + 1); if (!cp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (str2prefix_ipv6). Exiting ..\n", config.name, config.type); exit_gracefully(1); } strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_pton (AF_INET6, cp, &p->prefix); free (cp); if (ret != 1) return 0; plen = (u_char) atoi (++pnt); if (plen > 128) return 0; p->prefixlen = plen; } p->family = AF_INET6; return ret; } /* Convert struct in6_addr netmask into integer. * FIXME return u_char as ip_maskleni() does. */ int ip6_masklen (struct in6_addr netmask) { int len = 0; unsigned char val; unsigned char *pnt; pnt = (unsigned char *) & netmask; while ((*pnt == 0xff) && len < 128) { len += 8; pnt++; } if (len < 128) { val = *pnt; while (val) { len++; val <<= 1; } } return len; } void masklen2ip6 (int masklen, struct in6_addr *netmask) { unsigned char *pnt; int bit; int offset; memset (netmask, 0, sizeof (struct in6_addr)); pnt = (unsigned char *) netmask; offset = masklen / 8; bit = masklen % 8; while (offset--) *pnt++ = 0xff; if (bit) *pnt = maskbit[bit]; } void apply_mask_ipv6 (struct prefix_ipv6 *p) { u_char *pnt; int index; int offset; index = p->prefixlen / 8; if (index < 16) { pnt = (u_char *) &p->prefix; offset = p->prefixlen % 8; pnt[index] &= maskbit[offset]; index++; while (index < 16) pnt[index++] = 0; } } void str2in6_addr (const char *str, struct in6_addr *addr) { int i; unsigned int x; /* %x must point to unsinged int */ for (i = 0; i < 16; i++) { sscanf (str + (i * 2), "%02x", &x); addr->s6_addr[i] = x & 0xff; } } void apply_mask (struct prefix *p) { switch (p->family) { case AF_INET: apply_mask_ipv4 ((struct prefix_ipv4 *)p); break; case AF_INET6: apply_mask_ipv6 ((struct prefix_ipv6 *)p); break; default: break; } return; } int prefix_blen (const struct prefix *p) { switch (p->family) { case AF_INET: return IPV4_MAX_BYTELEN; break; case AF_INET6: return IPV6_MAX_BYTELEN; break; } return 0; } /* Generic function for conversion string to struct prefix. */ int str2prefix (const char *str, struct prefix *p) { int ret; /* First we try to convert string to struct prefix_ipv4. */ ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p); if (ret) return ret; /* Next we try to convert string to struct prefix_ipv6. */ ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p); if (ret) return ret; return 0; } int prefix2str (const struct prefix *p, char *str, int size) { char buf[BUFSIZ]; inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); snprintf (str, size, "%s/%d", buf, p->prefixlen); return 0; } struct prefix * prefix_new () { struct prefix *p; p = malloc (sizeof *p); if (!p) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (prefix_new). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memset(p, 0, sizeof *p); return p; } /* Free prefix structure. */ void prefix_free (struct prefix *p) { free (p); } /* Utility function. Check the string only contains digit * character. * FIXME str.[c|h] would be better place for this function. */ int all_digit (const char *str) { for (; *str != '\0'; str++) if (!isdigit ((int) *str)) return 0; return 1; } /* Utility function to convert ipv4 prefixes to Classful prefixes */ void apply_classful_mask_ipv4 (struct prefix_ipv4 *p) { u_int32_t destination; destination = ntohl (p->prefix.s_addr); if (p->prefixlen == IPV4_MAX_PREFIXLEN); /* do nothing for host routes */ else if (IN_CLASSC (destination)) { p->prefixlen=24; apply_mask_ipv4(p); } else if (IN_CLASSB(destination)) { p->prefixlen=16; apply_mask_ipv4(p); } else { p->prefixlen=8; apply_mask_ipv4(p); } } in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen) { struct in_addr mask; masklen2ip (masklen, &mask); return hostaddr & mask.s_addr; } in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen) { struct in_addr mask; masklen2ip (masklen, &mask); return (masklen != IPV4_MAX_PREFIXLEN-1) ? /* normal case */ (hostaddr | ~mask.s_addr) : /* special case for /31 */ (hostaddr ^ ~mask.s_addr); } /* Utility function to convert ipv4 netmask to prefixes ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ int netmask_str2prefix_str (const char *net_str, const char *mask_str, char *prefix_str) { struct in_addr network; struct in_addr mask; u_char prefixlen; u_int32_t destination; int ret; ret = inet_aton (net_str, &network); if (! ret) return 0; if (mask_str) { ret = inet_aton (mask_str, &mask); if (! ret) return 0; prefixlen = ip_masklen (mask); } else { destination = ntohl (network.s_addr); if (network.s_addr == 0) prefixlen = 0; else if (IN_CLASSC (destination)) prefixlen = 24; else if (IN_CLASSB (destination)) prefixlen = 16; else if (IN_CLASSA (destination)) prefixlen = 8; else return 0; } sprintf (prefix_str, "%s/%d", net_str, prefixlen); return 1; } /* Utility function for making IPv6 address string. */ const char * inet6_ntoa (struct in6_addr addr) { static char buf[INET6_ADDRSTRLEN]; inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN); return buf; } pmacct-1.7.8/src/bgp/bgp_table.c0000644000175000017500000003274214354105275015444 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* Originally based on Quagga BGP routing table which is: Copyright (C) 1998, 2001 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp.h" static void bgp_node_delete (struct bgp_peer *, struct bgp_node *); static struct bgp_node *bgp_node_create (struct bgp_peer *); static struct bgp_node *bgp_node_set (struct bgp_peer *, struct bgp_table *, struct prefix *); static void bgp_node_free (struct bgp_node *); static void route_common (struct prefix *, struct prefix *, struct prefix *); static int check_bit (u_char *, u_char); static void set_link (struct bgp_node *, struct bgp_node *); struct bgp_table * bgp_table_init (afi_t afi, safi_t safi) { struct bgp_table *rt; rt = malloc (sizeof (struct bgp_table)); if (rt) { memset (rt, 0, sizeof (struct bgp_table)); rt->afi = afi; rt->safi = safi; } else { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (bgp_table_init). Exiting ..\n", config.name); // XXX exit_gracefully(1); } return rt; } static struct bgp_node * bgp_node_create (struct bgp_peer *peer) { struct bgp_misc_structs *bms; struct bgp_node *rn; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; rn = (struct bgp_node *) malloc (sizeof (struct bgp_node)); if (rn) { memset (rn, 0, sizeof (struct bgp_node)); rn->info = (void **) malloc(sizeof(struct bgp_info *) * (bms->table_peer_buckets * bms->table_per_peer_buckets)); if (rn->info) memset (rn->info, 0, sizeof(struct bgp_info *) * (bms->table_peer_buckets * bms->table_per_peer_buckets)); else goto malloc_failed; } else goto malloc_failed; return rn; malloc_failed: Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_node_create). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); return NULL; /* silence compiler warning */ } /* Allocate new route node with prefix set. */ static struct bgp_node * bgp_node_set (struct bgp_peer *peer, struct bgp_table *table, struct prefix *prefix) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); (void)bms; struct bgp_node *node; node = bgp_node_create (peer); prefix_copy (&node->p, prefix); node->table = table; return node; } /* Free route node. */ static void bgp_node_free (struct bgp_node *node) { if (node->info) { free (node->info); node->info = NULL; } free (node); } /* Utility mask array. */ static u_char maskbit[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; /* Common prefix route genaration. */ static void route_common (struct prefix *n, struct prefix *p, struct prefix *new) { int i; u_char diff; u_char mask; u_char *np = (u_char *)&n->u.prefix; u_char *pp = (u_char *)&p->u.prefix; u_char *newp = (u_char *)&new->u.prefix; for (i = 0; i < p->prefixlen / 8; i++) { if (np[i] == pp[i]) newp[i] = np[i]; else break; } new->prefixlen = i * 8; if (new->prefixlen != p->prefixlen) { diff = np[i] ^ pp[i]; mask = 0x80; while (new->prefixlen < p->prefixlen && !(mask & diff)) { mask >>= 1; new->prefixlen++; } newp[i] = np[i] & maskbit[new->prefixlen % 8]; } } /* Macro version of check_bit (). */ #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1) /* Check bit of the prefix. */ static int check_bit (u_char *prefix, u_char prefixlen) { int offset; int shift; u_char *p = (u_char *)prefix; assert (prefixlen <= 128); offset = prefixlen / 8; shift = 7 - (prefixlen % 8); return (p[offset] >> shift & 1); } /* Macro version of set_link (). */ #define SET_LINK(X,Y) (X)->link[CHECK_BIT(&(Y)->prefix,(X)->prefixlen)] = (Y);\ (Y)->parent = (X) static void set_link (struct bgp_node *node, struct bgp_node *new) { int bit; bit = check_bit (&new->p.u.prefix, node->p.prefixlen); assert (bit == 0 || bit == 1); node->link[bit] = new; new->parent = node; } /* Lock node. */ struct bgp_node * bgp_lock_node (struct bgp_peer *peer, struct bgp_node *node) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); assert(bms); if (!bms->is_readonly) { node->lock++; } return node; } /* Unlock node. */ void bgp_unlock_node (struct bgp_peer *peer, struct bgp_node *node) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); assert(bms); if (!bms->is_readonly) { node->lock--; if (node->lock == 0) { bgp_node_delete (peer, node); } } } void bgp_node_vector_debug(struct bgp_node_vector *bnv, struct prefix *p) { char prefix_str[PREFIX_STRLEN]; int idx; if (bnv && p) { memset(prefix_str, 0, PREFIX_STRLEN); prefix2str(p, prefix_str, PREFIX_STRLEN); Log(LOG_DEBUG, "DEBUG ( %s/core/BGP ): bgp_node_vector_debug(): levels=%u lookup=%s\n", config.name, bnv->entries, prefix_str); for (idx = 0; idx < bnv->entries; idx++) { memset(prefix_str, 0, PREFIX_STRLEN); prefix2str(bnv->v[idx].p, prefix_str, PREFIX_STRLEN); Log(LOG_DEBUG, "DEBUG ( %s/core/BGP ): bgp_node_vector_debug(): level=%u prefix=%s\n", config.name, idx, prefix_str); } } } /* Find matched prefix. */ void bgp_node_match (const struct bgp_table *table, struct prefix *p, struct bgp_peer *peer, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *nmct2, struct bgp_node_vector *bnv, struct bgp_node **result_node, struct bgp_info **result_info) { struct bgp_misc_structs *bms; struct bgp_node *node, *matched_node; struct bgp_info *info, *matched_info; u_int32_t modulo, modulo_idx, local_modulo, modulo_max; if (!table || !peer || !cmp_func) return; bms = bgp_select_misc_db(peer->type); if (!bms) return; /* XXX: see https://github.com/pmacct/pmacct/pull/78 */ if (bms->table_per_peer_hash == BGP_ASPATH_HASH_PATHID) modulo_max = bms->table_per_peer_buckets; else modulo_max = 1; if (modulo_func) modulo = modulo_func(peer, NULL, modulo_max); else modulo = 0; matched_node = NULL; matched_info = NULL; node = table->top; if (bnv) bnv->entries = 0; /* Walk down tree. If there is matched route then store it to matched. */ while (node && node->p.prefixlen <= p->prefixlen && prefix_match(&node->p, p)) { for (local_modulo = modulo, modulo_idx = 0; modulo_idx < modulo_max; local_modulo++, modulo_idx++) { for (info = node->info[local_modulo]; info; info = info->next) { if (!cmp_func(info, nmct2)) { matched_node = node; matched_info = info; if (bnv) { bnv->v[bnv->entries].p = &node->p; bnv->v[bnv->entries].info = info; bnv->entries++; } if (node->p.prefixlen == p->prefixlen) break; } } } node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)]; } if (config.debug && bnv) bgp_node_vector_debug(bnv, p); if (matched_node) { (*result_node) = matched_node; (*result_info) = matched_info; bgp_lock_node (peer, matched_node); } else { (*result_node) = NULL; (*result_info) = NULL; } } void bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr, struct bgp_peer *peer, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *nmct2, struct bgp_node_vector *bnv, struct bgp_node **result_node, struct bgp_info **result_info) { struct prefix_ipv4 p; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = *addr; bgp_node_match (table, (struct prefix *) &p, peer, modulo_func, cmp_func, nmct2, bnv, result_node, result_info); } void bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr, struct bgp_peer *peer, u_int32_t (*modulo_func)(struct bgp_peer *, path_id_t *, int), int (*cmp_func)(struct bgp_info *, struct node_match_cmp_term2 *), struct node_match_cmp_term2 *nmct2, struct bgp_node_vector *bnv, struct bgp_node **result_node, struct bgp_info **result_info) { struct prefix_ipv6 p; memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; p.prefix = *addr; bgp_node_match (table, (struct prefix *) &p, peer, modulo_func, cmp_func, nmct2, bnv, result_node, result_info); } /* Add node to routing table. */ struct bgp_node * bgp_node_get (struct bgp_peer *peer, struct bgp_table *const table, struct prefix *p) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); (void)bms; struct bgp_node *new; struct bgp_node *node; struct bgp_node *match; match = NULL; node = table->top; while (node && node->p.prefixlen <= p->prefixlen && prefix_match (&node->p, p)) { if (node->p.prefixlen == p->prefixlen) { bgp_lock_node (peer, node); return node; } match = node; node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)]; } if (node == NULL) { new = bgp_node_set (peer, table, p); if (match) set_link (match, new); else table->top = new; } else { new = bgp_node_create (peer); route_common (&node->p, p, &new->p); new->p.family = p->family; new->table = table; set_link (new, node); if (match) set_link (match, new); else table->top = new; if (new->p.prefixlen != p->prefixlen) { match = new; new = bgp_node_set (peer, table, p); set_link (match, new); table->count++; } } table->count++; bgp_lock_node (peer, new); return new; } /* Delete node from the routing table. */ static void bgp_node_delete (struct bgp_peer *peer, struct bgp_node *node) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); struct bgp_node *child; struct bgp_node *parent; u_int32_t ri_idx; assert (node->lock == 0); for (ri_idx = 0; ri_idx < (bms->table_peer_buckets * bms->table_per_peer_buckets); ri_idx++) assert (node->info[ri_idx] == NULL); if (node->l_left && node->l_right) return; if (node->l_left) child = node->l_left; else child = node->l_right; parent = node->parent; if (child) child->parent = parent; if (parent) { if (parent->l_left == node) parent->l_left = child; else parent->l_right = child; } else node->table->top = child; node->table->count--; bgp_node_free (node); /* If parent node is stub then delete it also. */ if (parent && parent->lock == 0) bgp_node_delete (peer, parent); } /* Get fist node and lock it. This function is useful when one want to lookup all the node exist in the routing table. */ struct bgp_node * bgp_table_top (struct bgp_peer *peer, const struct bgp_table *const table) { if (table) { /* If there is no node in the routing table return NULL. */ if (table->top == NULL) return NULL; /* Lock the top node and return it. */ bgp_lock_node (peer, table->top); return table->top; } return NULL; } /* Unlock current node and lock next node then return it. */ struct bgp_node * bgp_route_next (struct bgp_peer *peer, struct bgp_node *node) { struct bgp_node *next; struct bgp_node *start; /* Node may be deleted from bgp_unlock_node so we have to preserve next node's pointer. */ if (node->l_left) { next = node->l_left; bgp_lock_node (peer, next); bgp_unlock_node (peer, node); return next; } if (node->l_right) { next = node->l_right; bgp_lock_node (peer, next); bgp_unlock_node (peer, node); return next; } start = node; while (node->parent) { if (node->parent->l_left == node && node->parent->l_right) { next = node->parent->l_right; bgp_lock_node (peer, next); bgp_unlock_node (peer, start); return next; } node = node->parent; } bgp_unlock_node (peer, start); return NULL; } /* Free route table. */ void bgp_table_free (struct bgp_table *rt) { struct bgp_node *tmp_node; struct bgp_node *node; if (rt == NULL) return; node = rt->top; /* Bulk deletion of nodes remaining in this table. This function is not called until workers have completed their dependency on this table. A final route_unlock_node() will not be called for these nodes. */ while (node) { if (node->l_left) { node = node->l_left; continue; } if (node->l_right) { node = node->l_right; continue; } tmp_node = node; node = node->parent; tmp_node->table->count--; tmp_node->lock = 0; /* to cause assert if unlocked after this */ bgp_node_free (tmp_node); if (node != NULL) { if (node->l_left == tmp_node) node->l_left = NULL; else node->l_right = NULL; } else { break; } } assert (rt->count == 0); free(rt); return; } pmacct-1.7.8/src/bgp/Makefile.in0000644000175000017500000011602414354105415015416 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/bgp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmbgp_la_LIBADD = am_libpmbgp_la_OBJECTS = libpmbgp_la-bgp.lo libpmbgp_la-bgp_aspath.lo \ libpmbgp_la-bgp_community.lo libpmbgp_la-bgp_ecommunity.lo \ libpmbgp_la-bgp_hash.lo libpmbgp_la-bgp_prefix.lo \ libpmbgp_la-bgp_table.lo libpmbgp_la-bgp_logdump.lo \ libpmbgp_la-bgp_util.lo libpmbgp_la-bgp_msg.lo \ libpmbgp_la-bgp_lookup.lo libpmbgp_la-bgp_lcommunity.lo \ libpmbgp_la-bgp_xcs.lo libpmbgp_la-bgp_blackhole.lo \ libpmbgp_la-bgp_lg.lo libpmbgp_la_OBJECTS = $(am_libpmbgp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmbgp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpmbgp_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmbgp_la-bgp.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_aspath.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_blackhole.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_community.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_ecommunity.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_hash.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_lcommunity.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_lg.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_logdump.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_lookup.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_msg.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_prefix.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_table.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_util.Plo \ ./$(DEPDIR)/libpmbgp_la-bgp_xcs.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmbgp_la_SOURCES) DIST_SOURCES = $(libpmbgp_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmbgp.la libpmbgp_la_SOURCES = bgp.c bgp_aspath.c bgp_community.c \ bgp_ecommunity.c bgp_hash.c bgp_prefix.c bgp_table.c \ bgp_logdump.c bgp_util.c bgp_msg.c bgp_lookup.c \ bgp_lcommunity.c bgp_xcs.c bgp_aspath.h bgp_community.h \ bgp_ecommunity.h bgp.h bgp_hash.h bgp_logdump.h \ bgp_lookup.h bgp_msg.h bgp_packet.h bgp_prefix.h \ bgp_table.h bgp_util.h bgp_lcommunity.h bgp_xcs.h \ bgp_xcs-data.h bgp_blackhole.c bgp_blackhole.h \ bgp_lg.c bgp_lg.h libpmbgp_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/bgp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/bgp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmbgp.la: $(libpmbgp_la_OBJECTS) $(libpmbgp_la_DEPENDENCIES) $(EXTRA_libpmbgp_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmbgp_la_LINK) $(libpmbgp_la_OBJECTS) $(libpmbgp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_aspath.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_blackhole.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_community.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_ecommunity.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_hash.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_lcommunity.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_lg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_logdump.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_lookup.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_msg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_prefix.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_table.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_util.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbgp_la-bgp_xcs.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmbgp_la-bgp.lo: bgp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp.Tpo -c -o libpmbgp_la-bgp.lo `test -f 'bgp.c' || echo '$(srcdir)/'`bgp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp.Tpo $(DEPDIR)/libpmbgp_la-bgp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp.c' object='libpmbgp_la-bgp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp.lo `test -f 'bgp.c' || echo '$(srcdir)/'`bgp.c libpmbgp_la-bgp_aspath.lo: bgp_aspath.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_aspath.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_aspath.Tpo -c -o libpmbgp_la-bgp_aspath.lo `test -f 'bgp_aspath.c' || echo '$(srcdir)/'`bgp_aspath.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_aspath.Tpo $(DEPDIR)/libpmbgp_la-bgp_aspath.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_aspath.c' object='libpmbgp_la-bgp_aspath.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_aspath.lo `test -f 'bgp_aspath.c' || echo '$(srcdir)/'`bgp_aspath.c libpmbgp_la-bgp_community.lo: bgp_community.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_community.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_community.Tpo -c -o libpmbgp_la-bgp_community.lo `test -f 'bgp_community.c' || echo '$(srcdir)/'`bgp_community.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_community.Tpo $(DEPDIR)/libpmbgp_la-bgp_community.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_community.c' object='libpmbgp_la-bgp_community.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_community.lo `test -f 'bgp_community.c' || echo '$(srcdir)/'`bgp_community.c libpmbgp_la-bgp_ecommunity.lo: bgp_ecommunity.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_ecommunity.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_ecommunity.Tpo -c -o libpmbgp_la-bgp_ecommunity.lo `test -f 'bgp_ecommunity.c' || echo '$(srcdir)/'`bgp_ecommunity.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_ecommunity.Tpo $(DEPDIR)/libpmbgp_la-bgp_ecommunity.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_ecommunity.c' object='libpmbgp_la-bgp_ecommunity.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_ecommunity.lo `test -f 'bgp_ecommunity.c' || echo '$(srcdir)/'`bgp_ecommunity.c libpmbgp_la-bgp_hash.lo: bgp_hash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_hash.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_hash.Tpo -c -o libpmbgp_la-bgp_hash.lo `test -f 'bgp_hash.c' || echo '$(srcdir)/'`bgp_hash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_hash.Tpo $(DEPDIR)/libpmbgp_la-bgp_hash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_hash.c' object='libpmbgp_la-bgp_hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_hash.lo `test -f 'bgp_hash.c' || echo '$(srcdir)/'`bgp_hash.c libpmbgp_la-bgp_prefix.lo: bgp_prefix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_prefix.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_prefix.Tpo -c -o libpmbgp_la-bgp_prefix.lo `test -f 'bgp_prefix.c' || echo '$(srcdir)/'`bgp_prefix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_prefix.Tpo $(DEPDIR)/libpmbgp_la-bgp_prefix.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_prefix.c' object='libpmbgp_la-bgp_prefix.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_prefix.lo `test -f 'bgp_prefix.c' || echo '$(srcdir)/'`bgp_prefix.c libpmbgp_la-bgp_table.lo: bgp_table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_table.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_table.Tpo -c -o libpmbgp_la-bgp_table.lo `test -f 'bgp_table.c' || echo '$(srcdir)/'`bgp_table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_table.Tpo $(DEPDIR)/libpmbgp_la-bgp_table.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_table.c' object='libpmbgp_la-bgp_table.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_table.lo `test -f 'bgp_table.c' || echo '$(srcdir)/'`bgp_table.c libpmbgp_la-bgp_logdump.lo: bgp_logdump.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_logdump.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_logdump.Tpo -c -o libpmbgp_la-bgp_logdump.lo `test -f 'bgp_logdump.c' || echo '$(srcdir)/'`bgp_logdump.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_logdump.Tpo $(DEPDIR)/libpmbgp_la-bgp_logdump.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_logdump.c' object='libpmbgp_la-bgp_logdump.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_logdump.lo `test -f 'bgp_logdump.c' || echo '$(srcdir)/'`bgp_logdump.c libpmbgp_la-bgp_util.lo: bgp_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_util.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_util.Tpo -c -o libpmbgp_la-bgp_util.lo `test -f 'bgp_util.c' || echo '$(srcdir)/'`bgp_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_util.Tpo $(DEPDIR)/libpmbgp_la-bgp_util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_util.c' object='libpmbgp_la-bgp_util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_util.lo `test -f 'bgp_util.c' || echo '$(srcdir)/'`bgp_util.c libpmbgp_la-bgp_msg.lo: bgp_msg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_msg.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_msg.Tpo -c -o libpmbgp_la-bgp_msg.lo `test -f 'bgp_msg.c' || echo '$(srcdir)/'`bgp_msg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_msg.Tpo $(DEPDIR)/libpmbgp_la-bgp_msg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_msg.c' object='libpmbgp_la-bgp_msg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_msg.lo `test -f 'bgp_msg.c' || echo '$(srcdir)/'`bgp_msg.c libpmbgp_la-bgp_lookup.lo: bgp_lookup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_lookup.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_lookup.Tpo -c -o libpmbgp_la-bgp_lookup.lo `test -f 'bgp_lookup.c' || echo '$(srcdir)/'`bgp_lookup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_lookup.Tpo $(DEPDIR)/libpmbgp_la-bgp_lookup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_lookup.c' object='libpmbgp_la-bgp_lookup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_lookup.lo `test -f 'bgp_lookup.c' || echo '$(srcdir)/'`bgp_lookup.c libpmbgp_la-bgp_lcommunity.lo: bgp_lcommunity.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_lcommunity.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_lcommunity.Tpo -c -o libpmbgp_la-bgp_lcommunity.lo `test -f 'bgp_lcommunity.c' || echo '$(srcdir)/'`bgp_lcommunity.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_lcommunity.Tpo $(DEPDIR)/libpmbgp_la-bgp_lcommunity.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_lcommunity.c' object='libpmbgp_la-bgp_lcommunity.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_lcommunity.lo `test -f 'bgp_lcommunity.c' || echo '$(srcdir)/'`bgp_lcommunity.c libpmbgp_la-bgp_xcs.lo: bgp_xcs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_xcs.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_xcs.Tpo -c -o libpmbgp_la-bgp_xcs.lo `test -f 'bgp_xcs.c' || echo '$(srcdir)/'`bgp_xcs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_xcs.Tpo $(DEPDIR)/libpmbgp_la-bgp_xcs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_xcs.c' object='libpmbgp_la-bgp_xcs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_xcs.lo `test -f 'bgp_xcs.c' || echo '$(srcdir)/'`bgp_xcs.c libpmbgp_la-bgp_blackhole.lo: bgp_blackhole.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_blackhole.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_blackhole.Tpo -c -o libpmbgp_la-bgp_blackhole.lo `test -f 'bgp_blackhole.c' || echo '$(srcdir)/'`bgp_blackhole.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_blackhole.Tpo $(DEPDIR)/libpmbgp_la-bgp_blackhole.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_blackhole.c' object='libpmbgp_la-bgp_blackhole.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_blackhole.lo `test -f 'bgp_blackhole.c' || echo '$(srcdir)/'`bgp_blackhole.c libpmbgp_la-bgp_lg.lo: bgp_lg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -MT libpmbgp_la-bgp_lg.lo -MD -MP -MF $(DEPDIR)/libpmbgp_la-bgp_lg.Tpo -c -o libpmbgp_la-bgp_lg.lo `test -f 'bgp_lg.c' || echo '$(srcdir)/'`bgp_lg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbgp_la-bgp_lg.Tpo $(DEPDIR)/libpmbgp_la-bgp_lg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bgp_lg.c' object='libpmbgp_la-bgp_lg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbgp_la_CFLAGS) $(CFLAGS) -c -o libpmbgp_la-bgp_lg.lo `test -f 'bgp_lg.c' || echo '$(srcdir)/'`bgp_lg.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmbgp_la-bgp.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_aspath.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_blackhole.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_community.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_ecommunity.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_hash.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lcommunity.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lg.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_logdump.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lookup.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_msg.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_prefix.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_table.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_util.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_xcs.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmbgp_la-bgp.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_aspath.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_blackhole.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_community.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_ecommunity.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_hash.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lcommunity.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lg.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_logdump.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_lookup.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_msg.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_prefix.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_table.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_util.Plo -rm -f ./$(DEPDIR)/libpmbgp_la-bgp_xcs.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/bgp/bgp_lookup.h0000644000175000017500000000431714354105275015670 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_LOOKUP_H_ #define _BGP_LOOKUP_H_ /* prototypes */ extern void bgp_srcdst_lookup(struct packet_ptrs *, int); extern void bgp_follow_nexthop_lookup(struct packet_ptrs *, int); extern struct bgp_peer *bgp_lookup_find_bgp_peer(struct sockaddr *, struct xflow_status_entry *, u_int16_t, int); extern u_int32_t bgp_route_info_modulo_pathid(struct bgp_peer *, path_id_t *, int); extern int bgp_lookup_node_match_cmp_bgp(struct bgp_info *, struct node_match_cmp_term2 *); extern int bgp_lookup_node_vector_unicast(struct prefix *, struct bgp_peer *, struct bgp_node_vector *); extern void pkt_to_cache_legacy_bgp_primitives(struct cache_legacy_bgp_primitives *, struct pkt_legacy_bgp_primitives *, pm_cfgreg_t, pm_cfgreg_t); extern void cache_to_pkt_legacy_bgp_primitives(struct pkt_legacy_bgp_primitives *, struct cache_legacy_bgp_primitives *); extern void free_cache_legacy_bgp_primitives(struct cache_legacy_bgp_primitives **); extern int bgp_lg_daemon_ip_lookup(struct bgp_lg_req_ipl_data *, struct bgp_lg_rep *, int); extern int bgp_lg_daemon_get_peers(struct bgp_lg_rep *, int); extern void bgp_lg_rep_init(struct bgp_lg_rep *); extern struct bgp_lg_rep_data *bgp_lg_rep_data_add(struct bgp_lg_rep *); extern void bgp_lg_rep_ipl_data_add(struct bgp_lg_rep *, afi_t, safi_t, struct prefix *, struct bgp_info *); extern void bgp_lg_rep_gp_data_add(struct bgp_lg_rep *, struct bgp_peer *); #endif pmacct-1.7.8/src/bgp/bgp_lg.c0000644000175000017500000003317414354105275014757 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #if defined WITH_ZMQ #include "zmq_common.h" #endif #include "bgp.h" #include "bgp_lg.h" #include "pmacct-data.h" #include "thread_pool.h" /* global var */ thread_pool_t *bgp_lg_pool; char bgp_lg_default_ip[] = "127.0.0.1"; #if defined WITH_ZMQ void bgp_lg_wrapper() { /* initialize variables */ if (!config.bgp_lg_ip) config.bgp_lg_ip = bgp_lg_default_ip; if (!config.bgp_lg_port) config.bgp_lg_port = BGP_LG_DEFAULT_TCP_PORT; if (!config.bgp_lg_threads) config.bgp_lg_threads = BGP_LG_DEFAULT_THREADS; /* initialize threads pool */ bgp_lg_pool = allocate_thread_pool(1); assert(bgp_lg_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/lg ): Looking Glass thread initialized\n", config.name); /* giving a kick to the BGP thread */ send_to_pool(bgp_lg_pool, bgp_lg_daemon, NULL); } int bgp_lg_daemon() { char inproc_str[] = "inproc://lg_host_backend", log_id[SHORTBUFLEN]; struct p_zmq_host lg_host; memset(&lg_host, 0, sizeof(lg_host)); snprintf(log_id, sizeof(log_id), "%s/core/lg", config.name); p_zmq_set_log_id(&lg_host, log_id); p_zmq_set_address(&lg_host, inproc_str); if (config.bgp_lg_user) p_zmq_set_username(&lg_host, config.bgp_lg_user); if (config.bgp_lg_passwd) p_zmq_set_password(&lg_host, config.bgp_lg_passwd); p_zmq_router_setup(&lg_host, config.bgp_lg_ip, config.bgp_lg_port); Log(LOG_INFO, "INFO ( %s/core/lg ): Looking Glass listening on %s:%u\n", config.name, config.bgp_lg_ip, config.bgp_lg_port); // XXX: more encodings supported in future? #ifdef WITH_JANSSON lg_host.router_worker.func = &bgp_lg_daemon_worker_json; #else lg_host.router_worker.func = NULL; Log(LOG_WARNING, "WARN ( %s/core/lg ): Looking Glass depends on missing --enable-jansson.\n", config.name); exit_gracefully(1); #endif p_zmq_router_backend_setup(&lg_host, config.bgp_lg_threads); return SUCCESS; } #ifdef WITH_JANSSON void bgp_lg_daemon_worker_json(void *zh, void *zs) { struct p_zmq_host *lg_host = (struct p_zmq_host *) zh; struct p_zmq_sock *sock = zs; struct bgp_lg_req req; struct bgp_lg_rep ipl_rep, gp_rep; int ret; if (!lg_host || !sock) { Log(LOG_ERR, "ERROR ( %s/core/lg ): bgp_lg_daemon_worker no lg_host or sock\nExiting.\n", config.name); exit_gracefully(1); } memset(&ipl_rep, 0, sizeof(ipl_rep)); memset(&gp_rep, 0, sizeof(gp_rep)); for (;;) { memset(&req, 0, sizeof(req)); ret = bgp_lg_daemon_decode_query_header_json(sock, &req); switch(req.type) { case BGP_LG_QT_IP_LOOKUP: { struct bgp_lg_req_ipl_data query_data; req.data = &query_data; memset(req.data, 0, sizeof(struct bgp_lg_req_ipl_data)); ret = bgp_lg_daemon_decode_query_ip_lookup_json(sock, req.data); bgp_lg_rep_init(&ipl_rep); if (!ret) ret = bgp_lg_daemon_ip_lookup(req.data, &ipl_rep, FUNC_TYPE_BGP); bgp_lg_daemon_encode_reply_ip_lookup_json(sock, &ipl_rep, ret); } break; case BGP_LG_QT_GET_PEERS: bgp_lg_rep_init(&gp_rep); ret = bgp_lg_daemon_get_peers(&gp_rep, FUNC_TYPE_BGP); bgp_lg_daemon_encode_reply_get_peers_json(sock, &gp_rep, ret); break; case BGP_LG_QT_UNKNOWN: default: bgp_lg_daemon_encode_reply_unknown_json(sock); break; } } } int bgp_lg_daemon_decode_query_header_json(struct p_zmq_sock *sock, struct bgp_lg_req *req) { json_t *req_obj, *query_type_json, *queries_num_json; json_error_t req_err; char *req_str; int ret = SUCCESS; if (!sock || !req) return ERR; req_str = p_zmq_recv_str(sock); if (req_str) { req_obj = json_loads(req_str, 0, &req_err); free(req_str); } else { req_obj = NULL; ret = ERR; } if (req_obj) { if (!json_is_object(req_obj)) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_header_json(): json_is_object() failed.\n", config.name); ret = ERR; goto exit_lane; } else { query_type_json = json_object_get(req_obj, "query_type"); if (query_type_json == NULL) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_header_json(): no 'query_type' element.\n", config.name); ret = ERR; goto exit_lane; } else req->type = json_integer_value(query_type_json); queries_num_json = json_object_get(req_obj, "queries"); if (queries_num_json == NULL) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_header_json(): no 'queries' element.\n", config.name); ret = ERR; goto exit_lane; } else req->num = json_integer_value(queries_num_json); /* XXX: only one query per query message currently supported */ if (req->num != 1) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_header_json(): 'queries' element != 1.\n", config.name); ret = ERR; goto exit_lane; } } exit_lane: json_decref(req_obj); } else { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_header_json(): invalid request received: %s.\n", config.name, req_err.text); ret = ERR; } return ret; } int bgp_lg_daemon_decode_query_ip_lookup_json(struct p_zmq_sock *sock, struct bgp_lg_req_ipl_data *req) { json_error_t req_err; json_t *req_obj, *peer_ip_src_json, *bgp_port_json, *ip_prefix_json, *rd_json; const char *peer_ip_src_str, *ip_prefix_str, *rd_str; char *req_str; int ret = SUCCESS; struct rd_as4 *rd_as4_ptr; u_int16_t bgp_port = 0; if (!sock || !req) return ERR; req_str = p_zmq_recv_str(sock); if (req_str) { req_obj = json_loads(req_str, 0, &req_err); free(req_str); } else { req_obj = NULL; ret = ERR; } if (req_obj) { if (!json_is_object(req_obj)) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): json_is_object() failed.\n", config.name); ret = ERR; goto exit_lane; } else { bgp_port_json = json_object_get(req_obj, "peer_tcp_port"); if (bgp_port_json) { int bgp_port_int; bgp_port_int = json_integer_value(bgp_port_json); if (bgp_port_int >= 0 && bgp_port_int <= 65535) bgp_port = bgp_port_int; else { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): bogus 'peer_tcp_port' element.\n", config.name); ret = ERR; goto exit_lane; } } peer_ip_src_json = json_object_get(req_obj, "peer_ip_src"); if (peer_ip_src_json == NULL) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): no 'peer_ip_src' element.\n", config.name); ret = ERR; goto exit_lane; } else { struct host_addr peer_ip_src_ha; peer_ip_src_str = json_string_value(peer_ip_src_json); str_to_addr(peer_ip_src_str, &peer_ip_src_ha); addr_to_sa(&req->peer, &peer_ip_src_ha, bgp_port); if (!req->peer.sa_family) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): bogus 'peer_ip_src' element.\n", config.name); ret = ERR; goto exit_lane; } } ip_prefix_json = json_object_get(req_obj, "ip_prefix"); if (ip_prefix_json == NULL) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): no 'ip_prefix' element.\n", config.name); ret = ERR; goto exit_lane; } else { ip_prefix_str = json_string_value(ip_prefix_json); str2prefix(ip_prefix_str, &req->pref); if (!req->pref.family) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): bogus 'ip_prefix' element.\n", config.name); ret = ERR; goto exit_lane; } } rd_json = json_object_get(req_obj, "rd"); if (rd_json) { rd_str = json_string_value(rd_json); bgp_str2rd(&req->rd, (char *) rd_str); rd_as4_ptr = (struct rd_as4 *) &req->rd; if (!rd_as4_ptr->as) { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): bogus 'rd' element.\n", config.name); ret = ERR; goto exit_lane; } } } exit_lane: json_decref(req_obj); } else { Log(LOG_WARNING, "WARN ( %s/core/lg ): bgp_lg_daemon_decode_query_ip_lookup_json(): invalid request received: %s.\n", config.name, req_err.text); ret = ERR; } return ret; } void bgp_lg_daemon_encode_reply_results_json(struct p_zmq_sock *sock, struct bgp_lg_rep *rep, int res, int query_type) { json_t *rep_results_obj; char *rep_results_str; rep_results_obj = json_object(); json_object_set_new_nocheck(rep_results_obj, "results", json_integer(rep->results)); json_object_set_new_nocheck(rep_results_obj, "query_type", json_integer(query_type)); if (!rep->results && res) { switch (res) { case BGP_LOOKUP_ERR: json_object_set_new_nocheck(rep_results_obj, "text", json_string("lookup error")); break; case BGP_LOOKUP_NOPREFIX: json_object_set_new_nocheck(rep_results_obj, "text", json_string("prefix not found")); break; case BGP_LOOKUP_NOPEER: json_object_set_new_nocheck(rep_results_obj, "text", json_string("peer not found")); break; default: json_object_set_new_nocheck(rep_results_obj, "text", json_string("unknown lookup error")); break; } } rep_results_str = json_dumps(rep_results_obj, JSON_PRESERVE_ORDER); json_decref(rep_results_obj); if (rep_results_str) { if (!rep->results) p_zmq_send_str(sock, rep_results_str); else p_zmq_sendmore_str(sock, rep_results_str); free(rep_results_str); } } void bgp_lg_daemon_encode_reply_ip_lookup_json(struct p_zmq_sock *sock, struct bgp_lg_rep *rep, int res) { if (!sock || !rep) return; bgp_lg_daemon_encode_reply_results_json(sock, rep, res, BGP_LG_QT_IP_LOOKUP); if (rep->results) { struct bgp_lg_rep_data *data; struct bgp_lg_rep_ipl_data *ipl_data; char *rep_data_str; u_int32_t idx; for (idx = 0, data = rep->data; idx < rep->results; idx++) { ipl_data = data->ptr; rep_data_str = bgp_lg_daemon_encode_reply_ip_lookup_data_json(ipl_data); if (rep_data_str) { if (idx == (rep->results - 1)) p_zmq_send_str(sock, rep_data_str); else p_zmq_sendmore_str(sock, rep_data_str); free(rep_data_str); } data = data->next; } } } char *bgp_lg_daemon_encode_reply_ip_lookup_data_json(struct bgp_lg_rep_ipl_data *rep_data) { struct bgp_node dummy_node; char event_type[] = "lglass", *data_str = NULL; if (rep_data && rep_data->pref) { memset(&dummy_node, 0, sizeof(dummy_node)); memcpy(&dummy_node.p, rep_data->pref, sizeof(struct prefix)); bgp_peer_log_msg(&dummy_node, rep_data->info, rep_data->afi, rep_data->safi, NULL, event_type, PRINT_OUTPUT_JSON, &data_str, BGP_LOG_TYPE_MISC); } return data_str; } void bgp_lg_daemon_encode_reply_get_peers_json(struct p_zmq_sock *sock, struct bgp_lg_rep *rep, int res) { if (!sock || !rep) return; bgp_lg_daemon_encode_reply_results_json(sock, rep, res, BGP_LG_QT_GET_PEERS); if (rep->results) { struct bgp_lg_rep_data *data; struct bgp_lg_rep_gp_data *gp_data; char *rep_data_str; u_int32_t idx; for (idx = 0, data = rep->data; idx < rep->results; idx++) { gp_data = data->ptr; rep_data_str = bgp_lg_daemon_encode_reply_get_peers_data_json(gp_data); if (rep_data_str) { if (idx == (rep->results - 1)) p_zmq_send_str(sock, rep_data_str); else p_zmq_sendmore_str(sock, rep_data_str); free(rep_data_str); } data = data->next; } } } char *bgp_lg_daemon_encode_reply_get_peers_data_json(struct bgp_lg_rep_gp_data *rep_data) { struct bgp_misc_structs *bms; char ip_address[INET6_ADDRSTRLEN], *data_str = NULL; json_t *obj = json_object(); if (rep_data) { struct bgp_peer *peer = rep_data->peer; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); addr_to_str(ip_address, &peer->id); json_object_set_new_nocheck(obj, "peer_id", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_tcp_port", json_integer((json_int_t)peer->tcp_port)); json_object_set_new_nocheck(obj, "peer_as", json_integer((json_int_t)peer->as)); data_str = compose_json_str(obj); } return data_str; } void bgp_lg_daemon_encode_reply_unknown_json(struct p_zmq_sock *sock) { json_t *rep_results_obj; char *rep_results_str; if (!sock) return; rep_results_obj = json_object(); json_object_set_new_nocheck(rep_results_obj, "results", json_integer(FALSE)); json_object_set_new_nocheck(rep_results_obj, "query_type", json_integer(BGP_LG_QT_UNKNOWN)); json_object_set_new_nocheck(rep_results_obj, "text", json_string("unsupported query_type")); rep_results_str = json_dumps(rep_results_obj, JSON_PRESERVE_ORDER); json_decref(rep_results_obj); p_zmq_send_str(sock, rep_results_str); } #endif #endif /* WITH_ZMQ */ pmacct-1.7.8/src/bgp/bgp_lg.h0000644000175000017500000000414114354105275014754 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BGP_LG_H #define BGP_LG_H /* includes */ /* defines */ #define BGP_LG_DEFAULT_TCP_PORT 17900 #define BGP_LG_DEFAULT_THREADS 8 #define BGP_LG_QT_UNKNOWN 0 #define BGP_LG_QT_IP_LOOKUP 1 #define BGP_LG_QT_GET_PEERS 2 /* structures */ /* prototypes */ #if defined WITH_ZMQ extern void bgp_lg_wrapper(); extern int bgp_lg_daemon(); #if defined WITH_JANSSON extern void bgp_lg_daemon_worker_json(void *, void *); extern int bgp_lg_daemon_decode_query_header_json(struct p_zmq_sock *, struct bgp_lg_req *); extern int bgp_lg_daemon_decode_query_ip_lookup_json(struct p_zmq_sock *, struct bgp_lg_req_ipl_data *); extern void bgp_lg_daemon_encode_reply_results_json(struct p_zmq_sock *, struct bgp_lg_rep *, int, int); extern void bgp_lg_daemon_encode_reply_ip_lookup_json(struct p_zmq_sock *, struct bgp_lg_rep *, int); extern char *bgp_lg_daemon_encode_reply_ip_lookup_data_json(struct bgp_lg_rep_ipl_data *); extern void bgp_lg_daemon_encode_reply_get_peers_json(struct p_zmq_sock *, struct bgp_lg_rep *, int); extern char *bgp_lg_daemon_encode_reply_get_peers_data_json(struct bgp_lg_rep_gp_data *); extern void bgp_lg_daemon_encode_reply_unknown_json(struct p_zmq_sock *); #endif //WITH_JANSSON #endif //WITH_ZMQ /* global variables */ extern char bgp_lg_default_ip[]; #endif //BGP_LG_H pmacct-1.7.8/src/bgp/bgp_util.h0000644000175000017500000001312314354105275015327 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_UTIL_H_ #define _BGP_UTIL_H_ /* prototypes */ extern int bgp_afi2family(int); extern u_int16_t bgp_rd_type_get(u_int16_t); extern u_int16_t bgp_rd_origin_get(u_int16_t); extern void bgp_rd_origin_set(rd_t *, u_int16_t); extern const char *bgp_rd_origin_print(u_int16_t); extern int bgp_rd_ntoh(rd_t *); extern int bgp_rd2str(char *, rd_t *); extern int bgp_str2rd(rd_t *, char *); extern int bgp_label2str(char *, u_char *); extern const char *bgp_origin_print(u_int8_t); extern u_int8_t bgp_str2origin(char *); extern void load_comm_patterns(char **, char **, char **, char **, char **); extern void load_peer_src_as_comm_ranges(char *, char *); extern void evaluate_comm_patterns(char *, char *, char **, int); extern int bgp_str2asn(char *, as_t *); extern as_t evaluate_last_asn(struct aspath *); extern as_t evaluate_first_asn(char *); extern void evaluate_bgp_aspath_radius(char *, int, int); extern void copy_stdcomm_to_asn(char *, as_t *, int); extern void copy_lrgcomm_to_asn(char *, as_t *, int); extern void write_neighbors_file(char *, int); extern struct bgp_rt_structs *bgp_select_routing_db(int); extern void bgp_md5_file_init(struct bgp_md5_table *); extern void bgp_md5_file_load(char *, struct bgp_md5_table *); extern void bgp_md5_file_unload(struct bgp_md5_table *); extern void bgp_md5_file_process(int, struct bgp_md5_table *); extern void bgp_config_checks(struct configuration *); extern struct bgp_misc_structs *bgp_select_misc_db(int); extern void bgp_link_misc_structs(struct bgp_misc_structs *); extern void bgp_blackhole_link_misc_structs(struct bgp_misc_structs *); extern struct bgp_attr_extra *bgp_attr_extra_new(struct bgp_info *); extern void bgp_attr_extra_free(struct bgp_peer *, struct bgp_attr_extra **); extern struct bgp_attr_extra *bgp_attr_extra_get(struct bgp_info *); extern struct bgp_attr_extra *bgp_attr_extra_process(struct bgp_peer *, struct bgp_info *, afi_t, safi_t, struct bgp_attr_extra *); extern struct bgp_info *bgp_info_new(struct bgp_peer *); extern void bgp_info_add(struct bgp_peer *, struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_delete(struct bgp_peer *, struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_free(struct bgp_peer *, struct bgp_info *, void (*bgp_extra_data_free)(struct bgp_msg_extra_data *)); extern void bgp_attr_init(int, struct bgp_rt_structs *); extern struct bgp_attr *bgp_attr_intern(struct bgp_peer *, struct bgp_attr *); extern void bgp_attr_unintern (struct bgp_peer *, struct bgp_attr *); extern void *bgp_attr_hash_alloc (void *); extern int bgp_attr_munge_as4path(struct bgp_peer *, struct bgp_attr *, struct aspath *); extern int bgp_peer_init(struct bgp_peer *, int); extern void bgp_peer_close(struct bgp_peer *, int, int, int, u_int8_t, u_int8_t, char *); extern int bgp_peer_xconnect_init(struct bgp_peer *, int); extern void bgp_peer_print(struct bgp_peer *, char *, int); extern void bgp_peer_xconnect_print(struct bgp_peer *, char *, int); extern void bgp_peer_info_delete(struct bgp_peer *); extern void bgp_table_info_delete(struct bgp_peer *, struct bgp_table *, afi_t, safi_t); extern void bgp_peer_cache_init(struct bgp_peer_cache_bucket *, u_int32_t); extern struct bgp_peer_cache *bgp_peer_cache_insert(struct bgp_peer_cache_bucket *, u_int32_t, struct bgp_peer *); extern int bgp_peer_cache_delete(struct bgp_peer_cache_bucket *, u_int32_t, struct bgp_peer *); extern struct bgp_peer *bgp_peer_cache_search(struct bgp_peer_cache_bucket *, u_int32_t, struct host_addr *, u_int16_t); extern void bgp_batch_init(struct bgp_peer_batch *, int, int); extern void bgp_batch_reset(struct bgp_peer_batch *, time_t); extern int bgp_batch_is_admitted(struct bgp_peer_batch *, time_t); extern int bgp_batch_is_enabled(struct bgp_peer_batch *); extern int bgp_batch_is_expired(struct bgp_peer_batch *, time_t); extern int bgp_batch_is_not_empty(struct bgp_peer_batch *); extern void bgp_batch_increase_counter(struct bgp_peer_batch *); extern void bgp_batch_decrease_counter(struct bgp_peer_batch *); extern void bgp_batch_rollback(struct bgp_peer_batch *); extern int bgp_peer_cmp(const void *, const void *); extern int bgp_peer_host_addr_cmp(const void *, const void *); extern int bgp_peer_sa_addr_cmp(const void *, const void *); extern void bgp_peer_free(void *); extern int bgp_peers_bintree_walk_print(const void *, const pm_VISIT, const int, void *); extern int bgp_peers_bintree_walk_delete(const void *, const pm_VISIT, const int, void *); extern unsigned int attrhash_key_make(void *); extern int attrhash_cmp(const void *, const void *); extern void attrhash_init(int, struct hash **); extern int bgp_router_id_check(struct bgp_msg_data *); extern u_int16_t bgp_get_packet_len(char *); extern u_int8_t bgp_get_packet_type(char *); void bgp_table_info_delete_tag_find_bgp(struct bgp_peer *); #endif pmacct-1.7.8/src/bgp/bgp_util.c0000644000175000017500000013315114354105275015326 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp.h" #include "thread_pool.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif /* BGP Address Famiy Identifier to UNIX Address Family converter. */ int bgp_afi2family (int afi) { if (afi == AFI_IP) return AF_INET; else if (afi == AFI_IP6) return AF_INET6; return SUCCESS; } u_int16_t bgp_rd_type_get(u_int16_t type) { return (type & RD_TYPE_MASK); } u_int16_t bgp_rd_origin_get(u_int16_t type) { return (type & RD_ORIGIN_MASK); } void bgp_rd_origin_set(rd_t *rd, u_int16_t source) { u_int16_t type; if (!rd) return; /* saving the type info, if any yet */ type = bgp_rd_type_get(rd->type); /* setting the source info, re-applying type */ rd->type = source; rd->type |= type; } const char *bgp_rd_origin_print(u_int16_t type) { switch(bgp_rd_origin_get(type)) { case RD_ORIGIN_BGP: return bgp_rd_origin[1]; case RD_ORIGIN_BMP: return bgp_rd_origin[2]; case RD_ORIGIN_FLOW: return bgp_rd_origin[3]; default: return bgp_rd_origin[0]; }; return NULL; } int bgp_rd_ntoh(rd_t *rd) { struct rd_ip *rdi; struct rd_as *rda; struct rd_as4 *rda4; if (!rd) return ERR; rd->type = ntohs(rd->type); switch(rd->type) { case RD_TYPE_AS: rda = (struct rd_as *) rd; rda->as = ntohs(rda->as); rda->val = ntohl(rda->val); break; case RD_TYPE_IP: rdi = (struct rd_ip *) rd; rdi->val = ntohs(rdi->val); break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) rd; rda4->as = ntohl(rda4->as); rda4->val = ntohs(rda4->val); break; default: return ERR; break; } return SUCCESS; } int bgp_rd2str(char *str, rd_t *rd) { struct rd_ip *rdi; struct rd_as *rda; struct rd_as4 *rda4; struct host_addr a; char ip_address[INET6_ADDRSTRLEN]; u_int16_t type = bgp_rd_type_get(rd->type); switch (type) { case RD_TYPE_AS: rda = (struct rd_as *) rd; sprintf(str, "%u:%u:%u", type, rda->as, rda->val); break; case RD_TYPE_IP: rdi = (struct rd_ip *) rd; a.family = AF_INET; a.address.ipv4.s_addr = rdi->ip.s_addr; addr_to_str(ip_address, &a); sprintf(str, "%u:%s:%u", type, ip_address, rdi->val); break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) rd; sprintf(str, "%u:%u:%u", type, rda4->as, rda4->val); break; case RD_TYPE_VRFID: rda = (struct rd_as *) rd; sprintf(str, "vrfid:%u", rda->val); break; default: sprintf(str, "unknown"); break; } return TRUE; } int bgp_str2rd(rd_t *output, char *value) { struct host_addr a; char *endptr, *token; u_int32_t tmp32; struct rd_ip *rdi; struct rd_as *rda; struct rd_as4 *rda4; int idx = 0; rd_t rd; memset(&a, 0, sizeof(a)); memset(&rd, 0, sizeof(rd)); /* type:RD_subfield1:RD_subfield2 */ while ( (token = extract_token(&value, ':')) && idx < 3) { if (idx == 0) { tmp32 = strtoul(token, &endptr, 10); rd.type = tmp32; switch (rd.type) { case RD_TYPE_AS: rda = (struct rd_as *) &rd; break; case RD_TYPE_IP: rdi = (struct rd_ip *) &rd; break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) &rd; break; default: printf("ERROR: Invalid RD type specified\n"); return FALSE; } } if (idx == 1) { switch (rd.type) { case RD_TYPE_AS: tmp32 = strtoul(token, &endptr, 10); rda->as = tmp32; break; case RD_TYPE_IP: memset(&a, 0, sizeof(a)); str_to_addr(token, &a); if (a.family == AF_INET) rdi->ip.s_addr = a.address.ipv4.s_addr; break; case RD_TYPE_AS4: tmp32 = strtoul(token, &endptr, 10); rda4->as = tmp32; break; } } if (idx == 2) { switch (rd.type) { case RD_TYPE_AS: tmp32 = strtoul(token, &endptr, 10); rda->val = tmp32; break; case RD_TYPE_IP: tmp32 = strtoul(token, &endptr, 10); rdi->val = tmp32; break; case RD_TYPE_AS4: tmp32 = strtoul(token, &endptr, 10); rda4->val = tmp32; break; } } idx++; } memcpy(output, &rd, sizeof(rd)); return TRUE; } int bgp_label2str(char *str, u_char *label) { unsigned long int tmp; char *endp; snprintf(str, 10, "0x%02x%02x%01x", (unsigned)(unsigned char)label[0], (unsigned)(unsigned char)label[1], (unsigned)(unsigned char)(label[2] >> 4)); tmp = strtoul(str, &endp, 16); snprintf(str, 8, "%lu", tmp); return TRUE; } /* Allocate bgp_attr_extra */ struct bgp_attr_extra *bgp_attr_extra_new(struct bgp_info *ri) { struct bgp_misc_structs *bms; struct bgp_attr_extra *new; if (!ri || !ri->peer) return NULL; bms = bgp_select_misc_db(ri->peer->type); if (!bms) return NULL; new = malloc(sizeof(struct bgp_attr_extra)); if (!new) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_attr_extra_new). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } else memset(new, 0, sizeof (struct bgp_attr_extra)); return new; } void bgp_attr_extra_free(struct bgp_peer *peer, struct bgp_attr_extra **attr_extra) { struct bgp_misc_structs *bms; bms = bgp_select_misc_db(peer->type); if (!bms) return; if (attr_extra && (*attr_extra)) { free(*attr_extra); *attr_extra = NULL; } } /* Get bgp_info extra information for the given bgp_info */ struct bgp_attr_extra *bgp_attr_extra_get(struct bgp_info *ri) { if (!ri->attr_extra) { ri->attr_extra = bgp_attr_extra_new(ri); } return ri->attr_extra; } struct bgp_attr_extra *bgp_attr_extra_process(struct bgp_peer *peer, struct bgp_info *ri, afi_t afi, safi_t safi, struct bgp_attr_extra *attr_extra) { struct bgp_attr_extra *rie = NULL; /* Install/update MPLS stuff if required */ if (safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) { if (!rie) { rie = bgp_attr_extra_get(ri); } if (rie) { if (safi == SAFI_MPLS_VPN) { memcpy(&rie->rd, &attr_extra->rd, sizeof(rd_t)); } memcpy(&rie->label, &attr_extra->label, 3); } } /* Install/update BGP ADD-PATHs stuff if required */ if (peer->cap_add_paths.cap[afi][safi]) { if (!rie) { rie = bgp_attr_extra_get(ri); } if (rie) { rie->path_id = attr_extra->path_id; } } /* AIGP attribute */ if (attr_extra->bitmap & BGP_BMAP_ATTR_AIGP) { if (!rie) { rie = bgp_attr_extra_get(ri); } if (rie) { rie->aigp = attr_extra->aigp; rie->bitmap |= BGP_BMAP_ATTR_AIGP; } } /* Prefix-SID attribute: either > 0 or absent */ if (attr_extra->psid_li) { if (!rie) { rie = bgp_attr_extra_get(ri); } if (rie) { rie->psid_li = attr_extra->psid_li; } } if (rie && !(attr_extra->bitmap & BGP_BMAP_ATTR_AIGP)) rie->bitmap &= ~BGP_BMAP_ATTR_AIGP; return rie; } /* Allocate new bgp info structure. */ struct bgp_info *bgp_info_new(struct bgp_peer *peer) { struct bgp_misc_structs *bms; struct bgp_info *new; if (!peer) return NULL; bms = bgp_select_misc_db(peer->type); if (!bms) return NULL; new = malloc(sizeof(struct bgp_info)); if (!new) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_info_new). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } else memset(new, 0, sizeof (struct bgp_info)); return new; } void bgp_info_add(struct bgp_peer *peer, struct bgp_node *rn, struct bgp_info *ri, u_int32_t modulo) { struct bgp_info *top; top = rn->info[modulo]; ri->next = rn->info[modulo]; ri->prev = NULL; if (top) top->prev = ri; rn->info[modulo] = ri; bgp_lock_node(peer, rn); ri->peer->lock++; } void bgp_info_delete(struct bgp_peer *peer, struct bgp_node *rn, struct bgp_info *ri, u_int32_t modulo) { struct bgp_misc_structs *bms; bms = bgp_select_misc_db(peer->type); if (ri->next) { ri->next->prev = ri->prev; } if (ri->prev) { ri->prev->next = ri->next; } else { rn->info[modulo] = ri->next; } bgp_info_free(peer, ri, bms->bgp_extra_data_free); bgp_unlock_node(peer, rn); } /* Free bgp route information. */ void bgp_info_free(struct bgp_peer *peer, struct bgp_info *ri, void (*bgp_extra_data_free)(struct bgp_msg_extra_data *)) { if (ri->attr) bgp_attr_unintern(peer, ri->attr); bgp_attr_extra_free(peer, &ri->attr_extra); if (bgp_extra_data_free) (*bgp_extra_data_free)(&ri->bmed); ri->peer->lock--; free(ri); } /* Initialization of attributes */ void bgp_attr_init(int buckets, struct bgp_rt_structs *inter_domain_routing_db) { aspath_init(buckets, &inter_domain_routing_db->ashash); attrhash_init(buckets, &inter_domain_routing_db->attrhash); community_init(buckets, &inter_domain_routing_db->comhash); ecommunity_init(buckets, &inter_domain_routing_db->ecomhash); lcommunity_init(buckets, &inter_domain_routing_db->lcomhash); } unsigned int attrhash_key_make(void *p) { struct bgp_attr *attr = (struct bgp_attr *) p; unsigned int key = 0; key += attr->origin; key += attr->nexthop.s_addr; key += attr->med; key += attr->local_pref; key += attr->bitmap; if (attr->aspath) key += aspath_key_make(attr->aspath); if (attr->community) key += community_hash_make(attr->community); if (attr->ecommunity) key += ecommunity_hash_make(attr->ecommunity); if (attr->lcommunity) key += lcommunity_hash_make(attr->lcommunity); /* XXX: add mp_nexthop to key */ return key; } int attrhash_cmp(const void *p1, const void *p2) { const struct bgp_attr *attr1 = (const struct bgp_attr *)p1; const struct bgp_attr *attr2 = (const struct bgp_attr *)p2; if (attr1->flag == attr2->flag && attr1->bitmap == attr2->bitmap && attr1->origin == attr2->origin && attr1->nexthop.s_addr == attr2->nexthop.s_addr && attr1->aspath == attr2->aspath && attr1->community == attr2->community && attr1->ecommunity == attr2->ecommunity && attr1->lcommunity == attr2->lcommunity && attr1->med == attr2->med && attr1->local_pref == attr2->local_pref && !host_addr_cmp2((struct host_addr *)&attr1->mp_nexthop, (struct host_addr *)&attr2->mp_nexthop)) return TRUE; return FALSE; } void attrhash_init(int buckets, struct hash **loc_attrhash) { (*loc_attrhash) = (struct hash *) hash_create(buckets, attrhash_key_make, attrhash_cmp); } /* Internet argument attribute. */ struct bgp_attr *bgp_attr_intern(struct bgp_peer *peer, struct bgp_attr *attr) { struct bgp_rt_structs *inter_domain_routing_db; struct bgp_attr *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; /* Intern referenced strucutre. */ if (attr->aspath) { if (! attr->aspath->refcnt) attr->aspath = aspath_intern(peer, attr->aspath); else attr->aspath->refcnt++; } if (attr->community) { if (! attr->community->refcnt) attr->community = community_intern(peer, attr->community); else attr->community->refcnt++; } if (attr->ecommunity) { if (!attr->ecommunity->refcnt) attr->ecommunity = ecommunity_intern(peer, attr->ecommunity); else attr->ecommunity->refcnt++; } if (attr->lcommunity) { if (!attr->lcommunity->refcnt) attr->lcommunity = lcommunity_intern(peer, attr->lcommunity); else attr->lcommunity->refcnt++; } find = (struct bgp_attr *) hash_get(peer, inter_domain_routing_db->attrhash, attr, bgp_attr_hash_alloc); find->refcnt++; return find; } /* Free bgp attribute and aspath. */ void bgp_attr_unintern(struct bgp_peer *peer, struct bgp_attr *attr) { struct bgp_rt_structs *inter_domain_routing_db; struct bgp_misc_structs *bms; struct bgp_attr *ret; struct aspath *aspath; struct community *community; struct ecommunity *ecommunity = NULL; struct lcommunity *lcommunity = NULL; if (!peer) return; inter_domain_routing_db = bgp_select_routing_db(peer->type); bms = bgp_select_misc_db(peer->type); if (!inter_domain_routing_db || !bms) return; /* Decrement attribute reference. */ attr->refcnt--; aspath = attr->aspath; community = attr->community; ecommunity = attr->ecommunity; lcommunity = attr->lcommunity; /* If reference becomes zero then free attribute object. */ if (attr->refcnt == 0) { ret = (struct bgp_attr *) hash_release(inter_domain_routing_db->attrhash, attr); // assert (ret != NULL); if (!ret) Log(LOG_INFO, "INFO ( %s/%s ): bgp_attr_unintern() hash lookup failed.\n", config.name, bms->log_str); free(attr); } /* aspath refcount shoud be decrement. */ if (aspath) aspath_unintern(peer, aspath); if (community) community_unintern(peer, community); if (ecommunity) ecommunity_unintern(peer, ecommunity); if (lcommunity) lcommunity_unintern(peer, lcommunity); } void *bgp_attr_hash_alloc(void *p) { struct bgp_attr *val = (struct bgp_attr *) p; struct bgp_attr *attr; attr = malloc(sizeof (struct bgp_attr)); if (!attr) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (bgp_attr_hash_alloc). Exiting ..\n", config.name); // XXX exit_gracefully(1); } else { memset(attr, 0, sizeof (struct bgp_attr)); memcpy(attr, val, sizeof (struct bgp_attr)); attr->refcnt = 0; } return attr; } void bgp_peer_cache_init(struct bgp_peer_cache_bucket *cache, u_int32_t buckets) { u_int32_t idx; for (idx = 0; idx < buckets; idx++) { memset(&cache[idx], 0, sizeof(struct bgp_peer_cache_bucket)); pthread_mutex_init(&cache[idx].mutex, NULL); } } struct bgp_peer_cache *bgp_peer_cache_insert(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct bgp_peer *peer) { struct bgp_peer_cache *cursor, *last, *new, *ret = NULL; pthread_mutex_lock(&peers_cache[bucket].mutex); for (cursor = peers_cache[bucket].e, last = NULL; cursor; cursor = cursor->next) last = cursor; new = malloc(sizeof(struct bgp_peer_cache)); if (new) { new->ptr = peer; new->next = NULL; if (!last) peers_cache[bucket].e = new; else last->next = new; ret = new; } pthread_mutex_unlock(&peers_cache[bucket].mutex); return ret; } int bgp_peer_cache_delete(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct bgp_peer *peer) { struct bgp_peer_cache *cursor, *last; int ret = ERR; pthread_mutex_lock(&peers_cache[bucket].mutex); for (cursor = peers_cache[bucket].e, last = NULL; cursor; cursor = cursor->next) { if (cursor->ptr == peer) { if (!last) peers_cache[bucket].e = cursor->next; else last->next = cursor->next; free(cursor); ret = SUCCESS; break; } last = cursor; } pthread_mutex_unlock(&peers_cache[bucket].mutex); return ret; } struct bgp_peer *bgp_peer_cache_search(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct host_addr *ha, u_int16_t port) { struct bgp_peer_cache *cursor; struct bgp_peer *ret = NULL; pthread_mutex_lock(&peers_cache[bucket].mutex); for (cursor = peers_cache[bucket].e; cursor; cursor = cursor->next) { if (port) { if (cursor->ptr->tcp_port != port) continue; } if (!host_addr_cmp(&cursor->ptr->addr, ha)) { ret = cursor->ptr; break; } } pthread_mutex_unlock(&peers_cache[bucket].mutex); return ret; } int bgp_peer_init(struct bgp_peer *peer, int type) { struct bgp_misc_structs *bms; int ret = TRUE; bms = bgp_select_misc_db(type); if (!peer || !bms) return ERR; memset(peer, 0, sizeof(struct bgp_peer)); peer->type = type; peer->status = Idle; peer->buf.tot_len = BGP_BUFFER_SIZE; peer->buf.base = malloc(peer->buf.tot_len); if (!peer->buf.base) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_peer_init). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } else { memset(peer->buf.base, 0, peer->buf.tot_len); ret = FALSE; } if (config.bgp_xconnect_map) { peer->xbuf.tot_len = BGP_BUFFER_SIZE; peer->xbuf.base = malloc(peer->xbuf.tot_len); if (!peer->xbuf.base) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_peer_init). Exiting ..\n", config.name, bms->log_str); exit_gracefully(1); } else { memset(peer->xbuf.base, 0, peer->xbuf.tot_len); ret = FALSE; } } return ret; } void bgp_peer_close(struct bgp_peer *peer, int type, int no_quiet, int send_notification, u_int8_t n_major, u_int8_t n_minor, char *shutdown_msg) { struct bgp_misc_structs *bms; if (!peer) return; bms = bgp_select_misc_db(peer->type); if (!bms) return; if (!config.bgp_xconnect_map) { if (send_notification) { int ret, notification_msglen = (BGP_MIN_NOTIFICATION_MSG_SIZE + BGP_NOTIFY_CEASE_SM_LEN + 1); char notification_msg[notification_msglen]; ret = bgp_write_notification_msg(notification_msg, notification_msglen, n_major, n_minor, shutdown_msg); if (ret) send(peer->fd, notification_msg, ret, 0); } /* be quiet if we are in a signal handler and already set to exit */ if (!no_quiet) bgp_peer_info_delete(peer); if (bms->msglog_file || bms->msglog_amqp_routing_key || bms->msglog_kafka_topic) bgp_peer_log_close(peer, bms->tag, bms->msglog_output, peer->type); if (bms->peers_cache && bms->peers_port_cache) { u_int32_t bucket; bucket = addr_hash(&peer->addr, bms->max_peers); bgp_peer_cache_delete(bms->peers_cache, bucket, peer); bucket = addr_port_hash(&peer->addr, peer->tcp_port, bms->max_peers); bgp_peer_cache_delete(bms->peers_port_cache, bucket, peer); } } else { if (peer->xconnect_fd && peer->xconnect_fd != ERR) close(peer->xconnect_fd); } if (peer->fd && peer->fd != ERR) close(peer->fd); peer->fd = 0; memset(&peer->xc, 0, sizeof(peer->xc)); peer->xconnect_fd = 0; memset(&peer->id, 0, sizeof(peer->id)); memset(&peer->addr, 0, sizeof(peer->addr)); memset(&peer->addr_str, 0, sizeof(peer->addr_str)); free(peer->buf.base); if (config.bgp_xconnect_map) { free(peer->xbuf.base); } if (bms->neighbors_file) { write_neighbors_file(bms->neighbors_file, peer->type); } if (bms->peers_limit_log) { log_notification_unset(bms->peers_limit_log); } } int bgp_peer_xconnect_init(struct bgp_peer *peer, int type) { char peer_str[INET6_ADDRSTRLEN], xconnect_str[BGP_XCONNECT_STRLEN]; struct bgp_misc_structs *bms; struct bgp_xconnects *bxm; int ret = TRUE, idx, fd; assert(!peer->xconnect_fd); bms = bgp_select_misc_db(type); if (!peer || !bms) return ERR; bxm = bms->xconnects; if (bxm) { for (idx = 0; idx < bxm->num; idx++) { if (!sa_addr_cmp((struct sockaddr *) &bxm->pool[idx].src, &peer->addr) || !host_addr_mask_cmp(&bxm->pool[idx].src_addr, &bxm->pool[idx].src_mask, &peer->addr)) { struct sockaddr *sa = (struct sockaddr *) &bxm->pool[idx].dst; memcpy(&peer->xc, &bxm->pool[idx], sizeof(struct bgp_xconnect)); bgp_peer_xconnect_print(peer, xconnect_str, BGP_XCONNECT_STRLEN); fd = socket(sa->sa_family, SOCK_STREAM, 0); if (fd == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bgp_peer_xconnect_init(): socket() failed.\n", config.name, bms->log_str, xconnect_str); memset(&peer->xc, 0, sizeof(peer->xc)); peer->xconnect_fd = 0; return ERR; } ret = connect(fd, sa, bxm->pool[idx].dst_len); if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bgp_peer_xconnect_init(): connect() failed.\n", config.name, bms->log_str, xconnect_str); memset(&peer->xc, 0, sizeof(peer->xc)); close(fd); peer->xconnect_fd = 0; return ERR; } peer->xconnect_fd = fd; break; } } if (!peer->xconnect_fd) { bgp_peer_print(peer, peer_str, INET6_ADDRSTRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] unable to xconnect BGP peer. Missing entry in bgp_daemon_xconnect_map.\n", config.name, bgp_misc_db->log_str, peer_str); } } return ret; } void bgp_peer_print(struct bgp_peer *peer, char *buf, int len) { char dumb_buf[] = "0.0.0.0"; int ret = 0; if (!buf || len < INET6_ADDRSTRLEN) return; if (peer) { if (peer->id.family) { inet_ntop(AF_INET, &peer->id.address.ipv4, buf, len); ret = AF_INET; } else ret = addr_to_str(buf, &peer->addr); } if (!ret) strcpy(buf, dumb_buf); } void bgp_peer_xconnect_print(struct bgp_peer *peer, char *buf, int len) { char src[INET6_ADDRSTRLEN + PORT_STRLEN + 1], dst[INET6_ADDRSTRLEN + PORT_STRLEN + 1]; struct sockaddr *sa_src; struct sockaddr *sa_dst; if (peer && buf && len >= BGP_XCONNECT_STRLEN) { sa_src = (struct sockaddr *) &peer->xc.src; sa_dst = (struct sockaddr *) &peer->xc.dst; if (sa_src->sa_family) sa_to_str(src, sizeof(src), sa_src, TRUE); else addr_mask_to_str(src, sizeof(src), &peer->xc.src_addr, &peer->xc.src_mask); sa_to_str(dst, sizeof(dst), sa_dst, TRUE); snprintf(buf, len, "%s x %s", src, dst); } } void bgp_peer_info_delete(struct bgp_peer *peer) { struct bgp_rt_structs *inter_domain_routing_db = bgp_select_routing_db(peer->type); struct bgp_table *table; afi_t afi; safi_t safi; if (!inter_domain_routing_db) return; for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { table = inter_domain_routing_db->rib[afi][safi]; bgp_table_info_delete(peer, table, afi, safi); } } } void bgp_table_info_delete(struct bgp_peer *peer, struct bgp_table *table, afi_t afi, safi_t safi) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); struct bgp_node *node; /* Being tag_map limited to 'ip' key lookups, this is finely placed here. Should further lookups be possible, this may be very possibly moved inside the loop */ if (bms->tag_map && bms->bgp_table_info_delete_tag_find) { bms->bgp_table_info_delete_tag_find(peer); } node = bgp_table_top(peer, table); while (node) { u_int32_t modulo; u_int32_t peer_buckets; struct bgp_info *ri; struct bgp_info *ri_next; if (bms->route_info_modulo) modulo = bms->route_info_modulo(peer, NULL, bms->table_per_peer_buckets); else modulo = 0; for (peer_buckets = 0; peer_buckets < bms->table_per_peer_buckets; peer_buckets++) { for (ri = node->info[modulo + peer_buckets]; ri; ri = ri_next) { if (ri->peer == peer) { if (bms->msglog_backend_methods) { char event_type[] = "log"; bgp_peer_log_msg(node, ri, afi, safi, bms->tag, event_type, bms->msglog_output, NULL, BGP_LOG_TYPE_DELETE); } ri_next = ri->next; /* let's save pointer to next before free up */ bgp_info_delete(peer, node, ri, (modulo + peer_buckets)); } else ri_next = ri->next; } } node = bgp_route_next(peer, node); } } int bgp_attr_munge_as4path(struct bgp_peer *peer, struct bgp_attr *attr, struct aspath *as4path) { struct aspath *newpath; /* If the BGP peer supports 32bit AS_PATH then we are done */ if (peer->cap_4as) return SUCCESS; /* pre-requisite for AS4_PATH is AS_PATH indeed */ // XXX if (as4path && !attr->aspath) return ERR; newpath = aspath_reconcile_as4(attr->aspath, as4path); aspath_unintern(peer, attr->aspath); attr->aspath = aspath_intern(peer, newpath); return SUCCESS; } void load_comm_patterns(char **stdcomm, char **extcomm, char **lrgcomm, char **stdcomm_to_asn, char **lrgcomm_to_asn) { int idx; char *token; memset(std_comm_patterns, 0, sizeof(std_comm_patterns)); memset(ext_comm_patterns, 0, sizeof(ext_comm_patterns)); memset(lrg_comm_patterns, 0, sizeof(lrg_comm_patterns)); memset(std_comm_patterns_to_asn, 0, sizeof(std_comm_patterns_to_asn)); memset(lrg_comm_patterns_to_asn, 0, sizeof(lrg_comm_patterns_to_asn)); if (*stdcomm) { idx = 0; while ( (token = extract_token(stdcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { std_comm_patterns[idx] = token; trim_spaces(std_comm_patterns[idx]); idx++; } } if (*extcomm) { idx = 0; while ( (token = extract_token(extcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { ext_comm_patterns[idx] = token; trim_spaces(ext_comm_patterns[idx]); idx++; } } if (*lrgcomm) { idx = 0; while ( (token = extract_token(lrgcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { lrg_comm_patterns[idx] = token; trim_spaces(lrg_comm_patterns[idx]); idx++; } } if (*stdcomm_to_asn) { idx = 0; while ( (token = extract_token(stdcomm_to_asn, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { std_comm_patterns_to_asn[idx] = token; trim_spaces(std_comm_patterns_to_asn[idx]); idx++; } } if (*lrgcomm_to_asn) { idx = 0; while ( (token = extract_token(lrgcomm_to_asn, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { lrg_comm_patterns_to_asn[idx] = token; trim_spaces(lrg_comm_patterns_to_asn[idx]); idx++; } } } void evaluate_comm_patterns(char *dst, char *src, char **patterns, int dstlen) { char *ptr, *haystack, *delim_src, *delim_ptn; char local_ptr[MAX_BGP_STD_COMMS], *auxptr; int idx, i, j; if (!src || !dst || !dstlen) return; memset(dst, 0, dstlen); for (idx = 0, j = 0; patterns[idx]; idx++) { haystack = src; find_again: delim_ptn = strchr(patterns[idx], '.'); if (delim_ptn) *delim_ptn = '\0'; ptr = strstr(haystack, patterns[idx]); if (ptr && delim_ptn) { delim_src = strchr(ptr, ' '); if (delim_src) { memcpy(local_ptr, ptr, delim_src-ptr); local_ptr[delim_src-ptr] = '\0'; } else memcpy(local_ptr, ptr, strlen(ptr)+1); *delim_ptn = '.'; if (strlen(local_ptr) != strlen(patterns[idx])) ptr = NULL; else { for (auxptr = strchr(patterns[idx], '.'); auxptr; auxptr = strchr(auxptr, '.')) { local_ptr[auxptr-patterns[idx]] = '.'; auxptr++; } if (strncmp(patterns[idx], local_ptr, strlen(patterns[idx]))) ptr = NULL; } } else if (delim_ptn) *delim_ptn = '.'; if (ptr) { /* If we have already something on the stack, let's insert a space */ if (j && j < dstlen) { dst[j] = ' '; j++; } /* We should be able to trust this string */ for (i = 0; ptr[i] != ' ' && ptr[i] != '\0'; i++, j++) { if (j < dstlen) dst[j] = ptr[i]; else break; } haystack = &ptr[i]; } /* If we don't have space anymore, let's finish it here */ if (j >= dstlen) { dst[dstlen-2] = '+'; dst[dstlen-1] = '\0'; break; } /* Trick to find multiple occurrences */ if (ptr) goto find_again; } } as_t evaluate_last_asn(struct aspath *as) { if (!as) return 0; return as->last_as; } as_t evaluate_first_asn(char *src) { int idx, is_space = FALSE, len = strlen(src), start, sub_as, iteration; char *endptr, *ptr, saved; as_t asn, real_first_asn; start = 0; iteration = 0; real_first_asn = 0; start_again: asn = 0; sub_as = FALSE; for (idx = start; idx < len && (src[idx] != ' ' && src[idx] != ')'); idx++); /* Mangling the AS_PATH string */ if (src[idx] == ' ' || src[idx] == ')') { is_space = TRUE; saved = src[idx]; src[idx] = '\0'; } if (src[start] == '(') { ptr = &src[start+1]; sub_as = TRUE; } else ptr = &src[start]; asn = strtoul(ptr, &endptr, 10); /* Restoring mangled AS_PATH */ if (is_space) { src[idx] = saved; saved = '\0'; is_space = FALSE; } if (config.bgp_daemon_peer_as_skip_subas /* XXX */ && sub_as) { while (idx < len && (src[idx] == ' ' || src[idx] == ')')) idx++; if (idx != len-1) { start = idx; if (iteration == 0) real_first_asn = asn; iteration++; goto start_again; } } /* skip sub-as kicks-in only when traffic is delivered to a different ASN */ if (real_first_asn && (!asn || sub_as)) asn = real_first_asn; return asn; } void evaluate_bgp_aspath_radius(char *path, int len, int radius) { int count, idx; for (idx = 0, count = 0; idx < len; idx++) { if (path[idx] == ' ') count++; if (count == radius) { path[idx] = '\0'; break; } } } void copy_stdcomm_to_asn(char *stdcomm, as_t *asn, int is_origin) { char *delim, *delim2; char *p1, *p2; if (!stdcomm || !strlen(stdcomm) || (delim = strchr(stdcomm, ':')) == NULL) return; if (validate_truefalse(is_origin)) return; delim2 = strchr(stdcomm, ','); *delim = '\0'; if (delim2) *delim2 = '\0'; p1 = stdcomm; p2 = delim+1; if (is_origin) *asn = atoi(p2); else *asn = atoi(p1); } void copy_lrgcomm_to_asn(char *lrgcomm, as_t *asn, int is_origin) { char *delim, *delim2; char *p1, *p2, *endptr; if (!lrgcomm || !strlen(lrgcomm) || (delim = strchr(lrgcomm, ':')) == NULL) return; if (validate_truefalse(is_origin)) return; delim2 = strchr(lrgcomm, ':'); *delim = '\0'; *delim2 = '\0'; p1 = lrgcomm; p2 = delim+1; if (is_origin) *asn = strtoul(p2, &endptr, 10); else *asn = strtoul(p1, &endptr, 10); } /* XXX: currently only BGP is supported due to use of peers struct */ void write_neighbors_file(char *filename, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); FILE *file; char neighbor[INET6_ADDRSTRLEN+1]; int idx, len, ret; uid_t owner = -1; gid_t group = -1; if (!bms) return; unlink(filename); if (config.files_uid) owner = config.files_uid; if (config.files_gid) group = config.files_gid; file = fopen(filename,"w"); if (file) { if ((ret = chown(filename, owner, group)) == -1) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown() (%s).\n", config.name, bms->log_str, filename, strerror(errno)); if (file_lock(fileno(file))) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, bms->log_str, filename); return; } for (idx = 0; idx < bms->max_peers; idx++) { if (peers[idx].fd) { if (peers[idx].addr.family == AF_INET) { inet_ntop(AF_INET, &peers[idx].addr.address.ipv4, neighbor, INET6_ADDRSTRLEN); len = strlen(neighbor); neighbor[len] = '\n'; len++; neighbor[len] = '\0'; fwrite(neighbor, len, 1, file); } else if (peers[idx].addr.family == AF_INET6) { inet_ntop(AF_INET6, &peers[idx].addr.address.ipv6, neighbor, INET6_ADDRSTRLEN); len = strlen(neighbor); neighbor[len] = '\n'; len++; neighbor[len] = '\0'; fwrite(neighbor, len, 1, file); } } } file_unlock(fileno(file)); fclose(file); } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, bms->log_str, filename); return; } } void bgp_config_checks(struct configuration *c) { if (c->what_to_count & (COUNT_LOCAL_PREF|COUNT_MED|COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS| COUNT_PEER_SRC_IP|COUNT_PEER_DST_IP|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF| COUNT_MPLS_VPN_RD)) { /* Sanitizing the aggregation method */ if ( (c->what_to_count & COUNT_SRC_LOCAL_PREF && !c->bgp_daemon_src_local_pref_type) || (c->what_to_count & COUNT_SRC_MED && !c->bgp_daemon_src_med_type) || (c->what_to_count & COUNT_PEER_SRC_AS && !c->bgp_daemon_peer_as_src_type && (config.acct_type != ACCT_SF && config.acct_type != ACCT_NF)) ) { printf("ERROR: At least one of the following primitives is in use but its source type is not specified:\n"); printf(" peer_src_as => bgp_peer_src_as_type\n"); printf(" src_local_pref => bgp_src_local_pref_type\n"); printf(" src_med => bgp_src_med_type\n"); exit_gracefully(1); } c->data_type |= PIPE_TYPE_BGP; } if ((c->what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_AS_PATH|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH)) || (c->what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM))) { /* Sanitizing the aggregation method */ if ( (c->what_to_count & COUNT_SRC_AS_PATH && !c->bgp_daemon_src_as_path_type) || (c->what_to_count & COUNT_SRC_STD_COMM && !c->bgp_daemon_src_std_comm_type) || (c->what_to_count & COUNT_SRC_EXT_COMM && !c->bgp_daemon_src_ext_comm_type) || (c->what_to_count_2 & COUNT_SRC_LRG_COMM && !c->bgp_daemon_src_lrg_comm_type) ) { printf("ERROR: At least one of the following primitives is in use but its source type is not specified:\n"); printf(" src_as_path => bgp_src_as_path_type\n"); printf(" src_std_comm => bgp_src_std_comm_type\n"); printf(" src_ext_comm => bgp_src_ext_comm_type\n"); printf(" src_lrg_comm => bgp_src_lrg_comm_type\n"); exit_gracefully(1); } if (c->type_id == PLUGIN_ID_MEMORY) c->data_type |= PIPE_TYPE_LBGP; else c->data_type |= PIPE_TYPE_VLEN; } } void bgp_md5_file_init(struct bgp_md5_table *t) { if (t) memset(t, 0, sizeof(struct bgp_md5_table)); } void bgp_md5_file_load(char *filename, struct bgp_md5_table *t) { FILE *file; char buf[SRVBUFLEN], *ptr; int index = 0; if (filename && t) { Log(LOG_INFO, "INFO ( %s/core/BGP ): [%s] (re)loading map.\n", config.name, filename); if ((file = fopen(filename, "r")) == NULL) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): [%s] file not found.\n", config.name, filename); exit_gracefully(1); } while (!feof(file)) { if (index >= BGP_MD5_MAP_ENTRIES) { Log(LOG_WARNING, "WARN ( %s/core/BGP ): [%s] loaded the first %u entries.\n", config.name, filename, BGP_MD5_MAP_ENTRIES); break; } memset(buf, 0, SRVBUFLEN); if (fgets(buf, SRVBUFLEN, file)) { if (!sanitize_buf(buf)) { char *token; int tk_idx = 0, ret = 0, len = 0; ptr = buf; memset(&t->table[index], 0, sizeof(t->table[index])); while ( (token = extract_token(&ptr, ',')) && tk_idx < 2 ) { if (tk_idx == 0) ret = str_to_addr(token, &t->table[index].addr); else if (tk_idx == 1) { strlcpy(t->table[index].key, token, TCP_MD5SIG_MAXKEYLEN); len = strlen(t->table[index].key); } tk_idx++; } if (ret > 0 && len > 0) index++; else Log(LOG_WARNING, "WARN ( %s/core/BGP ): [%s] line '%s' ignored.\n", config.name, filename, buf); } } } t->num = index; /* Set to -1 to distinguish between no map and empty map conditions */ if (!t->num) t->num = -1; Log(LOG_INFO, "INFO ( %s/core/BGP ): [%s] map successfully (re)loaded.\n", config.name, filename); fclose(file); } } void bgp_md5_file_unload(struct bgp_md5_table *t) { int index = 0; if (!t) return; while (index < t->num) { memset(t->table[index].key, 0, TCP_MD5SIG_MAXKEYLEN); index++; } } void bgp_md5_file_process(int sock, struct bgp_md5_table *bgp_md5) { char peer_str[INET6_ADDRSTRLEN + PORT_STRLEN + 1]; struct pm_tcp_md5sig md5sig; struct sockaddr_storage ss_md5sig, ss_server; struct sockaddr *sa_md5sig = (struct sockaddr *)&ss_md5sig, *sa_server = (struct sockaddr *)&ss_server; int rc, keylen, idx = 0, ss_md5sig_len; socklen_t ss_server_len; if (!bgp_md5) return; while (idx < bgp_md5->num) { memset(&md5sig, 0, sizeof(md5sig)); memset(&ss_md5sig, 0, sizeof(ss_md5sig)); ss_md5sig_len = addr_to_sa((struct sockaddr *)&ss_md5sig, &bgp_md5->table[idx].addr, 0); ss_server_len = sizeof(ss_server); getsockname(sock, (struct sockaddr *)&ss_server, &ss_server_len); if (sa_md5sig->sa_family == AF_INET6 && sa_server->sa_family == AF_INET) { ipv4_mapped_to_ipv4(&ss_md5sig); ss_md5sig_len = sizeof(struct sockaddr_in); } else if (sa_md5sig->sa_family == AF_INET && sa_server->sa_family == AF_INET6) { ipv4_to_ipv4_mapped(&ss_md5sig); ss_md5sig_len = sizeof(struct sockaddr_in6); } memcpy(&md5sig.tcpm_addr, &ss_md5sig, ss_md5sig_len); keylen = strlen(bgp_md5->table[idx].key); if (keylen) { md5sig.tcpm_keylen = keylen; memcpy(md5sig.tcpm_key, &bgp_md5->table[idx].key, keylen); } sa_to_str(peer_str, sizeof(peer_str), sa_md5sig, TRUE); rc = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, (socklen_t) sizeof(md5sig)); if (rc < 0) { Log(LOG_WARNING, "WARN ( %s/core/BGP ): setsockopt() failed for TCP_MD5SIG peer=%s (errno: %d)\n", config.name, peer_str, errno); } else { Log(LOG_DEBUG, "DEBUG ( %s/core/BGP ): setsockopt() set TCP_MD5SIG peer=%s\n", config.name, peer_str); } idx++; } } void bgp_batch_init(struct bgp_peer_batch *bp_batch, int num, int interval) { if (bp_batch) { memset(bp_batch, 0, sizeof(struct bgp_peer_batch)); bp_batch->num = num; bp_batch->interval = interval; } } void bgp_batch_reset(struct bgp_peer_batch *bp_batch, time_t now) { if (bp_batch) { bp_batch->num_current = bp_batch->num; bp_batch->base_stamp = now; } } int bgp_batch_is_admitted(struct bgp_peer_batch *bp_batch, time_t now) { if (bp_batch) { /* bgp_batch_is_not_empty() maybe replaced by a linear distribution of the peers over the time interval */ if (bgp_batch_is_not_empty(bp_batch) || bgp_batch_is_expired(bp_batch, now)) return TRUE; else return FALSE; } else return ERR; } int bgp_batch_is_enabled(struct bgp_peer_batch *bp_batch) { if (bp_batch) { if (bp_batch->num) return TRUE; else return FALSE; } else return ERR; } int bgp_batch_is_expired(struct bgp_peer_batch *bp_batch, time_t now) { if (bp_batch) { if (now > (bp_batch->base_stamp + bp_batch->interval)) return TRUE; else return FALSE; } else return ERR; } int bgp_batch_is_not_empty(struct bgp_peer_batch *bp_batch) { if (bp_batch) { if (bp_batch->num_current) return TRUE; else return FALSE; } else return ERR; } void bgp_batch_increase_counter(struct bgp_peer_batch *bp_batch) { if (bp_batch) bp_batch->num_current++; } void bgp_batch_decrease_counter(struct bgp_peer_batch *bp_batch) { if (bp_batch) bp_batch->num_current--; } void bgp_batch_rollback(struct bgp_peer_batch *bp_batch) { if (bp_batch && bgp_batch_is_enabled(bp_batch)) { bgp_batch_increase_counter(bp_batch); if (bp_batch->num_current == bp_batch->num) bgp_batch_init(bp_batch, bp_batch->num, bp_batch->interval); } } struct bgp_rt_structs *bgp_select_routing_db(int peer_type) { if (peer_type < FUNC_TYPE_MAX) return &inter_domain_routing_dbs[peer_type]; return NULL; } struct bgp_misc_structs *bgp_select_misc_db(int peer_type) { if (peer_type < FUNC_TYPE_MAX) return &inter_domain_misc_dbs[peer_type]; return NULL; } void bgp_link_misc_structs(struct bgp_misc_structs *bms) { #if defined WITH_RABBITMQ bms->msglog_amqp_host = &bgp_daemon_msglog_amqp_host; #endif #if defined WITH_KAFKA bms->msglog_kafka_host = &bgp_daemon_msglog_kafka_host; #endif bms->max_peers = config.bgp_daemon_max_peers; bms->peers = peers; bms->peers_cache = peers_cache; bms->peers_port_cache = peers_port_cache; bms->peers_limit_log = &log_notifications.bgp_peers_limit; bms->xconnects = &bgp_xcs_map; bms->neighbors_file = config.bgp_daemon_neighbors_file; bms->dump_file = config.bgp_table_dump_file; bms->dump_amqp_routing_key = config.bgp_table_dump_amqp_routing_key; bms->dump_amqp_routing_key_rr = config.bgp_table_dump_amqp_routing_key_rr; bms->dump_kafka_topic = config.bgp_table_dump_kafka_topic; bms->dump_kafka_topic_rr = config.bgp_table_dump_kafka_topic_rr; bms->dump_kafka_partition_key = config.bgp_table_dump_kafka_partition_key; bms->dump_kafka_avro_schema_registry = config.bgp_table_dump_kafka_avro_schema_registry; bms->msglog_file = config.bgp_daemon_msglog_file; bms->msglog_output = config.bgp_daemon_msglog_output; bms->msglog_amqp_routing_key = config.bgp_daemon_msglog_amqp_routing_key; bms->msglog_amqp_routing_key_rr = config.bgp_daemon_msglog_amqp_routing_key_rr; bms->msglog_kafka_topic = config.bgp_daemon_msglog_kafka_topic; bms->msglog_kafka_topic_rr = config.bgp_daemon_msglog_kafka_topic_rr; bms->msglog_kafka_partition_key = config.bgp_daemon_msglog_kafka_partition_key; bms->msglog_kafka_avro_schema_registry = config.bgp_daemon_msglog_kafka_avro_schema_registry; bms->peer_str = malloc(strlen("peer_ip_src") + 1); strcpy(bms->peer_str, "peer_ip_src"); bms->peer_port_str = malloc(strlen("peer_tcp_port") + 1); strcpy(bms->peer_port_str, "peer_tcp_port"); bms->bgp_peer_log_msg_extras = NULL; bms->bgp_peer_logdump_initclose_extras = NULL; bms->table_peer_buckets = config.bgp_table_peer_buckets; bms->table_per_peer_buckets = config.bgp_table_per_peer_buckets; bms->table_attr_hash_buckets = config.bgp_table_attr_hash_buckets; bms->table_per_peer_hash = config.bgp_table_per_peer_hash; bms->route_info_modulo = bgp_route_info_modulo; bms->bgp_lookup_find_peer = bgp_lookup_find_bgp_peer; bms->bgp_lookup_node_match_cmp = bgp_lookup_node_match_cmp_bgp; bms->bgp_msg_open_router_id_check = bgp_router_id_check; if (!bms->is_thread && !bms->dump_backend_methods && !bms->has_lglass && !bms->has_blackhole) { bms->skip_rib = TRUE; } bms->cap_add_path_ignore = config.bgp_daemon_add_path_ignore; bms->tag = &bgp_logdump_tag; bms->tag_map = config.bgp_daemon_tag_map; bms->tag_peer = &bgp_logdump_tag_peer; } void bgp_blackhole_link_misc_structs(struct bgp_misc_structs *m_data) { m_data->table_peer_buckets = 1; /* saving on DEFAULT_BGP_INFO_HASH for now */ m_data->table_per_peer_buckets = DEFAULT_BGP_INFO_PER_PEER_HASH; m_data->table_attr_hash_buckets = HASHTABSIZE; m_data->table_per_peer_hash = BGP_ASPATH_HASH_PATHID; m_data->route_info_modulo = NULL; m_data->bgp_lookup_node_match_cmp = NULL; } int bgp_peer_cmp(const void *a, const void *b) { return host_addr_cmp(&((struct bgp_peer *)a)->addr, &((struct bgp_peer *)b)->addr); } int bgp_peer_host_addr_cmp(const void *a, const void *b) { return host_addr_cmp((struct host_addr *)a, &((struct bgp_peer *)b)->addr); } int bgp_peer_sa_addr_cmp(const void *a, const void *b) { return sa_addr_cmp((struct sockaddr *) a, &((struct bgp_peer *)b)->addr); } void bgp_peer_free(void *a) { free((char *)a); } int bgp_peers_bintree_walk_print(const void *nodep, const pm_VISIT which, const int depth, void *extra) { struct bgp_misc_structs *bms; struct bgp_peer *peer; char peer_str[INET6_ADDRSTRLEN]; peer = (*(struct bgp_peer **) nodep); bms = bgp_select_misc_db(peer->type); if (!bms) return FALSE; if (!peer) Log(LOG_INFO, "INFO ( %s/%s ): bgp_peers_bintree_walk_print(): null\n", config.name, bms->log_str); else { addr_to_str(peer_str, &peer->addr); Log(LOG_INFO, "INFO ( %s/%s ): bgp_peers_bintree_walk_print(): %s\n", config.name, bms->log_str, peer_str); } return TRUE; } int bgp_peers_bintree_walk_delete(const void *nodep, const pm_VISIT which, const int depth, void *extra) { struct bgp_misc_structs *bms; struct bgp_peer *peer; peer = (*(struct bgp_peer **) nodep); if (!peer) return FALSE; bms = bgp_select_misc_db(peer->type); if (!bms) return FALSE; bgp_peer_info_delete(peer); // XXX: count tree elements to index and free() later return TRUE; } int bgp_router_id_check(struct bgp_msg_data *bmd) { struct bgp_peer *peer = bmd->peer; struct bgp_misc_structs *bms; struct bgp_peer *peers_check; int peers_check_idx = 0; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; peers_check = bms->peers; for (; peers_check_idx < bms->max_peers; peers_check_idx++) { if (peers_check_idx != peer->idx && !memcmp(&peers_check[peers_check_idx].id, &peer->id, sizeof(peers_check[peers_check_idx].id))) { char bgp_peer_str[INET6_ADDRSTRLEN]; bgp_peer_print(&peers_check[peers_check_idx], bgp_peer_str, INET6_ADDRSTRLEN); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Refusing new connection from existing Router-ID.\n", config.name, bms->log_str, bgp_peer_str); return ERR; } } return FALSE; } /* utility function when an ASN is prepended by 'AS', 'AS ', etc. strings that need to be stripped. */ int bgp_str2asn(char *asn_str, as_t *asn) { char *endptr, *asn_ptr = asn_str; int len, cnt; if (!asn_str || !asn) return ERR; len = strlen(asn_str); for (cnt = 0; !isdigit(asn_str[cnt]) && (cnt < len); cnt++); asn_ptr = &asn_str[cnt]; (*asn) = strtoul(asn_ptr, &endptr, 10); if (endptr == asn_ptr || (*endptr) != '\0') return ERR; if (errno) { errno = FALSE; return ERR; } return SUCCESS; } const char *bgp_origin_print(u_int8_t origin) { if (origin <= BGP_ORIGIN_MAX) return bgp_origin[origin]; else return bgp_origin[BGP_ORIGIN_UNKNOWN]; } u_int8_t bgp_str2origin(char *origin_str) { if (!strcmp(origin_str, "i")) return BGP_ORIGIN_IGP; else if (!strcmp(origin_str, "e")) return BGP_ORIGIN_EGP; else if (!strcmp(origin_str, "u")) return BGP_ORIGIN_INCOMPLETE; return BGP_ORIGIN_UNKNOWN; } u_int16_t bgp_get_packet_len(char *pkt) { struct bgp_header *bhdr = (struct bgp_header *) pkt; u_int16_t blen = 0; if (bgp_marker_check(bhdr, BGP_MARKER_SIZE) != ERR) { blen = ntohs(bhdr->bgpo_len); } return blen; } u_int8_t bgp_get_packet_type(char *pkt) { struct bgp_header *bhdr = (struct bgp_header *) pkt; u_int8_t btype = 0; if (bgp_marker_check(bhdr, BGP_MARKER_SIZE) != ERR) { btype = bhdr->bgpo_type; } return btype; } void bgp_table_info_delete_tag_find_bgp(struct bgp_peer *peer) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); bgp_tag_init_find(peer, (struct sockaddr *) bms->tag_peer, bms->tag); bgp_tag_find((struct id_table *)bms->tag->tag_table, bms->tag, &bms->tag->tag, NULL); } pmacct-1.7.8/src/bgp/bgp_aspath.c0000644000175000017500000007167714354105275015647 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* Originally based on Quagga AS path management routines which is: Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro Copyright (C) 2005 Sun Microsystems, Inc. GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "jhash.h" #include "bgp.h" void * assegment_data_new (int num) { return (malloc(ASSEGMENT_DATA_SIZE (num, TRUE))); } __attribute__((unused)) static inline void assegment_data_free (as_t *asdata) { free(asdata); } /* Get a new segment. Note that 0 is an allowed length, * and will result in a segment with no allocated data segment. * the caller should immediately assign data to the segment, as the segment * otherwise is not generally valid */ static struct assegment * assegment_new (u_char type, u_short length) { struct assegment *new; new = malloc(sizeof (struct assegment)); if (!new) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (assegment_new: new). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset(new, 0, sizeof (struct assegment)); if (length) { new->as = assegment_data_new (length); if (!new->as) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (assegment_new: new->as). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset(new->as, 0, length); } new->length = length; new->type = type; return new; } static void assegment_free (struct assegment *seg) { if (!seg) return; if (seg->as) free(seg->as); memset (seg, 0xfe, sizeof(struct assegment)); free(seg); return; } /* free entire chain of segments */ static void assegment_free_all (struct assegment *seg) { struct assegment *prev; while (seg) { prev = seg; seg = seg->next; assegment_free (prev); } } /* Duplicate just the given assegment and its data */ static struct assegment * assegment_dup (struct assegment *seg) { struct assegment *new; new = assegment_new (seg->type, seg->length); memcpy (new->as, seg->as, ASSEGMENT_DATA_SIZE (new->length, TRUE /* 32-bit ASN */) ); return new; } /* Duplicate entire chain of assegments, return the head */ static struct assegment * assegment_dup_all (struct assegment *seg) { struct assegment *new = NULL; struct assegment *head = NULL; while (seg) { if (head) { new->next = assegment_dup (seg); new = new->next; } else head = new = assegment_dup (seg); seg = seg->next; } return head; } /* append given array of as numbers to the segment */ static struct assegment * assegment_append_asns (struct assegment *seg, as_t *asnos, int num) { as_t *newas; newas = realloc(seg->as, ASSEGMENT_DATA_SIZE (seg->length + num, TRUE)); if (newas) { seg->as = newas; memcpy (seg->as + seg->length, asnos, ASSEGMENT_DATA_SIZE(num, TRUE)); seg->length += num; return seg; } assegment_free_all (seg); return NULL; } static int int_cmp (const void *p1, const void *p2) { const as_t *as1 = p1; const as_t *as2 = p2; return (*as1 == *as2) ? 0 : ( (*as1 > *as2) ? 1 : -1); } /* normalise the segment. * In particular, merge runs of AS_SEQUENCEs into one segment * Internally, we do not care about the wire segment length limit, and * we want each distinct AS_PATHs to have the exact same internal * representation - eg, so that our hashing actually works.. */ static struct assegment * assegment_normalise (struct assegment *head) { struct assegment *seg = head, *pin; struct assegment *tmp; if (!head) return head; while (seg) { pin = seg; /* Sort values SET segments, for determinism in paths to aid * creation of hash values / path comparisons * and because it helps other lesser implementations ;) */ if (seg->type == AS_SET || seg->type == AS_CONFED_SET) { int tail = 0; int i; qsort (seg->as, seg->length, sizeof(as_t), int_cmp); /* weed out dupes */ for (i=1; i < seg->length; i++) { if (seg->as[tail] == seg->as[i]) continue; tail++; if (tail < i) seg->as[tail] = seg->as[i]; } /* seg->length can be 0.. */ if (seg->length) seg->length = tail + 1; } /* read ahead from the current, pinned segment while the segments * are packable/mergeable. Append all following packable segments * to the segment we have pinned and remove these appended * segments. */ while (pin->next && ASSEGMENT_TYPES_PACKABLE(pin, pin->next)) { tmp = pin->next; seg = pin->next; /* append the next sequence to the pinned sequence */ pin = assegment_append_asns (pin, seg->as, seg->length); /* bypass the next sequence */ pin->next = seg->next; /* get rid of the now referenceless segment */ assegment_free (tmp); } seg = pin->next; } return head; } static struct aspath * aspath_new () { struct aspath *aspath; aspath = malloc(sizeof (struct aspath)); if (!aspath) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (aspath_new). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset (aspath, 0, sizeof (struct aspath)); return aspath; } /* Free AS path structure. */ void aspath_free (struct aspath *aspath) { if (!aspath) return; if (aspath->segments) assegment_free_all (aspath->segments); if (aspath->str) free(aspath->str); free(aspath); } /* Unintern aspath from AS path bucket. */ void aspath_unintern(struct bgp_peer *peer, struct aspath *aspath) { struct bgp_rt_structs *inter_domain_routing_db; struct aspath *ret = NULL; (void) ret; if (!peer) return; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return; if (aspath->refcnt) aspath->refcnt--; if (aspath->refcnt == 0) { /* This aspath must exist in aspath hash table. */ ret = hash_release(inter_domain_routing_db->ashash, aspath); assert (ret != NULL); aspath_free (aspath); } } /* Add new as segment to the as path. */ static void aspath_segment_add (struct aspath *as, int type) { struct assegment *seg = as->segments; struct assegment *new = assegment_new (type, 0); if (seg) { while (seg->next) seg = seg->next; seg->next = new; } else as->segments = new; } /* Add new as value to as path structure. */ static void aspath_as_add (struct aspath *as, as_t asno) { struct assegment *seg = as->segments; if (!seg) return; /* Last segment search procedure. */ while (seg->next) seg = seg->next; assegment_append_asns (seg, &asno, 1); } /* Return the start or end delimiters for a particular Segment type */ #define AS_SEG_START 0 #define AS_SEG_END 1 static char aspath_delimiter_char (u_char type, u_char which) { int i; struct { int type; char start; char end; } aspath_delim_char [] = { { AS_SET, '{', '}' }, { AS_CONFED_SET, '[', ']' }, { AS_CONFED_SEQUENCE, '(', ')' }, { 0 } }; for (i = 0; aspath_delim_char[i].type != 0; i++) { if (aspath_delim_char[i].type == type) { if (which == AS_SEG_START) return aspath_delim_char[i].start; else if (which == AS_SEG_END) return aspath_delim_char[i].end; } } return ' '; } /* countup asns from this segment and index onward */ static int assegment_count_asns (struct assegment *seg, int from) { int count = 0; while (seg) { if (!from) count += seg->length; else { count += (seg->length - from); from = 0; } seg = seg->next; } return count; } unsigned int aspath_count_confeds (struct aspath *aspath) { int count = 0; struct assegment *seg = aspath->segments; while (seg) { if (seg->type == AS_CONFED_SEQUENCE) count += seg->length; else if (seg->type == AS_CONFED_SET) count++; seg = seg->next; } return count; } unsigned int aspath_count_hops (struct aspath *aspath) { int count = 0; struct assegment *seg = aspath->segments; while (seg) { if (seg->type == AS_SEQUENCE) count += seg->length; else if (seg->type == AS_SET) count++; seg = seg->next; } return count; } /* Estimate size aspath /might/ take if encoded into an * ASPATH attribute. * * This is a quick estimate, not definitive! aspath_put() * may return a different number!! */ unsigned int aspath_size (struct aspath *aspath) { int size = 0; struct assegment *seg = aspath->segments; while (seg) { size += ASSEGMENT_SIZE(seg->length, 1); seg = seg->next; } return size; } /* Return highest public ASN in path */ as_t aspath_highest (struct aspath *aspath) { struct assegment *seg = aspath->segments; as_t highest = 0; unsigned int i; while (seg) { for (i = 0; i < seg->length; i++) if (seg->as[i] > highest && (seg->as[i] < BGP_PRIVATE_AS_MIN || seg->as[i] > BGP_PRIVATE_AS_MAX)) highest = seg->as[i]; seg = seg->next; } return highest; } /* Return 1 if there are any 4-byte ASes in the path */ unsigned int aspath_has_as4 (struct aspath *aspath) { struct assegment *seg = aspath->segments; unsigned int i; while (seg) { for (i = 0; i < seg->length; i++) if (seg->as[i] > BGP_AS_MAX) return 1; seg = seg->next; } return 0; } /* Return number of as numbers in in path */ unsigned int aspath_count_numas (struct aspath *aspath) { struct assegment *seg = aspath->segments; unsigned int num; num=0; while (seg) { num += seg->length; seg = seg->next; } return num; } char *aspath_make_empty() { char *str_buf; str_buf = malloc(1); if (!str_buf) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (aspath_make_str_count). Exiting ..\n", config.name); // XXX exit_gracefully(1); } str_buf[0] = '\0'; return str_buf; } /* Convert aspath structure to string expression. */ static char * aspath_make_str_count (struct aspath *as) { struct assegment *seg; int str_size; int len = 0; char *str_buf; /* Empty aspath. */ if (!as->segments) { str_buf = aspath_make_empty(); return str_buf; } seg = as->segments; /* ASN takes 5 chars at least, plus seperator, see below. * If there is one differing segment type, we need an additional * 2 chars for segment delimiters, and the final '\0'. * Hopefully this is large enough to avoid hitting the realloc * code below for most common sequences. * * With 32bit ASNs, this range will increase, but only worth changing * once there are significant numbers of ASN >= 100000 */ #define ASN_STR_LEN (10 + 1) str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1, ASPATH_STR_DEFAULT_LEN); str_buf = malloc(str_size); if (!str_buf) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (aspath_make_str_count). Exiting ..\n", config.name); // XXX exit_gracefully(1); } while (seg) { int i; char seperator; /* Check AS type validity. Set seperator for segment */ switch (seg->type) { case AS_SET: case AS_CONFED_SET: seperator = ','; break; case AS_SEQUENCE: case AS_CONFED_SEQUENCE: seperator = ' '; break; default: free(str_buf); str_buf = aspath_make_empty(); return str_buf; } /* We might need to increase str_buf, particularly if path has * differing segments types, our initial guesstimate above will * have been wrong. need 5 chars for ASN, a seperator each and * potentially two segment delimiters, plus a space between each * segment and trailing zero. * * This may need to revised if/when significant numbers of * ASNs >= 100000 are assigned and in-use on the internet... */ #define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1) if ( (len + SEGMENT_STR_LEN(seg)) > str_size) { str_size = len + SEGMENT_STR_LEN(seg); str_buf = realloc(str_buf, str_size); } #undef ASN_STR_LEN #undef SEGMENT_STR_LEN if (seg->type != AS_SEQUENCE) len += snprintf (str_buf + len, str_size - len, "%c", aspath_delimiter_char (seg->type, AS_SEG_START)); /* write out the ASNs, with their seperators, bar the last one*/ for (i = 0; i < seg->length; i++) { len += snprintf (str_buf + len, str_size - len, "%u", seg->as[i]); as->last_as = seg->as[i]; if (i < (seg->length - 1)) len += snprintf (str_buf + len, str_size - len, "%c", seperator); } if (seg->type != AS_SEQUENCE) len += snprintf (str_buf + len, str_size - len, "%c", aspath_delimiter_char (seg->type, AS_SEG_END)); if (seg->next) len += snprintf (str_buf + len, str_size - len, " "); seg = seg->next; } assert (len < str_size); str_buf[len] = '\0'; return str_buf; } static void aspath_str_update (struct aspath *as) { if (as->str) free(as->str); as->str = aspath_make_str_count (as); } /* Intern allocated AS path. */ struct aspath * aspath_intern (struct bgp_peer *peer, struct aspath *aspath) { struct bgp_rt_structs *inter_domain_routing_db; struct aspath *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; /* Assert this AS path structure is not interned. */ assert (aspath->refcnt == 0); /* Check AS path hash. */ find = hash_get(peer, inter_domain_routing_db->ashash, aspath, hash_alloc_intern); if (find != aspath) aspath_free (aspath); find->refcnt++; if (! find->str) find->str = aspath_make_str_count (find); return find; } /* Duplicate aspath structure. Created same aspath structure but reference count and AS path string is cleared. */ struct aspath * aspath_dup (struct aspath *aspath) { struct aspath *new; new = malloc(sizeof (struct aspath)); if (!new) { Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (aspath_dup). Exiting ..\n", config.name); // XXX exit_gracefully(1); } memset(new, 0, sizeof(struct aspath)); if (aspath->segments) new->segments = assegment_dup_all (aspath->segments); else new->segments = NULL; new->str = aspath_make_str_count (aspath); new->last_as = aspath->last_as; return new; } static void * aspath_hash_alloc (void *arg) { struct aspath *aspath; /* New aspath structure is needed. */ aspath = aspath_dup (arg); /* Malformed AS path value. */ if (! aspath->str) { aspath_free (aspath); return NULL; } return aspath; } /* parse as-segment in struct assegment */ static struct assegment * assegments_parse(struct bgp_peer *peer, char *s, size_t length, int use32bit) { struct assegment_header segh; struct assegment *seg, *prev = NULL, *head = NULL; size_t bytes = 0, aspathlen; u_char *tmp8; u_int16_t tmp16; u_int32_t tmp32; /* empty aspath (ie iBGP or somesuch) */ if (length == 0) return NULL; /* basic checks; XXX: length? */ if (length % AS16_VALUE_SIZE) return NULL; aspathlen = length; while (aspathlen > 0) { int i; int seg_size; /* softly softly, get the header first on its own */ tmp8 = (u_char *) s; segh.type = *tmp8; s++; tmp8 = (u_char *) s; segh.length = *tmp8; s++; /* small BMP heuristics: since BGP OPENs are fabricated, they may not always reflect the reality of what is encoded in BGP UPDATE msgs */ if (peer->type == FUNC_TYPE_BMP && aspathlen > 2 && segh.length) { if ((aspathlen - 2) / segh.length == AS_VALUE_SIZE) { if (!use32bit) { use32bit = TRUE; } } } seg_size = ASSEGMENT_SIZE(segh.length, use32bit); /* check it.. */ if ( ((bytes + seg_size) > length) /* 1771bis 4.3b: seg length contains one or more */ || (segh.length == 0) /* Paranoia in case someone changes type of segment length */ || ((sizeof(segh.length) > 1) && (segh.length > AS_SEGMENT_MAX)) ) { if (head) assegment_free_all (head); return NULL; } /* now its safe to trust lengths */ seg = assegment_new (segh.type, segh.length); if (head) prev->next = seg; else /* it's the first segment */ head = prev = seg; for (i = 0; i < segh.length; i++) { if (use32bit) { memcpy(&tmp32, s, 4); seg->as[i] = ntohl(tmp32); s += 4; } else { memcpy(&tmp16, s, 2); seg->as[i] = ntohs(tmp16); s += 2; } } bytes += seg_size; aspathlen -= seg_size; prev = seg; } return assegment_normalise (head); } /* AS path parse function. If there is same AS path in the the AS path hash then return it else make new AS path structure. */ struct aspath *aspath_parse(struct bgp_peer *peer, char *s, size_t length, int use32bit) { struct bgp_rt_structs *inter_domain_routing_db; struct aspath as; struct aspath *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; /* If length is odd it's malformed AS path. */ /* Nit-picking: if (use32bit == 0) it is malformed if odd, * otherwise its malformed when length is larger than 2 and (length-2) * is not dividable by 4. * But... this time we're lazy */ if (length % AS16_VALUE_SIZE ) return NULL; memset (&as, 0, sizeof (struct aspath)); as.segments = assegments_parse(peer, s, length, use32bit); /* If already same aspath exist then return it. */ find = hash_get (peer, inter_domain_routing_db->ashash, &as, aspath_hash_alloc); /* aspath_hash_alloc dupes segments too. that probably could be * optimised out. */ assegment_free_all (as.segments); if (as.str) free(as.str); if (! find) return NULL; find->refcnt++; return find; } /* When a BGP router receives an UPDATE with an MP_REACH_NLRI attribute, check the leftmost AS number in the AS_PATH attribute is or not the peer's AS number. */ int aspath_firstas_check (struct aspath *aspath, as_t asno) { if ( (aspath == NULL) || (aspath->segments == NULL) ) return 0; if (aspath->segments && (aspath->segments->type == AS_SEQUENCE) && (aspath->segments->as[0] == asno )) return 1; return 0; } /* AS path loop check. If aspath contains asno then return >= 1. */ int aspath_loop_check (struct aspath *aspath, as_t asno) { struct assegment *seg; int count = 0; if ( (aspath == NULL) || (aspath->segments == NULL) ) return 0; seg = aspath->segments; while (seg) { int i; for (i = 0; i < seg->length; i++) if (seg->as[i] == asno) count++; seg = seg->next; } return count; } /* When all of AS path is private AS return 1. */ int aspath_private_as_check (struct aspath *aspath) { struct assegment *seg; if ( !(aspath && aspath->segments) ) return 0; seg = aspath->segments; while (seg) { int i; for (i = 0; i < seg->length; i++) { if ( (seg->as[i] < BGP_PRIVATE_AS_MIN) || (seg->as[i] > BGP_PRIVATE_AS_MAX) ) return 0; } seg = seg->next; } return 1; } /* Merge as1 to as2. as2 should be uninterned aspath. */ static struct aspath * aspath_merge (struct aspath *as1, struct aspath *as2) { struct assegment *last, *new; if (! as1 || ! as2) return NULL; last = new = assegment_dup_all (as1->segments); /* find the last valid segment */ while (last && last->next) last = last->next; last->next = as2->segments; as2->segments = new; aspath_str_update (as2); return as2; } /* Compare leftmost AS value for MED check. If as1's leftmost AS and as2's leftmost AS is same return 1. */ int aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2) { const struct assegment *seg1 = NULL; const struct assegment *seg2 = NULL; if (!(aspath1 && aspath2)) return 0; seg1 = aspath1->segments; seg2 = aspath2->segments; /* find first non-confed segments for each */ while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE) || (seg1->type == AS_CONFED_SET))) seg1 = seg1->next; while (seg2 && ((seg2->type == AS_CONFED_SEQUENCE) || (seg2->type == AS_CONFED_SET))) seg2 = seg2->next; /* Check as1's */ if (!(seg1 && seg2 && (seg1->type == AS_SEQUENCE) && (seg2->type == AS_SEQUENCE))) return 0; if (seg1->as[0] == seg2->as[0]) return 1; return 0; } /* Truncate an aspath after a number of hops, and put the hops remaining * at the front of another aspath. Needed for AS4 compat. * * Returned aspath is a /new/ aspath, which should either by free'd or * interned by the caller, as desired. */ struct aspath * aspath_reconcile_as4 (struct aspath *aspath, struct aspath *as4path) { struct assegment *seg, *newseg, *prevseg = NULL; struct aspath *newpath = NULL, *mergedpath; int hops, cpasns = 0; if (!aspath) return NULL; seg = aspath->segments; /* CONFEDs should get reconciled too.. */ hops = (aspath_count_hops (aspath) + aspath_count_confeds (aspath)) - aspath_count_hops (as4path); if (hops < 0) { /* Something's gone wrong. The RFC says we should now ignore AS4_PATH, * which is daft behaviour - it contains vital loop-detection * information which must have been removed from AS_PATH. */ hops = aspath_count_hops (aspath); } if (!hops) return aspath_dup (as4path); while (seg && hops > 0) { switch (seg->type) { case AS_SET: case AS_CONFED_SET: hops--; cpasns = seg->length; break; case AS_CONFED_SEQUENCE: /* Should never split a confed-sequence, if hop-count * suggests we must then something's gone wrong somewhere. * * Most important goal is to preserve AS_PATHs prime function * as loop-detector, so we fudge the numbers so that the entire * confed-sequence is merged in. */ if (hops < seg->length) { hops = seg->length; } case AS_SEQUENCE: cpasns = MIN(seg->length, hops); hops -= seg->length; } assert (cpasns <= seg->length); newseg = assegment_new (seg->type, 0); newseg = assegment_append_asns (newseg, seg->as, cpasns); if (!newpath) { newpath = aspath_new (); newpath->segments = newseg; } else prevseg->next = newseg; prevseg = newseg; seg = seg->next; } /* We may be able to join some segments here, and we must * do this because... we want normalised aspaths in out hash * and we do not want to stumble in aspath_put. */ mergedpath = aspath_merge (newpath, aspath_dup(as4path)); aspath_free (newpath); mergedpath->segments = assegment_normalise (mergedpath->segments); aspath_str_update (mergedpath); return mergedpath; } /* Compare leftmost AS value for MED check. If as1's leftmost AS and as2's leftmost AS is same return 1. (confederation as-path only). */ int aspath_cmp_left_confed (const struct aspath *aspath1, const struct aspath *aspath2) { if (! (aspath1 && aspath2) ) return 0; if ( !(aspath1->segments && aspath2->segments) ) return 0; if ( (aspath1->segments->type != AS_CONFED_SEQUENCE) || (aspath2->segments->type != AS_CONFED_SEQUENCE) ) return 0; if (aspath1->segments->as[0] == aspath2->segments->as[0]) return 1; return 0; } /* Make hash value by raw aspath data. */ unsigned int aspath_key_make (void *p) { struct aspath * aspath = (struct aspath *) p; unsigned int key = 0; if (!aspath->str) aspath_str_update (aspath); key = jhash (aspath->str, strlen(aspath->str), 2334325); return key; } /* If two aspath have same value then return 1 else return 0 */ static int aspath_cmp (const void *arg1, const void *arg2) { const struct assegment *seg1 = ((struct aspath *)arg1)->segments; const struct assegment *seg2 = ((struct aspath *)arg2)->segments; while (seg1 || seg2) { int i; if ((!seg1 && seg2) || (seg1 && !seg2)) return 0; if (seg1->type != seg2->type) return 0; if (seg1->length != seg2->length) return 0; for (i = 0; i < seg1->length; i++) if (seg1->as[i] != seg2->as[i]) return 0; seg1 = seg1->next; seg2 = seg2->next; } return 1; } /* AS path hash initialize. */ void aspath_init (int buckets, struct hash **loc_ashash) { (*loc_ashash) = hash_create_size (32767, aspath_key_make, aspath_cmp); } /* return and as path value */ const char * aspath_print (struct aspath *as) { return (as ? as->str : NULL); } /* Return next token and point for string parse. */ const char * aspath_gettoken (const char *buf, enum as_token *token, as_t *asno) { const char *p = buf; /* Skip seperators (space for sequences, ',' for sets). */ while (isspace ((int) *p) || *p == ',') p++; /* Check the end of the string and type specify characters (e.g. {}()). */ switch (*p) { case '\0': return NULL; case '{': *token = as_token_set_start; p++; return p; case '}': *token = as_token_set_end; p++; return p; case '(': *token = as_token_confed_seq_start; p++; return p; case ')': *token = as_token_confed_seq_end; p++; return p; case '[': *token = as_token_confed_set_start; p++; return p; case ']': *token = as_token_confed_set_end; p++; return p; } /* Check actual AS value. */ if (isdigit ((int) *p)) { as_t asval; *token = as_token_asval; asval = (*p - '0'); p++; while (isdigit ((int) *p)) { asval *= 10; asval += (*p - '0'); p++; } *asno = asval; return p; } /* There is no match then return unknown token. */ *token = as_token_unknown; return p++; } struct aspath * aspath_str2aspath (const char *str) { enum as_token token = as_token_unknown; u_short as_type; as_t asno = 0; struct aspath *aspath; int needtype; aspath = aspath_new (); /* We start default type as AS_SEQUENCE. */ as_type = AS_SEQUENCE; needtype = 1; while ((str = aspath_gettoken (str, &token, &asno)) != NULL) { switch (token) { case as_token_asval: if (needtype) { aspath_segment_add (aspath, as_type); needtype = 0; } aspath_as_add (aspath, asno); break; case as_token_set_start: as_type = AS_SET; aspath_segment_add (aspath, as_type); needtype = 0; break; case as_token_set_end: as_type = AS_SEQUENCE; needtype = 1; break; case as_token_confed_seq_start: as_type = AS_CONFED_SEQUENCE; aspath_segment_add (aspath, as_type); needtype = 0; break; case as_token_confed_seq_end: as_type = AS_SEQUENCE; needtype = 1; break; case as_token_confed_set_start: as_type = AS_CONFED_SET; aspath_segment_add (aspath, as_type); needtype = 0; break; case as_token_confed_set_end: as_type = AS_SEQUENCE; needtype = 1; break; case as_token_unknown: default: aspath_free (aspath); return NULL; } } aspath_make_str_count (aspath); return aspath; } struct aspath * aspath_ast2aspath (as_t asn) { struct aspath *aspath; aspath = aspath_new (); aspath_segment_add (aspath, AS_SEQUENCE); aspath_as_add (aspath, asn); aspath_make_str_count (aspath); return aspath; } struct aspath * aspath_parse_ast(struct bgp_peer *peer, as_t asn) { struct bgp_rt_structs *inter_domain_routing_db; struct aspath *aspath, *find; if (!peer) return NULL; inter_domain_routing_db = bgp_select_routing_db(peer->type); if (!inter_domain_routing_db) return NULL; aspath = aspath_ast2aspath(asn); find = hash_get (peer, inter_domain_routing_db->ashash, aspath, aspath_hash_alloc); /* aspath_hash_alloc dupes stuff */ assegment_free_all (aspath->segments); if (aspath->str) free(aspath->str); free(aspath); if (!find) return NULL; find->refcnt++; return find; } pmacct-1.7.8/src/bgp/bgp_community.h0000644000175000017500000000572414354105275016406 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* Originally based on Quagga BGP community attribute related functions which is: Copyright (C) 1998, 2001 Kunihiro Ishiguro GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BGP_COMMUNITY_H_ #define _BGP_COMMUNITY_H_ /* Communities attribute. */ struct community { /* Reference count of communities value. */ unsigned long refcnt; /* Communities value size. */ int size; /* Communities value. */ u_int32_t *val; /* String of community attribute. This sring is used by vty output and expanded community-list for regular expression match. */ char *str; }; /* Well-known communities value. */ #define COMMUNITY_INTERNET 0x0 #define COMMUNITY_NO_EXPORT 0xFFFFFF01 #define COMMUNITY_NO_ADVERTISE 0xFFFFFF02 #define COMMUNITY_NO_EXPORT_SUBCONFED 0xFFFFFF03 #define COMMUNITY_LOCAL_AS 0xFFFFFF03 /* Macros of community attribute. */ #define com_length(X) ((X)->size * 4) #define com_lastval(X) ((X)->val + (X)->size - 1) #define com_nthval(X,n) ((X)->val + (n)) /* Prototypes of communities attribute functions. */ extern struct community *community_new (struct bgp_peer *); extern void community_init (int, struct hash **); extern void community_free (struct community *); extern struct community *community_uniq_sort (struct bgp_peer *, struct community *); extern struct community *community_intern (struct bgp_peer *, struct community *); extern void community_unintern (struct bgp_peer *, struct community *); extern unsigned int community_hash_make (struct community *); extern int community_cmp (const struct community *, const struct community *); extern struct community *community_delete (struct community *, struct community *); extern struct community *community_parse (struct bgp_peer *, u_int32_t *, u_short); extern int community_include (struct community *, u_int32_t); extern void community_del_val (struct community *, u_int32_t *); extern int community_str2com_simple(const char *, u_int32_t *); extern void community_add_val(struct bgp_peer *, struct community *, u_int32_t); extern u_int32_t community_val_get(struct community *, int); extern int community_compare(const void *, const void *); extern struct community *community_dup(struct community *); #endif pmacct-1.7.8/src/bgp/Makefile.am0000644000175000017500000000107614354105275015411 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmbgp.la libpmbgp_la_SOURCES = bgp.c bgp_aspath.c bgp_community.c \ bgp_ecommunity.c bgp_hash.c bgp_prefix.c bgp_table.c \ bgp_logdump.c bgp_util.c bgp_msg.c bgp_lookup.c \ bgp_lcommunity.c bgp_xcs.c bgp_aspath.h bgp_community.h \ bgp_ecommunity.h bgp.h bgp_hash.h bgp_logdump.h \ bgp_lookup.h bgp_msg.h bgp_packet.h bgp_prefix.h \ bgp_table.h bgp_util.h bgp_lcommunity.h bgp_xcs.h \ bgp_xcs-data.h bgp_blackhole.c bgp_blackhole.h \ bgp_lg.c bgp_lg.h libpmbgp_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/bgp/bgp_prefix.h0000644000175000017500000001270014354105275015647 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* * Originally based on Quagga prefix structure which is: * * Copyright (C) 1998 Kunihiro Ishiguro * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _BGP_PREFIX_H_ #define _BGP_PREFIX_H_ #define PREFIX_MASKSTRLEN 4 #define PREFIX_STRLEN (INET6_ADDRSTRLEN + PREFIX_MASKSTRLEN) /* * A struct prefix contains an address family, a prefix length, and an * address. This can represent either a 'network prefix' as defined * by CIDR, where the 'host bits' of the prefix are 0 * (e.g. AF_INET:10.0.0.0/8), or an address and netmask * (e.g. AF_INET:10.0.0.9/8), such as might be configured on an * interface. */ /* IPv4 and IPv6 unified prefix structure. */ struct prefix { u_char family; u_char prefixlen; union { u_char prefix; struct in_addr prefix4; struct in6_addr prefix6; } u __attribute__ ((aligned (8))); }; /* IPv4 prefix structure. */ struct prefix_ipv4 { u_char family; u_char prefixlen; struct in_addr prefix __attribute__ ((aligned (8))); }; /* IPv6 prefix structure. */ struct prefix_ipv6 { u_char family; u_char prefixlen; struct in6_addr prefix __attribute__ ((aligned (8))); }; #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif /* INET_ADDRSTRLEN */ #ifndef INET6_ADDRSTRLEN #define INET6_ADDRSTRLEN 46 #endif /* INET6_ADDRSTRLEN */ #ifndef INET6_BUFSIZ #define INET6_BUFSIZ 51 #endif /* INET6_BUFSIZ */ /* Max bit/byte length of IPv4 address. */ #define IPV4_MAX_BYTELEN 4 #define IPV4_MAX_BITLEN 32 #define IPV4_MAX_PREFIXLEN 32 #define IPV4_ADDR_CMP(D,S) memcmp ((D), (S), IPV4_MAX_BYTELEN) #define IPV4_ADDR_SAME(D,S) (memcmp ((D), (S), IPV4_MAX_BYTELEN) == 0) #define IPV4_ADDR_COPY(D,S) memcpy ((D), (S), IPV4_MAX_BYTELEN) #define IPV4_NET0(a) ((((u_int32_t) (a)) & 0xff000000) == 0x00000000) #define IPV4_NET127(a) ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000) #define IPV4_LINKLOCAL(a) ((((u_int32_t) (a)) & 0xffff0000) == 0xa9fe0000) /* Max bit/byte length of IPv6 address. */ #define IPV6_MAX_BYTELEN 16 #define IPV6_MAX_BITLEN 128 #define IPV6_MAX_PREFIXLEN 128 #define IPV6_ADDR_CMP(D,S) memcmp ((D), (S), IPV6_MAX_BYTELEN) #define IPV6_ADDR_SAME(D,S) (memcmp ((D), (S), IPV6_MAX_BYTELEN) == 0) #define IPV6_ADDR_COPY(D,S) memcpy ((D), (S), IPV6_MAX_BYTELEN) /* Count prefix size from mask length */ #define PSIZE(a) (((a) + 7) / (8)) /* Prefix's family member. */ #define PREFIX_FAMILY(p) ((p)->family) /* Prototypes. */ extern int afi2family (int); extern int family2afi (int); extern struct prefix *prefix_new (void); extern void prefix_free (struct prefix *); extern const char *prefix_family_str (const struct prefix *); extern int prefix_blen (const struct prefix *); extern int str2prefix (const char *, struct prefix *); extern int prefix2str (const struct prefix *, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); extern void prefix_copy (struct prefix *dest, const struct prefix *src); extern void apply_mask (struct prefix *); extern struct prefix_ipv4 *prefix_ipv4_new (void); extern void prefix_ipv4_free (struct prefix_ipv4 *); extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *); extern void apply_mask_ipv4 (struct prefix_ipv4 *); #define PREFIX_COPY_IPV4(DST, SRC) \ *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC)); extern int prefix_ipv4_any (const struct prefix_ipv4 *); extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *); extern u_char ip_masklen (struct in_addr); extern void masklen2ip (int, struct in_addr *); /* returns the network portion of the host address */ extern in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen); /* given the address of a host on a network and the network mask length, * calculate the broadcast address for that network; * special treatment for /31: returns the address of the other host * on the network by flipping the host bit */ extern in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen); extern int netmask_str2prefix_str (const char *, const char *, char *); extern struct prefix_ipv6 *prefix_ipv6_new (void); extern void prefix_ipv6_free (struct prefix_ipv6 *); extern int str2prefix_ipv6 (const char *, struct prefix_ipv6 *); extern void apply_mask_ipv6 (struct prefix_ipv6 *); #define PREFIX_COPY_IPV6(DST, SRC) \ *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC)); extern int ip6_masklen (struct in6_addr); extern void masklen2ip6 (int, struct in6_addr *); extern void str2in6_addr (const char *, struct in6_addr *); extern const char *inet6_ntoa (struct in6_addr); extern int all_digit (const char *); #endif pmacct-1.7.8/src/preprocess-internal.h0000644000175000017500000000554314354105275016760 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PREPROCESS_INTERNAL_H #define PREPROCESS_INTERNAL_H #include "preprocess.h" /* funcs */ extern void set_preprocess_funcs(char *, struct preprocess *, int); extern int cond_qnum(struct db_cache *[], int *, int); extern int check_minp(struct db_cache *[], int *, int); extern int check_minb(struct db_cache *[], int *, int); extern int check_minf(struct db_cache *[], int *, int); extern int check_maxp(struct db_cache *[], int *, int); extern int check_maxb(struct db_cache *[], int *, int); extern int check_maxf(struct db_cache *[], int *, int); extern int check_maxbpp(struct db_cache *[], int *, int); extern int check_maxppf(struct db_cache *[], int *, int); extern int check_minbpp(struct db_cache *[], int *, int); extern int check_minppf(struct db_cache *[], int *, int); extern int check_fss(struct db_cache *[], int *, int); extern int check_fsrc(struct db_cache *[], int *, int); extern int action_usrf(struct db_cache *[], int *, int); extern int action_adjb(struct db_cache *[], int *, int); extern int P_check_minp(struct chained_cache *[], int *, int); extern int P_check_minb(struct chained_cache *[], int *, int); extern int P_check_minf(struct chained_cache *[], int *, int); extern int P_check_maxp(struct chained_cache *[], int *, int); extern int P_check_maxb(struct chained_cache *[], int *, int); extern int P_check_maxf(struct chained_cache *[], int *, int); extern int P_check_minbpp(struct chained_cache *[], int *, int); extern int P_check_minppf(struct chained_cache *[], int *, int); extern int mandatory_invalidate(struct db_cache *[], int *, int); extern int mandatory_validate(struct db_cache *[], int *, int); extern void check_validity(struct db_cache *, int); extern int P_mandatory_invalidate(struct chained_cache *[], int *, int); extern void P_check_validity(struct chained_cache *, int); extern sql_preprocess_func sql_preprocess_funcs[2*N_FUNCS]; /* 20 */ extern P_preprocess_func P_preprocess_funcs[2*N_FUNCS]; /* 20 */ extern struct preprocess prep; extern struct _fsrc_queue fsrc_queue; #endif // PREPROCESS_INTERNAL_H pmacct-1.7.8/src/pmacct-globals.c0000644000175000017500000000511014354105275015632 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "nfacctd.h" struct utpl_field *(*get_ext_db_ie_by_type)(struct template_cache_entry *, u_int32_t, u_int16_t, u_int8_t); char sll_mac[2][ETH_ADDR_LEN]; struct host_addr mcast_groups[MAX_MCAST_GROUPS]; int reload_map, reload_map_exec_plugins, reload_geoipv2_file; int reload_map_bgp_thread, reload_log, reload_log_bgp_thread; int reload_map_bmp_thread, reload_log_bmp_thread; int reload_map_rpki_thread, reload_log_rpki_thread; int reload_map_telemetry_thread, reload_log_telemetry_thread; int reload_map_pmacctd; int print_stats; int reload_log_sf_cnt; int data_plugins, tee_plugins; int collector_port; struct timeval reload_map_tstamp; struct child_ctl2 dump_writers; int debug; struct configuration config; /* global configuration structure */ struct plugins_list_entry *plugins_list = NULL; /* linked list of each plugin configuration */ pid_t failed_plugins[MAX_N_PLUGINS]; /* plugins failed during startup phase */ u_char dummy_tlhdr[16], empty_mem_area_256b[SRVBUFLEN]; struct pm_pcap_device device; struct pm_pcap_devices devices, bkp_devices; struct pm_pcap_interfaces pm_pcap_if_map, pm_bkp_pcap_if_map; struct pcap_stat ps; struct sigaction sighandler_action; int protocols_number; u_int32_t PdataSz, ChBufHdrSz, CharPtrSz, CounterSz, HostAddrSz; u_int32_t PpayloadSz, PextrasSz, PmsgSz, PvhdrSz, PtLabelTSz; u_int32_t PmLabelTSz; u_int32_t NfHdrV5Sz, NfHdrV9Sz; u_int32_t IpFixHdrSz; u_int32_t NfDataHdrV9Sz, NfTplHdrV9Sz, NfOptTplHdrV9Sz; u_int32_t NfTplFieldV9Sz; u_int32_t NfDataV5Sz; u_int32_t IP4HdrSz, IP4TlSz, IP6HdrSz, IP6AddrSz, IP6TlSz; u_int32_t MyTLHdrSz, TCPFlagOff; u_int32_t SFSampleSz, SFLAddressSz, SFrenormEntrySz; u_int32_t PptrsSz, UDPHdrSz, CSSz, MyTCPHdrSz, IpFlowCmnSz; u_int16_t PbgpSz, PlbgpSz, PnatSz, PmplsSz, PtunSz; pmacct-1.7.8/src/sql_handlers.c0000644000175000017500000016520514354105275015435 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* PG_* functions are used only by PostgreSQL plugin; MY_* functions are used only by MySQL plugin; count_* functions are used by more than one plugin; fake_* functions are used to supply static zero-filled values; */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "sql_common.h" #include "ip_flow.h" #include "classifier.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif static const char fake_mac[] = "0:0:0:0:0:0"; static const char fake_host[] = "0.0.0.0"; static const char fake_as[] = "0"; static const char fake_comm[] = ""; static const char fake_as_path[] = ""; /* Functions */ #if defined (HAVE_L2) void count_src_mac_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char sbuf[18]; u_int8_t ubuf[ETH_ADDR_LEN]; memcpy(ubuf, cache_elem->primitives.eth_shost, ETH_ADDR_LEN); etheraddr_string(ubuf, sbuf); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_mac_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char sbuf[18]; u_int8_t ubuf[ETH_ADDR_LEN]; memcpy(ubuf, cache_elem->primitives.eth_dhost, ETH_ADDR_LEN); etheraddr_string(ubuf, sbuf); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_vlan_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.vlan_id); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.vlan_id); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_out_vlan_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.out_vlan_id); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.out_vlan_id); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_cos_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.cos); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.cos); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_etype_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.etype); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.etype); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #endif void count_src_host_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.src_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_net_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.src_net); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_as_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_as); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_as); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.dst_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_net_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.dst_net); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_as_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_as); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_as); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_in_iface_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.ifindex_in); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.ifindex_in); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_out_iface_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.ifindex_out); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.ifindex_out); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_nmask_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_nmask); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_nmask); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_nmask_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_nmask); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_nmask); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #if defined WITH_GEOIP void count_src_host_country_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, GeoIP_code_by_id(cache_elem->primitives.src_ip_country.id)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, GeoIP_code_by_id(cache_elem->primitives.src_ip_country.id)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_country_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, GeoIP_code_by_id(cache_elem->primitives.dst_ip_country.id)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, GeoIP_code_by_id(cache_elem->primitives.dst_ip_country.id)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #endif #if defined WITH_GEOIPV2 void count_src_host_country_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_ip_country.str); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_ip_country.str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_country_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_ip_country.str); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_ip_country.str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_host_pocode_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_ip_pocode.str); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_ip_pocode.str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_pocode_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_ip_pocode.str); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_ip_pocode.str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_host_coords_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_ip_lat, cache_elem->primitives.src_ip_lon); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_ip_lat, cache_elem->primitives.src_ip_lon); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_coords_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_ip_lat, cache_elem->primitives.dst_ip_lon); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_ip_lat, cache_elem->primitives.dst_ip_lon); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #endif void count_sampling_rate_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.sampling_rate); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.sampling_rate); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_sampling_direction_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, sampling_direction_print(cache_elem->primitives.sampling_direction)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sampling_direction_print(cache_elem->primitives.sampling_direction)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_src_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pnat->post_nat_src_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_dst_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pnat->post_nat_dst_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_src_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->post_nat_src_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->post_nat_src_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_dst_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->post_nat_dst_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->post_nat_dst_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_nat_event_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->nat_event); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->nat_event); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_fw_event_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->fw_event); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->fw_event); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_fwd_status_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->fwd_status); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->fwd_status); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_mpls_label_top_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pmpls->mpls_label_top); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pmpls->mpls_label_top); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_mpls_label_bottom_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pmpls->mpls_label_bottom); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pmpls->mpls_label_bottom); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_mpls_label_stack_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char label_stack[MAX_MPLS_LABEL_STACK]; char *label_stack_ptr = NULL; int label_stack_len = 0; memset(label_stack, 0, MAX_MPLS_LABEL_STACK); label_stack_len = vlen_prims_get(cache_elem->pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); if (label_stack_ptr) { mpls_label_stack_to_str(label_stack, sizeof(label_stack), (u_int32_t *)label_stack_ptr, label_stack_len); } snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, label_stack); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, label_stack); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_src_mac_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char sbuf[18]; u_int8_t ubuf[ETH_ADDR_LEN]; memcpy(ubuf, cache_elem->ptun->tunnel_eth_shost, ETH_ADDR_LEN); etheraddr_string(ubuf, sbuf); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_dst_mac_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char sbuf[18]; u_int8_t ubuf[ETH_ADDR_LEN]; memcpy(ubuf, cache_elem->ptun->tunnel_eth_dhost, ETH_ADDR_LEN); etheraddr_string(ubuf, sbuf); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, sbuf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, sbuf); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_src_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->ptun->tunnel_src_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_dst_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->ptun->tunnel_dst_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void MY_count_tunnel_ip_proto_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char proto[PROTO_NUM_STRLEN]; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ip_proto_print(cache_elem->ptun->tunnel_proto, proto, PROTO_NUM_STRLEN)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ip_proto_print(cache_elem->ptun->tunnel_proto, proto, PROTO_NUM_STRLEN)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_count_tunnel_ip_proto_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->ptun->tunnel_proto); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->ptun->tunnel_proto); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_ip_tos_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->ptun->tunnel_tos); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->ptun->tunnel_tos); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_src_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->ptun->tunnel_src_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->ptun->tunnel_src_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_dst_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->ptun->tunnel_dst_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->ptun->tunnel_dst_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_tcpflags_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->tunnel_tcp_flags); *ptr_values += strlen(*ptr_values); } void count_vxlan_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->ptun->tunnel_id); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->ptun->tunnel_id); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_start_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->pnat->timestamp_start.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_start.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_start_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_start.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_start.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_start_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_start.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_start.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_end_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->pnat->timestamp_end.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_end.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_end_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_end.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_end.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_end_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_end.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_end.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_arrival_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->pnat->timestamp_arrival.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_arrival.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_arrival_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_arrival.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_arrival.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_arrival_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_arrival.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_arrival.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_export_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->pnat->timestamp_export.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_export.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_export_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_export.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_export.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_export_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pnat->timestamp_export.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pnat->timestamp_export.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_min_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->stitch->timestamp_min.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_min.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_min_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_min.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->stitch->timestamp_min.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_min_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_min.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->stitch->timestamp_min.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_copy_count_timestamp_max_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char time_str[VERYSHORTBUFLEN]; pm_strftime(time_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->stitch->timestamp_max.tv_sec, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_max.tv_sec); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, time_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_max_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_max.tv_sec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->stitch->timestamp_max.tv_sec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_max_residual_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->stitch->timestamp_max.tv_usec); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->stitch->timestamp_max.tv_usec); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_export_proto_seqno_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.export_proto_seqno); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.export_proto_seqno); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_export_proto_version_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.export_proto_version); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.export_proto_version); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_export_proto_sysid_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.export_proto_sysid); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.export_proto_sysid); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_custom_primitives_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { struct custom_primitive_ptrs *cp_entry; cp_entry = &config.cpptrs.primitive[idata->cp_idx]; if (cp_entry->ptr->len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; custom_primitive_value_print(cp_str, SRVBUFLEN, cache_elem->pcust, cp_entry, FALSE); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cp_str); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cp_str); } else { char *label_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, cp_entry->ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, label_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, label_ptr); } *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); idata->cp_idx++; idata->cp_idx %= config.cpptrs.num; } void count_std_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_STD_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_ext_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_EXT_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_lrg_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_LRG_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_as_path_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *as_path_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_AS_PATH, &as_path_ptr); if (!as_path_ptr) as_path_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, as_path_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, as_path_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_std_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_SRC_STD_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_ext_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_SRC_EXT_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_lrg_comm_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *bgp_comm_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_SRC_LRG_COMM, &bgp_comm_ptr); if (!bgp_comm_ptr) bgp_comm_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, bgp_comm_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, bgp_comm_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_as_path_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *as_path_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_SRC_AS_PATH, &as_path_ptr); if (!as_path_ptr) as_path_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, as_path_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, as_path_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_local_pref_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->local_pref); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->local_pref); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_local_pref_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->src_local_pref); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->src_local_pref); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_med_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->med); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->med); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_med_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->src_med); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->src_med); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_roa_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, rpki_roa_print(cache_elem->pbgp->dst_roa)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, rpki_roa_print(cache_elem->pbgp->dst_roa)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_roa_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, rpki_roa_print(cache_elem->pbgp->src_roa)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, rpki_roa_print(cache_elem->pbgp->src_roa)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_mpls_vpn_rd_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[SRVBUFLEN]; bgp_rd2str(ptr, &cache_elem->pbgp->mpls_vpn_rd); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_mpls_pw_id_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->mpls_pw_id); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->mpls_pw_id); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_src_as_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->peer_src_as); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->peer_src_as); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_dst_as_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->pbgp->peer_dst_as); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->pbgp->peer_dst_as); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_src_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pbgp->peer_src_ip); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_dst_ip_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ptr[INET6_ADDRSTRLEN], *indirect_ptr = ptr; addr_to_str2(ptr, &cache_elem->pbgp->peer_dst_ip, ft2af(cache_elem->flow_type)); if (!strlen(ptr)) indirect_ptr = (char *) fake_host; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, indirect_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, indirect_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.src_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.src_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_port_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.dst_port); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.dst_port); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tcpflags_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->tcp_flags); *ptr_values += strlen(*ptr_values); } void count_ip_tos_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.tos); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.tos); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void MY_count_ip_proto_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char proto[PROTO_NUM_STRLEN]; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ip_proto_print(cache_elem->primitives.proto, proto, PROTO_NUM_STRLEN)); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ip_proto_print(cache_elem->primitives.proto, proto, PROTO_NUM_STRLEN)); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void PG_count_ip_proto_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.proto); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.proto); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_copy_timestamp_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { static char btime_str[VERYSHORTBUFLEN], now_str[VERYSHORTBUFLEN]; pm_strftime(btime_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &cache_elem->basetime, config.timestamps_utc); pm_strftime(now_str, VERYSHORTBUFLEN, "%Y-%m-%d %H:%M:%S", &idata->now, config.timestamps_utc); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->basetime); // dummy snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, now_str, btime_str); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_timestamp_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { time_t tme = idata->now; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->basetime); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, tme, cache_elem->basetime); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tag_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.tag); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.tag); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tag2_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, cache_elem->primitives.tag2); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, cache_elem->primitives.tag2); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_label_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *label_ptr = NULL, empty_string[] = ""; vlen_prims_get(cache_elem->pvlen, COUNT_INT_LABEL, &label_ptr); if (!label_ptr) label_ptr = empty_string; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, label_ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, label_ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_class_id_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char buf[MAX_PROTOCOL_LEN+1]; memset(buf, 0, MAX_PROTOCOL_LEN+1); if (cache_elem->primitives.class && class[cache_elem->primitives.class-1].id) { strlcpy(buf, class[cache_elem->primitives.class-1].protocol, MAX_PROTOCOL_LEN); buf[sizeof(buf)-1] = '\0'; } else strlcpy(buf, "unknown", MAX_PROTOCOL_LEN); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, buf); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, buf); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #if defined (WITH_NDPI) void count_ndpi_class_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char ndpi_class[SUPERSHORTBUFLEN]; snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, cache_elem->primitives.ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, cache_elem->primitives.ndpi_class.app_protocol)); snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, ndpi_class); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, ndpi_class); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } #endif void count_counters_setclause_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { snprintf(*ptr_set, SPACELEFT(set_clause), set[num].string, cache_elem->packet_counter, cache_elem->bytes_counter); *ptr_set += strlen(*ptr_set); } void count_flows_setclause_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { snprintf(*ptr_set, SPACELEFT(set_clause), set[num].string, cache_elem->flows_counter); *ptr_set += strlen(*ptr_set); } void count_tcpflags_setclause_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { snprintf(*ptr_set, SPACELEFT(set_clause), set[num].string, cache_elem->tcp_flags); *ptr_set += strlen(*ptr_set); } void count_tunnel_tcpflags_setclause_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { snprintf(*ptr_set, SPACELEFT(set_clause), set[num].string, cache_elem->tunnel_tcp_flags); *ptr_set += strlen(*ptr_set); } void count_noop_setclause_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { strncpy(*ptr_set, set[num].string, SPACELEFT(set_clause)); *ptr_set += strlen(*ptr_set); } void count_noop_setclause_event_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_set, char **ptr_none) { strncpy(*ptr_set, set_event[num].string, SPACELEFT(set_clause)); *ptr_set += strlen(*ptr_set); } /* Fake handlers next */ void fake_mac_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, fake_mac); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, fake_mac); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void fake_host_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, fake_host); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, fake_host); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void fake_as_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, fake_as); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, fake_as); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void fake_comms_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, fake_comm); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, fake_comm); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void fake_as_path_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, fake_as_path); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, fake_as_path); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_host_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.src_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_host_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.dst_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_src_net_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.src_net); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_dst_net_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->primitives.dst_net); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_src_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pbgp->peer_src_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_peer_dst_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str2(ptr, &cache_elem->pbgp->peer_dst_ip, ft2af(cache_elem->flow_type)); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_src_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pnat->post_nat_src_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_post_nat_dst_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->pnat->post_nat_dst_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_src_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->ptun->tunnel_src_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void count_tunnel_dst_ip_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char aton_v6[] = "INET6_ATON", aton_null[] = " ", *aton = aton_null; char ptr[INET6_ADDRSTRLEN]; addr_to_str(ptr, &cache_elem->ptun->tunnel_dst_ip); aton = aton_v6; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, ptr); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, ptr); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } void fake_host_aton_handler(const struct db_cache *cache_elem, struct insert_data *idata, int num, char **ptr_values, char **ptr_where) { char *aton = NULL, aton_v4[] = "INET_ATON"; aton = aton_v4; snprintf(*ptr_where, SPACELEFT(where_clause), where[num].string, aton, fake_host); snprintf(*ptr_values, SPACELEFT(values_clause), values[num].string, aton, fake_host); *ptr_where += strlen(*ptr_where); *ptr_values += strlen(*ptr_values); } pmacct-1.7.8/src/bmp/0000755000175000017500000000000014354105415013353 5ustar paolopaolopmacct-1.7.8/src/bmp/bmp_msg.c0000644000175000017500000012344514354105275015160 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif u_int32_t bmp_process_packet(char *bmp_packet, u_int32_t len, struct bmp_peer *bmpp, int *do_term) { struct bgp_misc_structs *bms; struct bgp_peer *peer; char *bmp_packet_ptr = bmp_packet; u_int32_t pkt_remaining_len, orig_msg_len, msg_len, msg_start_len; struct bmp_common_hdr *bch = NULL; if (do_term) (*do_term) = FALSE; if (!bmpp) return FALSE; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return FALSE; if (len < sizeof(struct bmp_common_hdr)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: failed bmp_get_and_check_length() BMP common hdr\n", config.name, bms->log_str, peer->addr_str); return FALSE; } for (msg_start_len = pkt_remaining_len = len; pkt_remaining_len; msg_start_len = pkt_remaining_len) { if (!(bch = (struct bmp_common_hdr *) bmp_get_and_check_length(&bmp_packet_ptr, &pkt_remaining_len, sizeof(struct bmp_common_hdr)))) { return msg_start_len; } if (bch->version != BMP_V3 && bch->version != BMP_V4) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: unknown BMP version: %u (2)\n", config.name, bms->log_str, peer->addr_str, bch->version); return FALSE; } peer->version = bch->version; bmp_common_hdr_get_len(bch, &msg_len); msg_len -= sizeof(struct bmp_common_hdr); orig_msg_len = msg_len; if (pkt_remaining_len < msg_len) return msg_start_len; if (bch->type <= BMP_MSG_TYPE_MAX) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] [common] type: %s (%u)\n", config.name, bms->log_str, peer->addr_str, bmp_msg_types[bch->type], bch->type); } switch (bch->type) { case BMP_MSG_ROUTE_MONITOR: bmp_process_msg_route_monitor(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_STATS: bmp_process_msg_stats(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_PEER_DOWN: bmp_process_msg_peer_down(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_PEER_UP: bmp_process_msg_peer_up(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_INIT: bmp_process_msg_init(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_TERM: bmp_process_msg_term(&bmp_packet_ptr, &msg_len, bmpp); if (do_term) (*do_term) = TRUE; break; case BMP_MSG_ROUTE_MIRROR: bmp_process_msg_route_mirror(&bmp_packet_ptr, &msg_len, bmpp); break; case BMP_MSG_TMP_RPAT: bmp_process_msg_rpat(&bmp_packet_ptr, &msg_len, bmpp); break; default: Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: unknown message type (%u)\n", config.name, bms->log_str, peer->addr_str, bch->type); break; } /* sync-up status of pkt_remaining_len to bmp_packet_ptr */ pkt_remaining_len -= (orig_msg_len - msg_len); if (msg_len) { /* let's jump forward: we may have been unable to parse some (sub-)element */ bmp_jump_offset(&bmp_packet_ptr, &pkt_remaining_len, msg_len); } } return FALSE; } void bmp_process_msg_init(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; int ret; /* TLV vars */ struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; /* Init message does not contain a timestamp */ gettimeofday(&bdata.tstamp_arrival, NULL); memset(&bdata.tstamp, 0, sizeof(struct timeval)); while ((*len)) { u_int32_t pen = 0; if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [init] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (bmp_tlv_handle_ebit(&bmp_tlv_type)) { if (!(bmp_tlv_get_pen(bmp_packet, len, &bmp_tlv_len, &pen))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [init] packet discarded: failed bmp_tlv_get_pen()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } if (!(bmp_tlv_value = bmp_get_and_check_length(bmp_packet, len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [init] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret = bmp_tlv_list_add(tlvs, pen, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [init] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, NULL, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_INIT); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, NULL, BMP_LOG_TYPE_INIT); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); } void bmp_process_msg_term(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; int ret = 0; /* TLV vars */ struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; /* Term message does not contain a timestamp */ gettimeofday(&bdata.tstamp_arrival, NULL); memset(&bdata.tstamp, 0, sizeof(struct timeval)); while ((*len)) { u_int32_t pen = 0; if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [term] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (bmp_tlv_handle_ebit(&bmp_tlv_type)) { if (!(bmp_tlv_get_pen(bmp_packet, len, &bmp_tlv_len, &pen))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [term] packet discarded: failed bmp_tlv_get_pen()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } if (!(bmp_tlv_value = bmp_get_and_check_length(bmp_packet, len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [term] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret = bmp_tlv_list_add(tlvs, pen, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [term] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, NULL, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_TERM); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, NULL, BMP_LOG_TYPE_TERM); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); /* BGP peers are deleted as part of bmp_peer_close() */ } void bmp_process_msg_peer_up(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_peer_up_hdr *bpuh; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bpuh = (struct bmp_peer_up_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_up_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP peer up hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_peer_type(bph, &bdata.chars.peer_type); if (bdata.chars.peer_type == BMP_PEER_TYPE_LOC_RIB) { bmp_peer_hdr_get_f_flag(bph, &bdata.chars.is_filtered); bdata.chars.is_loc = TRUE; } else { bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.chars.is_post); bmp_peer_hdr_get_a_flag(bph, &bdata.chars.is_2b_asn); bmp_peer_hdr_get_o_flag(bph, &bdata.chars.is_out); } bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, &bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_rd(bph, &bdata.chars.rd); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); if (bdata.family) { gettimeofday(&bdata.tstamp_arrival, NULL); { struct bmp_log_peer_up blpu; struct bgp_peer bgp_peer_loc, bgp_peer_rem, *bmpp_bgp_peer; struct bmp_chars bmed_bmp; struct bgp_msg_data bmd; int bgp_open_len, ret2 = 0; u_int8_t bgp_msg_type = 0; void *ret = NULL; /* TLV vars */ struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; memset(&bgp_peer_loc, 0, sizeof(bgp_peer_loc)); memset(&bgp_peer_rem, 0, sizeof(bgp_peer_rem)); memset(&bmd, 0, sizeof(bmd)); memset(&bmed_bmp, 0, sizeof(bmed_bmp)); tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; bmp_peer_up_hdr_get_loc_port(bpuh, &blpu.loc_port); bmp_peer_up_hdr_get_rem_port(bpuh, &blpu.rem_port); bmp_peer_up_hdr_get_local_ip(bpuh, &blpu.local_ip, bdata.family); bgp_peer_loc.type = FUNC_TYPE_BMP; bmd.peer = &bgp_peer_loc; bmd.extra.id = BGP_MSG_EXTRA_DATA_BMP; bmd.extra.len = sizeof(bmed_bmp); bmd.extra.data = &bmed_bmp; bgp_msg_data_set_data_bmp(&bmed_bmp, &bdata); /* length checks */ if ((*len) >= sizeof(struct bgp_header)) { bgp_open_len = bgp_get_packet_len((*bmp_packet)); if (bgp_open_len <= 0 || bgp_open_len > (*len)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bgp_get_packet_len()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } else { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer_up] packet discarded: incomplete BGP header\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } if ((bgp_msg_type = bgp_get_packet_type((*bmp_packet))) == BGP_OPEN) { bgp_open_len = bgp_parse_open_msg(&bmd, (*bmp_packet), FALSE, FALSE); if (bgp_open_len == ERR) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bgp_parse_open_msg()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } else { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: wrong BGP message type: %s (%u)\n", config.name, bms->log_str, peer->addr_str, (bgp_msg_type <= BGP_MSG_TYPE_MAX ? bgp_msg_types[bgp_msg_type] : bgp_msg_types[0]), bgp_msg_type); bmp_tlv_list_destroy(tlvs); return; } bmp_get_and_check_length(bmp_packet, len, bgp_open_len); memcpy(&bmpp->self.id, &bgp_peer_loc.id, sizeof(struct host_addr)); memcpy(&bgp_peer_loc.addr, &blpu.local_ip, sizeof(struct host_addr)); bgp_peer_rem.type = FUNC_TYPE_BMP; bmd.peer = &bgp_peer_rem; /* length checks */ if ((*len) >= sizeof(struct bgp_header)) { bgp_open_len = bgp_get_packet_len((*bmp_packet)); if (bgp_open_len <= 0 || bgp_open_len > (*len)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bgp_get_packet_len() (2)\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } else { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer_up] packet discarded: incomplete BGP header (2)\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } if ((bgp_msg_type = bgp_get_packet_type((*bmp_packet))) == BGP_OPEN) { bgp_open_len = bgp_parse_open_msg(&bmd, (*bmp_packet), FALSE, FALSE); if (bgp_open_len == ERR) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bgp_parse_open_msg() (2)\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } else { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: wrong BGP message type: %u (2)\n", config.name, bms->log_str, peer->addr_str, bgp_msg_type); bmp_tlv_list_destroy(tlvs); return; } bmp_get_and_check_length(bmp_packet, len, bgp_open_len); memcpy(&bgp_peer_rem.addr, &bdata.peer_ip, sizeof(struct host_addr)); bmpp_bgp_peer = bmp_sync_loc_rem_peers(&bgp_peer_loc, &bgp_peer_rem); bmpp_bgp_peer->log = bmpp->self.log; bmpp_bgp_peer->bmp_se = bmpp; /* using bmp_se field to back-point a BGP peer to its parent BMP peer */ if (bdata.family == AF_INET) { ret = pm_tsearch(bmpp_bgp_peer, &bmpp->bgp_peers_v4, bgp_peer_cmp, sizeof(struct bgp_peer)); } else if (bdata.family == AF_INET6) { ret = pm_tsearch(bmpp_bgp_peer, &bmpp->bgp_peers_v6, bgp_peer_cmp, sizeof(struct bgp_peer)); } if (!ret) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] [peer up] tsearch() unable to insert.\n", config.name, bms->log_str, peer->addr_str); while ((*len)) { u_int32_t pen = 0; if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (bmp_tlv_handle_ebit(&bmp_tlv_type)) { if (!(bmp_tlv_get_pen(bmp_packet, len, &bmp_tlv_len, &pen))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_tlv_get_pen()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } if (!(bmp_tlv_value = bmp_get_and_check_length(bmp_packet, len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret2 = bmp_tlv_list_add(tlvs, pen, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret2 == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [peer up] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, &blpu, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_PEER_UP); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, &blpu, BMP_LOG_TYPE_PEER_UP); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); } } } void bmp_process_msg_peer_down(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_peer_down_hdr *bpdh; void *ret = NULL; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bpdh = (struct bmp_peer_down_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_down_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer down hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_peer_type(bph, &bdata.chars.peer_type); if (bdata.chars.peer_type == BMP_PEER_TYPE_LOC_RIB) { bdata.chars.is_loc = TRUE; } else { bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.chars.is_post); bmp_peer_hdr_get_o_flag(bph, &bdata.chars.is_out); } bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, &bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_rd(bph, &bdata.chars.rd); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); if (bdata.family) { gettimeofday(&bdata.tstamp_arrival, NULL); { struct bmp_log_peer_down blpd; int ret2 = 0; /* TLV vars */ struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; bmp_peer_down_hdr_get_reason(bpdh, &blpd.reason); if (blpd.reason == BMP_PEER_DOWN_LOC_CODE) bmp_peer_down_hdr_get_loc_code(bmp_packet, len, &blpd.loc_code); /* draft-ietf-grow-bmp-tlv */ if (peer->version == BMP_V4) { /* let's skip intermediate data in order to get to TLVs */ if (blpd.reason == BMP_PEER_DOWN_LOC_NOT_MSG || blpd.reason == BMP_PEER_DOWN_REM_NOT_MSG) { int bgp_notification_len = 0; bgp_notification_len = bgp_get_packet_len((*bmp_packet)); if (bgp_notification_len <= 0 || bgp_notification_len > (*len)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bgp_get_packet_len() reason=%u\n", config.name, bms->log_str, peer->addr_str, blpd.reason); bmp_tlv_list_destroy(tlvs); return; } bmp_jump_offset(bmp_packet, len, bgp_notification_len); } else if (blpd.reason == BMP_PEER_DOWN_LOC_CODE) { ret2 = bmp_jump_offset(bmp_packet, len, 2); if (ret2 == ERR) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_jump_offset() reason=%u\n", config.name, bms->log_str, peer->addr_str, blpd.reason); bmp_tlv_list_destroy(tlvs); return; } } while ((*len)) { u_int32_t pen = 0; if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (bmp_tlv_handle_ebit(&bmp_tlv_type)) { if (!(bmp_tlv_get_pen(bmp_packet, len, &bmp_tlv_len, &pen))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_tlv_get_pen()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } if (!(bmp_tlv_value = bmp_get_and_check_length(bmp_packet, len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret2 = bmp_tlv_list_add(tlvs, pen, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret2 == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [peer down] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } } if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, &blpd, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_PEER_DOWN); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, &blpd, BMP_LOG_TYPE_PEER_DOWN); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); } if (bdata.family == AF_INET) { ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers_v4, bgp_peer_host_addr_cmp); } else if (bdata.family == AF_INET6) { ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers_v6, bgp_peer_host_addr_cmp); } if (ret) { bmpp_bgp_peer = (*(struct bgp_peer **) ret); bgp_peer_info_delete(bmpp_bgp_peer); if (bdata.family == AF_INET) { pm_tdelete(&bdata.peer_ip, &bmpp->bgp_peers_v4, bgp_peer_host_addr_cmp); } else if (bdata.family == AF_INET6) { pm_tdelete(&bdata.peer_ip, &bmpp->bgp_peers_v6, bgp_peer_host_addr_cmp); } } /* missing BMP peer up message, ie. case of replay/replication of BMP messages */ else { char peer_ip[INET6_ADDRSTRLEN]; addr_to_str(peer_ip, &bdata.peer_ip); if (!log_notification_isset(&bmpp->missing_peer_up, bdata.tstamp_arrival.tv_sec)) { log_notification_set(&bmpp->missing_peer_up, bdata.tstamp_arrival.tv_sec, BMP_MISSING_PEER_UP_LOG_TOUT); Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: missing peer up BMP message for peer %s\n", config.name, bms->log_str, peer->addr_str, peer_ip); } } } } void bmp_process_msg_route_monitor(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; int bgp_update_len, ret2 = 0; u_int8_t bgp_msg_type = 0; void *ret = NULL; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_peer_type(bph, &bdata.chars.peer_type); if (bdata.chars.peer_type == BMP_PEER_TYPE_LOC_RIB) { bmp_peer_hdr_get_f_flag(bph, &bdata.chars.is_filtered); bdata.chars.is_loc = TRUE; } else { bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.chars.is_post); bmp_peer_hdr_get_a_flag(bph, &bdata.chars.is_2b_asn); bmp_peer_hdr_get_o_flag(bph, &bdata.chars.is_out); } bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, &bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_rd(bph, &bdata.chars.rd); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); if (bdata.family) { gettimeofday(&bdata.tstamp_arrival, NULL); if (bdata.family == AF_INET) { ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers_v4, bgp_peer_host_addr_cmp); } else if (bdata.family == AF_INET6) { ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers_v6, bgp_peer_host_addr_cmp); } if (ret) { struct bmp_chars bmed_bmp; struct bgp_msg_data bmd; bmpp_bgp_peer = (*(struct bgp_peer **) ret); memset(&bmd, 0, sizeof(bmd)); memset(&bmed_bmp, 0, sizeof(bmed_bmp)); bmd.peer = bmpp_bgp_peer; bmd.extra.id = BGP_MSG_EXTRA_DATA_BMP; bmd.extra.len = sizeof(bmed_bmp); bmd.extra.data = &bmed_bmp; bgp_msg_data_set_data_bmp(&bmed_bmp, &bdata); compose_timestamp(bms->log_tstamp_str, SRVBUFLEN, &bdata.tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); encode_tstamp_arrival(bms->log_tstamp_str, SRVBUFLEN, &bdata.tstamp_arrival, TRUE); /* length checks & draft-ietf-grow-bmp-tlv preps */ if ((*len) >= sizeof(struct bgp_header)) { bgp_update_len = bgp_get_packet_len((*bmp_packet)); if (bgp_update_len <= 0 || bgp_update_len > (*len)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: bgp_get_packet_len() failed\n", config.name, bms->log_str, peer->addr_str); return; } } else { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: incomplete BGP header\n", config.name, bms->log_str, peer->addr_str); return; } if (peer->version == BMP_V4 && bgp_update_len && bgp_update_len < (*len)) { struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; u_int32_t loc_len = (*len); char *loc_ptr = (*bmp_packet); bmp_jump_offset(&loc_ptr, &loc_len, bgp_update_len); while (loc_len) { u_int32_t pen = 0; if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(&loc_ptr, &loc_len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (bmp_tlv_handle_ebit(&bmp_tlv_type)) { if (!(bmp_tlv_get_pen(&loc_ptr, &loc_len, &bmp_tlv_len, &pen))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: failed bmp_tlv_get_pen()\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } } if (!(bmp_tlv_value = bmp_get_and_check_length(&loc_ptr, &loc_len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret2 = bmp_tlv_list_add(tlvs, pen, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret2 == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [route monitor] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } bmed_bmp.tlvs = tlvs; } if ((bgp_msg_type = bgp_get_packet_type((*bmp_packet))) == BGP_UPDATE) { bgp_update_len = bgp_parse_update_msg(&bmd, (*bmp_packet)); if (bgp_update_len <= 0) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: bgp_parse_update_msg() failed\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(bmed_bmp.tlvs); return; } } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] [route monitor] packet discarded: unsupported BGP message type: %s (%u)\n", config.name, bms->log_str, peer->addr_str, (bgp_msg_type <= BGP_MSG_TYPE_MAX ? bgp_msg_types[bgp_msg_type] : bgp_msg_types[0]), bgp_msg_type); } bmp_get_and_check_length(bmp_packet, len, bgp_update_len); bmp_tlv_list_destroy(bmed_bmp.tlvs); } /* missing BMP peer up message, ie. case of replay/replication of BMP messages */ else { if (!log_notification_isset(&bmpp->missing_peer_up, bdata.tstamp_arrival.tv_sec)) { char peer_ip[INET6_ADDRSTRLEN]; addr_to_str(peer_ip, &bdata.peer_ip); log_notification_set(&bmpp->missing_peer_up, bdata.tstamp_arrival.tv_sec, BMP_MISSING_PEER_UP_LOG_TOUT); Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route monitor] packet discarded: missing peer up BMP message for peer %s\n", config.name, bms->log_str, peer->addr_str, peer_ip); } } } } void bmp_process_msg_route_mirror(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route mirror] packet discarded: Unicorn! Message type currently not supported.\n", config.name, bms->log_str, peer->addr_str); // XXX: maybe support route mirroring } void bmp_process_msg_stats(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_stats_hdr *bsh; struct bmp_stats_cnt_hdr *bsch; u_int64_t cnt_data64; u_int32_t index, count = 0, cnt_data32; u_int16_t cnt_type, cnt_len; afi_t afi; safi_t safi; int ret; /* unknown stats TLVs */ char *cnt_value; struct pm_list *tlvs = NULL; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bsh = (struct bmp_stats_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_stats_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP stats hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_peer_type(bph, &bdata.chars.peer_type); if (bdata.chars.peer_type == BMP_PEER_TYPE_LOC_RIB) { bmp_peer_hdr_get_f_flag(bph, &bdata.chars.is_filtered); bdata.chars.is_loc = TRUE; } else { bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.chars.is_post); bmp_peer_hdr_get_o_flag(bph, &bdata.chars.is_out); } bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, &bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_rd(bph, &bdata.chars.rd); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_stats_hdr_get_count(bsh, &count); if (bdata.family) { gettimeofday(&bdata.tstamp_arrival, NULL); for (index = 0; index < count; index++) { if (!(bsch = (struct bmp_stats_cnt_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_stats_cnt_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP stats cnt hdr #%u\n", config.name, bms->log_str, peer->addr_str, index); return; } cnt_value = 0; tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; bmp_stats_cnt_hdr_get_type(bsch, &cnt_type); bmp_stats_cnt_hdr_get_len(bsch, &cnt_len); cnt_data32 = 0, cnt_data64 = 0, afi = 0, safi = 0; switch (cnt_type) { case BMP_STATS_TYPE0: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE1: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE2: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE3: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE4: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE5: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE6: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE7: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; case BMP_STATS_TYPE8: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; case BMP_STATS_TYPE9: if (cnt_len == 11) bmp_stats_cnt_get_afi_safi_data64(bmp_packet, len, &afi, &safi, &cnt_data64); break; case BMP_STATS_TYPE10: if (cnt_len == 11) bmp_stats_cnt_get_afi_safi_data64(bmp_packet, len, &afi, &safi, &cnt_data64); break; case BMP_STATS_TYPE11: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE12: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE13: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE14: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; case BMP_STATS_TYPE15: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; case BMP_STATS_TYPE16: if (cnt_len == 11) bmp_stats_cnt_get_afi_safi_data64(bmp_packet, len, &afi, &safi, &cnt_data64); break; case BMP_STATS_TYPE17: if (cnt_len == 11) bmp_stats_cnt_get_afi_safi_data64(bmp_packet, len, &afi, &safi, &cnt_data64); break; default: if (!(cnt_value = bmp_get_and_check_length(bmp_packet, len, cnt_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } ret = bmp_tlv_list_add(tlvs, 0, cnt_type, cnt_len, cnt_value); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [stats] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } break; } if (cnt_data32 && !cnt_data64) cnt_data64 = cnt_data32; { struct bmp_log_stats blstats; memset(&blstats, 0, sizeof(blstats)); blstats.cnt_type = cnt_type; blstats.cnt_afi = afi; blstats.cnt_safi = safi; blstats.cnt_data = cnt_data64; if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, &blstats, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_STATS); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, &blstats, BMP_LOG_TYPE_STATS); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); } } } } void bmp_common_hdr_get_len(struct bmp_common_hdr *bch, u_int32_t *len) { if (bch && len) (*len) = ntohl(bch->len); } void bmp_tlv_hdr_get_type(struct bmp_tlv_hdr *bth, u_int16_t *type) { if (bth && type) (*type) = ntohs(bth->type); } void bmp_tlv_hdr_get_len(struct bmp_tlv_hdr *bth, u_int16_t *len) { if (bth && len) (*len) = ntohs(bth->len); } void bmp_term_hdr_get_reason_type(char **bmp_packet, u_int32_t *pkt_size, u_int16_t *type) { char *ptr; if (bmp_packet && (*bmp_packet) && pkt_size && type) { ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 2); if (ptr) { memcpy(type, ptr, 2); (*type) = ntohs((*type)); } } } void bmp_peer_hdr_get_v_flag(struct bmp_peer_hdr *bph, u_int8_t *family) { u_int8_t version; if (bph && family) { version = (bph->flags & BMP_PEER_FLAGS_ARI_V); (*family) = FALSE; if (version == 0) (*family) = AF_INET; else (*family) = AF_INET6; } } void bmp_peer_hdr_get_l_flag(struct bmp_peer_hdr *bph, u_int8_t *is_post) { if (bph && is_post) { if (bph->flags & BMP_PEER_FLAGS_ARI_L) (*is_post) = TRUE; else (*is_post) = FALSE; } } void bmp_peer_hdr_get_a_flag(struct bmp_peer_hdr *bph, u_int8_t *is_2b_asn) { if (bph && is_2b_asn) { if (bph->flags & BMP_PEER_FLAGS_ARI_A) (*is_2b_asn) = TRUE; else (*is_2b_asn) = FALSE; } } void bmp_peer_hdr_get_f_flag(struct bmp_peer_hdr *bph, u_int8_t *is_filtered) { if (bph && is_filtered) { if (bph->flags & BMP_PEER_FLAGS_LR_F) (*is_filtered) = TRUE; else (*is_filtered) = FALSE; } } void bmp_peer_hdr_get_o_flag(struct bmp_peer_hdr *bph, u_int8_t *is_out) { if (bph && is_out) { if (bph->flags & BMP_PEER_FLAGS_ARO_O) (*is_out) = TRUE; else (*is_out) = FALSE; } } void bmp_peer_hdr_get_peer_ip(struct bmp_peer_hdr *bph, struct host_addr *a, u_int8_t *family) { if (bph && a) { if ((*family) == AF_INET) a->address.ipv4.s_addr = bph->addr[3]; else if ((*family) == AF_INET6) memcpy(&a->address.ipv6, &bph->addr, 16); else { memset(a, 0, sizeof(struct host_addr)); if (!bph->addr[0] && !bph->addr[1] && !bph->addr[2] && !bph->addr[3]) { (*family) = AF_INET; /* we just set this up to something non-zero */ } } a->family = (*family); } } void bmp_peer_hdr_get_bgp_id(struct bmp_peer_hdr *bph, struct host_addr *a) { if (bph && a) { a->family = AF_INET; a->address.ipv4.s_addr = bph->bgp_id; } } void bmp_peer_hdr_get_rd(struct bmp_peer_hdr *bph, rd_t *rd) { if (bph && rd) { if (bph->type == BMP_PEER_TYPE_L3VPN || bph->type == BMP_PEER_TYPE_LOC_RIB) { memcpy(rd, bph->rd, RD_LEN); bgp_rd_ntoh(rd); if (!is_empty_256b(rd, RD_LEN)) { bgp_rd_origin_set(rd, RD_ORIGIN_BMP); } } } } void bmp_peer_hdr_get_tstamp(struct bmp_peer_hdr *bph, struct timeval *tv) { u_int32_t sec, usec; if (bph && tv) { if (bph->tstamp_sec) { sec = ntohl(bph->tstamp_sec); usec = ntohl(bph->tstamp_usec); tv->tv_sec = sec; tv->tv_usec = usec; } } } void bmp_peer_hdr_get_peer_asn(struct bmp_peer_hdr *bph, u_int32_t *asn) { if (bph && asn) (*asn) = ntohl(bph->asn); } void bmp_peer_hdr_get_peer_type(struct bmp_peer_hdr *bph, u_int8_t *type) { if (bph && type) (*type) = bph->type; } void bmp_peer_up_hdr_get_local_ip(struct bmp_peer_up_hdr *bpuh, struct host_addr *a, u_int8_t family) { if (bpuh && a && family) { a->family = family; if (family == AF_INET) a->address.ipv4.s_addr = bpuh->loc_addr[3]; else if (family == AF_INET6) memcpy(&a->address.ipv6, &bpuh->loc_addr, 16); } } void bmp_peer_up_hdr_get_loc_port(struct bmp_peer_up_hdr *bpuh, u_int16_t *port) { if (bpuh && port) (*port) = ntohs(bpuh->loc_port); } void bmp_peer_up_hdr_get_rem_port(struct bmp_peer_up_hdr *bpuh, u_int16_t *port) { if (bpuh && port) (*port) = ntohs(bpuh->rem_port); } void bmp_peer_down_hdr_get_reason(struct bmp_peer_down_hdr *bpdh, u_char *reason) { if (bpdh && reason) (*reason) = bpdh->reason; } void bmp_peer_down_hdr_get_loc_code(char **bmp_packet, u_int32_t *pkt_size, u_int16_t *code) { char *ptr; if (bmp_packet && (*bmp_packet) && pkt_size && code) { ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 2); memcpy(code, ptr, 2); (*code) = ntohs((*code)); } } void bmp_stats_hdr_get_count(struct bmp_stats_hdr *bsh, u_int32_t *count) { if (bsh && count) (*count) = ntohl(bsh->count); } void bmp_stats_cnt_hdr_get_type(struct bmp_stats_cnt_hdr *bsch, u_int16_t *type) { if (bsch && type) (*type) = ntohs(bsch->type); } void bmp_stats_cnt_hdr_get_len(struct bmp_stats_cnt_hdr *bsch, u_int16_t *len) { if (bsch && len) (*len) = ntohs(bsch->len); } void bmp_stats_cnt_get_data32(char **bmp_packet, u_int32_t *pkt_size, u_int32_t *data) { char *ptr; if (bmp_packet && (*bmp_packet) && pkt_size && data) { ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 4); memcpy(data, ptr, 4); (*data) = ntohl((*data)); } } void bmp_stats_cnt_get_data64(char **bmp_packet, u_int32_t *pkt_size, u_int64_t *data) { char *ptr; if (bmp_packet && (*bmp_packet) && pkt_size && data) { ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 8); memcpy(data, ptr, 8); (*data) = pm_ntohll((*data)); } } void bmp_stats_cnt_get_afi_safi_data64(char **bmp_packet, u_int32_t *pkt_size, afi_t *afi, safi_t *safi, u_int64_t *data) { char *ptr; if (bmp_packet && (*bmp_packet) && pkt_size && afi && safi && data) { ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 2); memcpy(afi, ptr, 2); (*afi) = ntohs((*afi)); ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 1); memcpy(safi, ptr, 1); ptr = bmp_get_and_check_length(bmp_packet, pkt_size, 8); memcpy(data, ptr, 8); (*data) = pm_ntohll((*data)); } } pmacct-1.7.8/src/bmp/bmp.c0000644000175000017500000013127014354105275014305 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" #include "rpki/rpki.h" #include "thread_pool.h" #include "ip_flow.h" #include "ip_frag.h" #if defined WITH_EBPF #include "ebpf/ebpf_rp_balancer.h" #endif #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined WITH_AVRO #include "plugin_cmn_avro.h" #endif /* variables to be exported away */ thread_pool_t *bmp_pool; bgp_tag_t bmp_logdump_tag; struct sockaddr_storage bmp_logdump_tag_peer; /* Functions */ void bmp_daemon_wrapper() { /* initialize variables */ if (!config.bmp_daemon_port) config.bmp_daemon_port = BMP_TCP_PORT; /* initialize threads pool */ bmp_pool = allocate_thread_pool(1); assert(bmp_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/BMP ): %d thread(s) initialized\n", config.name, 1); bmp_prepare_thread(); /* giving a kick to the BMP thread */ send_to_pool(bmp_pool, skinny_bmp_daemon, NULL); } int skinny_bmp_daemon() { int ret, rc, peers_idx, allowed, yes=1, do_term; int peers_idx_rr = 0, max_peers_idx = 0; time_t now; afi_t afi; safi_t safi; socklen_t slen, clen; struct bmp_peer *bmpp = NULL; struct bgp_peer *peer = NULL; struct sockaddr_storage server, client; struct hosts_table allow; struct host_addr addr; struct bgp_peer_batch bp_batch; sigset_t signal_set; /* select() stuff */ fd_set read_descs, bkp_read_descs; int fd, select_fd, bkp_select_fd, recalc_fds, select_num; /* logdump time management */ time_t dump_refresh_deadline = {0}; struct timeval dump_refresh_timeout, *drt_ptr; /* pcap_savefile stuff */ struct packet_ptrs recv_pptrs; unsigned char *bmp_packet; int sf_ret, pcap_savefile_round = 1; /* bmp_daemon_tag_map stuff */ struct plugin_requests req; struct id_table bmp_logdump_tag_table; int bmp_logdump_tag_map_allocated; /* initial cleanups */ reload_map_bmp_thread = FALSE; reload_log_bmp_thread = FALSE; memset(&server, 0, sizeof(server)); memset(&client, 0, sizeof(client)); memset(&allow, 0, sizeof(struct hosts_table)); clen = sizeof(client); memset(&recv_pptrs, 0, sizeof(recv_pptrs)); memset(&device, 0, sizeof(device)); bmp_packet = malloc(BGP_BUFFER_SIZE); bmp_routing_db = &inter_domain_routing_dbs[FUNC_TYPE_BMP]; memset(bmp_routing_db, 0, sizeof(struct bgp_rt_structs)); /* socket creation for BMP server: IPv4 only */ if (!config.bmp_daemon_ip && !config.pcap_savefile) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&server; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.bmp_daemon_port); slen = sizeof(struct sockaddr_in6); } else if (config.bmp_daemon_ip) { trim_spaces(config.bmp_daemon_ip); ret = str_to_addr(config.bmp_daemon_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bmp_daemon_ip' value is not a valid IPv4/IPv6 address. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } slen = addr_to_sa((struct sockaddr *)&server, &addr, config.bmp_daemon_port); } if (config.bmp_daemon_ip && config.pcap_savefile) { Log(LOG_ERR, "ERROR ( %s/%s ): bmp_daemon_ip and pcap_savefile directives are mutually exclusive. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } if (config.pcap_savefile && bmp_misc_db->is_thread) { Log(LOG_ERR, "ERROR ( %s/%s ): pcap_savefile directive only applies to pmbmpd. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } if (!config.bmp_daemon_max_peers) config.bmp_daemon_max_peers = BMP_MAX_PEERS_DEFAULT; Log(LOG_INFO, "INFO ( %s/%s ): maximum BMP peers allowed: %d\n", config.name, bmp_misc_db->log_str, config.bmp_daemon_max_peers); bmp_peers = malloc(config.bmp_daemon_max_peers*sizeof(struct bmp_peer)); if (!bmp_peers) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BMP peers structure. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } memset(bmp_peers, 0, config.bmp_daemon_max_peers*sizeof(struct bmp_peer)); if (config.rpki_roas_file || config.rpki_rtr_cache) { rpki_daemon_wrapper(); /* Let's give the RPKI thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } if (config.bmp_daemon_msglog_file || config.bmp_daemon_msglog_amqp_routing_key || config.bmp_daemon_msglog_kafka_topic) { if (config.bmp_daemon_msglog_file) bmp_misc_db->msglog_backend_methods++; if (config.bmp_daemon_msglog_amqp_routing_key) bmp_misc_db->msglog_backend_methods++; if (config.bmp_daemon_msglog_kafka_topic) bmp_misc_db->msglog_backend_methods++; if (bmp_misc_db->msglog_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): bmp_daemon_msglog_file, bmp_daemon_msglog_amqp_routing_key and bmp_daemon_msglog_kafka_topic are mutually exclusive. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } } if (config.bmp_dump_file || config.bmp_dump_amqp_routing_key || config.bmp_dump_kafka_topic) { if (config.bmp_dump_file) bmp_misc_db->dump_backend_methods++; if (config.bmp_dump_amqp_routing_key) bmp_misc_db->dump_backend_methods++; if (config.bmp_dump_kafka_topic) bmp_misc_db->dump_backend_methods++; if (bmp_misc_db->dump_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): bmp_dump_file, bmp_dump_amqp_routing_key and bmp_dump_kafka_topic are mutually exclusive. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } } if (bmp_misc_db->msglog_backend_methods || bmp_misc_db->dump_backend_methods) bgp_peer_log_seq_init(&bmp_misc_db->log_seq); if (bmp_misc_db->msglog_backend_methods) { bmp_misc_db->peers_log = malloc(config.bmp_daemon_max_peers*sizeof(struct bgp_peer_log)); if (!bmp_misc_db->peers_log) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() BMP peers log structure. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } memset(bmp_misc_db->peers_log, 0, config.bmp_daemon_max_peers*sizeof(struct bgp_peer_log)); if (config.bmp_daemon_msglog_amqp_routing_key) { #ifdef WITH_RABBITMQ bmp_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&bmp_daemon_msglog_amqp_host); if (!config.bmp_daemon_msglog_amqp_retry) config.bmp_daemon_msglog_amqp_retry = AMQP_DEFAULT_RETRY; #else Log(LOG_WARNING, "WARN ( %s/%s ): p_amqp_connect_to_publish() not possible due to missing --enable-rabbitmq\n", config.name, bmp_misc_db->log_str); #endif } if (config.bmp_daemon_msglog_kafka_topic) { #ifdef WITH_KAFKA bmp_daemon_msglog_init_kafka_host(); #else Log(LOG_WARNING, "WARN ( %s/%s ): p_kafka_connect_to_produce() not possible due to missing --enable-kafka\n", config.name, bmp_misc_db->log_str); #endif } } if (!config.bmp_table_attr_hash_buckets) config.bmp_table_attr_hash_buckets = HASHTABSIZE; bgp_attr_init(config.bmp_table_attr_hash_buckets, bmp_routing_db); if (!config.bmp_table_peer_buckets) config.bmp_table_peer_buckets = DEFAULT_BGP_INFO_HASH; if (!config.bmp_table_per_peer_buckets) config.bmp_table_per_peer_buckets = DEFAULT_BGP_INFO_PER_PEER_HASH; if (config.bmp_table_per_peer_hash == BGP_ASPATH_HASH_PATHID) bmp_route_info_modulo = bmp_route_info_modulo_pathid; else { Log(LOG_ERR, "ERROR ( %s/%s ): Unknown 'bmp_table_per_peer_hash' value. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } if (!config.pcap_savefile) { config.bmp_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); if (config.bmp_sock < 0) { /* retry with IPv4 */ if (!config.bmp_daemon_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.bmp_daemon_port); slen = sizeof(struct sockaddr_in); config.bmp_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); } if (config.bmp_sock < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): thread socket() failed. Terminating thread.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } } setnonblocking(config.bmp_sock); setsockopt(config.bmp_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&yes, sizeof(yes)); if (config.bmp_daemon_ipprec) { int opt = config.bmp_daemon_ipprec << 5; rc = setsockopt(config.bmp_sock, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IP_TOS (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); } #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.bmp_sock, SOL_SOCKET, SO_REUSEPORT, (char *)&yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEPORT (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); #endif #if (defined HAVE_SO_BINDTODEVICE) if (config.bmp_daemon_interface) { rc = setsockopt(config.bmp_sock, SOL_SOCKET, SO_BINDTODEVICE, config.bmp_daemon_interface, (socklen_t) strlen(config.bmp_daemon_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); } #endif rc = setsockopt(config.bmp_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEADDR (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); if (config.bmp_daemon_ipv6_only) { int yes=1; rc = setsockopt(config.bmp_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IPV6_V6ONLY (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); } if (config.bmp_daemon_pipe_size) { socklen_t l = sizeof(config.bmp_daemon_pipe_size); int saved = 0, obtained = 0; getsockopt(config.bmp_sock, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(config.bmp_sock, SOL_SOCKET, SO_RCVBUF, &config.bmp_daemon_pipe_size, (socklen_t) sizeof(config.bmp_daemon_pipe_size)); getsockopt(config.bmp_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Setsocksize(config.bmp_sock, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(config.bmp_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Log(LOG_INFO, "INFO ( %s/%s ): bmp_daemon_pipe_size: obtained=%d target=%d.\n", config.name, bmp_misc_db->log_str, obtained, config.bmp_daemon_pipe_size); } rc = bind(config.bmp_sock, (struct sockaddr *) &server, slen); if (rc < 0) { char null_ip_address[] = "0.0.0.0"; char *ip_address; ip_address = config.bmp_daemon_ip ? config.bmp_daemon_ip : null_ip_address; Log(LOG_ERR, "ERROR ( %s/%s ): bind() to ip=%s port=%d/tcp failed (errno: %d).\n", config.name, bmp_misc_db->log_str, ip_address, config.bmp_daemon_port, errno); exit_gracefully(1); } rc = listen(config.bmp_sock, 1); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): listen() failed (errno: %d).\n", config.name, bmp_misc_db->log_str, errno); exit_gracefully(1); } { char srv_string[INET6_ADDRSTRLEN]; struct host_addr srv_addr; u_int16_t srv_port; sa_to_addr((struct sockaddr *)&server, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/%s ): waiting for BMP data on %s:%u\n", config.name, bmp_misc_db->log_str, srv_string, srv_port); } #if defined WITH_EBPF if (config.bmp_daemon_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(config.bmp_sock, config.bmp_daemon_rp_ebpf_prog, config.cluster_name, "bmp", config.cluster_id, TRUE); } #endif /* Preparing ACL, if any */ if (config.bmp_daemon_allow_file) load_allow_file(config.bmp_daemon_allow_file, &allow); } else { open_pcap_savefile(&device, config.pcap_savefile); pm_pcap_add_filter(&device); config.bmp_sock = pcap_get_selectable_fd(device.dev_desc); enable_ip_fragment_handler(); Log(LOG_INFO, "INFO ( %s/core ): reading BMP data from: %s\n", config.name, config.pcap_savefile); allowed = TRUE; sleep(2); } /* Preparing for syncronous I/O multiplexing */ select_fd = 0; FD_ZERO(&bkp_read_descs); FD_SET(config.bmp_sock, &bkp_read_descs); /* Let's initialize clean shared RIB */ for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { bmp_routing_db->rib[afi][safi] = bgp_table_init(afi, safi); } } /* BMP peers batching checks */ if ((config.bmp_daemon_batch && !config.bmp_daemon_batch_interval) || (config.bmp_daemon_batch_interval && !config.bmp_daemon_batch)) { Log(LOG_WARNING, "WARN ( %s/%s ): 'bmp_daemon_batch_interval' and 'bmp_daemon_batch' both set to zero.\n", config.name, bmp_misc_db->log_str); config.bmp_daemon_batch = 0; config.bmp_daemon_batch_interval = 0; } else bgp_batch_init(&bp_batch, config.bmp_daemon_batch, config.bmp_daemon_batch_interval); /* bmp_link_misc_structs() will re-apply. But we need to anticipate this definition in order to build the Avro schemas correctly */ bmp_misc_db->tag_map = config.bmp_daemon_tag_map; if (bmp_misc_db->msglog_backend_methods) { #ifdef WITH_JANSSON if (!config.bmp_daemon_msglog_output) config.bmp_daemon_msglog_output = PRINT_OUTPUT_JSON; #else Log(LOG_WARNING, "WARN ( %s/%s ): bmp_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", config.name, bmp_misc_db->log_str); #endif #ifdef WITH_AVRO if ((config.bmp_daemon_msglog_output == PRINT_OUTPUT_AVRO_BIN) || (config.bmp_daemon_msglog_output == PRINT_OUTPUT_AVRO_JSON)) { assert(BMP_MSG_TYPE_MAX < BMP_LOG_TYPE_LOGINIT); assert(BMP_LOG_TYPE_MAX < MAX_AVRO_SCHEMA); bmp_misc_db->msglog_avro_schema[BMP_MSG_ROUTE_MONITOR] = p_avro_schema_build_bmp_rm(BGP_LOGDUMP_ET_LOG, "bmp_msglog_rm"); bmp_misc_db->msglog_avro_schema[BMP_MSG_STATS] = p_avro_schema_build_bmp_stats("bmp_stats"); bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_DOWN] = p_avro_schema_build_bmp_peer_down("bmp_peer_down"); bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_UP] = p_avro_schema_build_bmp_peer_up("bmp_peer_up"); bmp_misc_db->msglog_avro_schema[BMP_MSG_INIT] = p_avro_schema_build_bmp_init("bmp_init"); bmp_misc_db->msglog_avro_schema[BMP_MSG_TERM] = p_avro_schema_build_bmp_term("bmp_term"); bmp_misc_db->msglog_avro_schema[BMP_MSG_TMP_RPAT] = p_avro_schema_build_bmp_rpat("bmp_rpat"); bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGINIT] = p_avro_schema_build_bmp_log_initclose(BGP_LOGDUMP_ET_LOG, "bmp_loginit"); bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGCLOSE] = p_avro_schema_build_bmp_log_initclose(BGP_LOGDUMP_ET_LOG, "bmp_logclose"); if (config.bmp_daemon_msglog_avro_schema_file) { char p_avro_schema_file[SRVBUFLEN]; if (strlen(config.bmp_daemon_msglog_avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bmp_daemon_msglog_avro_schema_file' too long. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_msglog_rm", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_ROUTE_MONITOR]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_stats", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_STATS]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_peer_down", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_DOWN]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_peer_up", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_UP]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_init", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_INIT]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_term", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_TERM]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_rpat", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_MSG_TMP_RPAT]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_loginit", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGINIT]); write_avro_schema_to_file_with_suffix(config.bmp_daemon_msglog_avro_schema_file, "-bmp_logclose", p_avro_schema_file, bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGCLOSE]); } if (config.bmp_daemon_msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES if (strchr(config.bmp_daemon_msglog_kafka_topic, '$')) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'bmp_daemon_msglog_kafka_topic' is not compatible with 'bmp_daemon_msglog_kafka_avro_schema_registry'. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } if (config.bmp_daemon_msglog_output == PRINT_OUTPUT_AVRO_JSON) { Log(LOG_ERR, "ERROR ( %s/%s ): 'avro_json' output is not compatible with 'bmp_daemon_msglog_kafka_avro_schema_registry'. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } bmp_daemon_msglog_prepare_sd_schemas(); #endif } } #endif } if (bmp_misc_db->dump_backend_methods) { if (!config.bmp_dump_workers) { config.bmp_dump_workers = 1; } #ifdef WITH_JANSSON if (!config.bmp_dump_output) { config.bmp_dump_output = PRINT_OUTPUT_JSON; } #else Log(LOG_WARNING, "WARN ( %s/%s ): bmp_table_dump_output set to json but will produce no output (missing --enable-jansson).\n", config.name, bmp_misc_db->log_str); #endif #ifdef WITH_AVRO if ((config.bmp_dump_output == PRINT_OUTPUT_AVRO_BIN) || (config.bmp_dump_output == PRINT_OUTPUT_AVRO_JSON)) { assert(BMP_MSG_TYPE_MAX < BMP_LOG_TYPE_LOGINIT); assert(BMP_LOG_TYPE_MAX < MAX_AVRO_SCHEMA); bmp_misc_db->dump_avro_schema[BMP_MSG_ROUTE_MONITOR] = p_avro_schema_build_bmp_rm(BGP_LOGDUMP_ET_DUMP, "bmp_dump_rm"); bmp_misc_db->dump_avro_schema[BMP_MSG_STATS] = p_avro_schema_build_bmp_stats("bmp_stats"); bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_DOWN] = p_avro_schema_build_bmp_peer_down("bmp_peer_down"); bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_UP] = p_avro_schema_build_bmp_peer_up("bmp_peer_up"); bmp_misc_db->dump_avro_schema[BMP_MSG_INIT] = p_avro_schema_build_bmp_init("bmp_init"); bmp_misc_db->dump_avro_schema[BMP_MSG_TERM] = p_avro_schema_build_bmp_term("bmp_term"); bmp_misc_db->dump_avro_schema[BMP_MSG_TMP_RPAT] = p_avro_schema_build_bmp_rpat("bmp_rpat"); bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPINIT] = p_avro_schema_build_bmp_dump_init(BGP_LOGDUMP_ET_DUMP, "bmp_dumpinit"); bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPCLOSE] = p_avro_schema_build_bmp_dump_close(BGP_LOGDUMP_ET_DUMP, "bmp_dumpclose"); if (config.bmp_dump_avro_schema_file) { char p_avro_schema_file[SRVBUFLEN]; if (strlen(config.bmp_dump_avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'bmp_table_dump_avro_schema_file' too long. Exiting ..\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_dump_rm", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_ROUTE_MONITOR]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_stats", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_STATS]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_peer_down", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_DOWN]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_peer_up", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_UP]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_init", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_INIT]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_term", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_TERM]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_rpat", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_MSG_TMP_RPAT]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_dumpinit", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPINIT]); write_avro_schema_to_file_with_suffix(config.bmp_dump_avro_schema_file, "-bmp_dumpclose", p_avro_schema_file, bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPCLOSE]); } } #endif } if (bmp_misc_db->dump_backend_methods) { char dump_roundoff[] = "m"; time_t tmp_time; if (!config.bmp_dump_time_slots) { config.bmp_dump_time_slots = 1; } bmp_misc_db->current_slot = 0; if (config.bmp_dump_refresh_time % config.bmp_dump_time_slots != 0) { Log(LOG_WARNING, "WARN ( %s/%s ): 'bmp_dump_time_slots' is not a divisor of 'bmp_dump_refresh_time', please fix.\n", config.name, bmp_misc_db->log_str); } if (config.bmp_dump_refresh_time) { gettimeofday(&bmp_misc_db->log_tstamp, NULL); dump_refresh_deadline = bmp_misc_db->log_tstamp.tv_sec; tmp_time = roundoff_time(dump_refresh_deadline, dump_roundoff); while ((tmp_time+config.bmp_dump_refresh_time) < dump_refresh_deadline) { tmp_time += config.bmp_dump_refresh_time; } dump_refresh_deadline = tmp_time; dump_refresh_deadline += config.bmp_dump_refresh_time; /* it's a deadline not a basetime */ } else { config.bmp_dump_file = NULL; bmp_misc_db->dump_backend_methods = FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): Invalid 'bmp_dump_refresh_time'.\n", config.name, bmp_misc_db->log_str); } } #ifdef WITH_AVRO bmp_misc_db->avro_buf = malloc(LARGEBUFLEN); if (!bmp_misc_db->avro_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (avro_buf). Exiting ..\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); } else memset(bmp_misc_db->avro_buf, 0, LARGEBUFLEN); #endif if (config.bmp_daemon_msglog_kafka_avro_schema_registry || config.bmp_dump_kafka_avro_schema_registry) { #ifndef WITH_SERDES Log(LOG_ERR, "ERROR ( %s/%s ): 'bmp_*_kafka_avro_schema_registry' require --enable-serdes. Exiting.\n", config.name, bmp_misc_db->log_str); exit_gracefully(1); #endif } if (!config.writer_id_string) { config.writer_id_string = DYNNAME_DEFAULT_WRITER_ID; } dynname_tokens_prepare(config.writer_id_string, &bmp_misc_db->writer_id_tokens, DYN_STR_WRITER_ID); select_fd = bkp_select_fd = (config.bmp_sock + 1); recalc_fds = FALSE; bmp_link_misc_structs(bmp_misc_db); if (config.bmp_daemon_tag_map) { memset(&bmp_logdump_tag, 0, sizeof(bmp_logdump_tag)); memset(&bmp_logdump_tag_table, 0, sizeof(bmp_logdump_tag_table)); memset(&req, 0, sizeof(req)); bmp_logdump_tag_map_allocated = FALSE; load_pre_tag_map(ACCT_PMBMP, config.bmp_daemon_tag_map, &bmp_logdump_tag_table, &req, &bmp_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); /* making some bindings */ bmp_logdump_tag.tag_table = (unsigned char *) &bmp_logdump_tag_table; } sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } for (;;) { select_again: if (!bmp_misc_db->is_thread) { sigprocmask(SIG_UNBLOCK, &signal_set, NULL); sigprocmask(SIG_BLOCK, &signal_set, NULL); } if (recalc_fds) { select_fd = config.bmp_sock; max_peers_idx = -1; /* .. since valid indexes include 0 */ for (peers_idx = 0; peers_idx < config.bmp_daemon_max_peers; peers_idx++) { if (select_fd < bmp_peers[peers_idx].self.fd) select_fd = bmp_peers[peers_idx].self.fd; if (bmp_peers[peers_idx].self.fd) max_peers_idx = peers_idx; } select_fd++; max_peers_idx++; bkp_select_fd = select_fd; recalc_fds = FALSE; } else select_fd = bkp_select_fd; memcpy(&read_descs, &bkp_read_descs, sizeof(bkp_read_descs)); if (bmp_misc_db->dump_backend_methods) { int delta; calc_refresh_timeout_sec(dump_refresh_deadline, bmp_misc_db->log_tstamp.tv_sec, &delta); dump_refresh_timeout.tv_sec = delta; dump_refresh_timeout.tv_usec = 0; drt_ptr = &dump_refresh_timeout; } else drt_ptr = NULL; select_num = select(select_fd, &read_descs, NULL, NULL, drt_ptr); if (select_num < 0) goto select_again; if (reload_map_bmp_thread) { if (config.bmp_daemon_allow_file) load_allow_file(config.bmp_daemon_allow_file, &allow); if (config.bmp_daemon_tag_map) { load_pre_tag_map(ACCT_PMBMP, config.bmp_daemon_tag_map, &bmp_logdump_tag_table, &req, &bmp_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); } reload_map_bmp_thread = FALSE; } if (reload_log_bmp_thread) { for (peers_idx = 0; peers_idx < config.bmp_daemon_max_peers; peers_idx++) { if (bmp_misc_db->peers_log[peers_idx].fd) { fclose(bmp_misc_db->peers_log[peers_idx].fd); bmp_misc_db->peers_log[peers_idx].fd = open_output_file(bmp_misc_db->peers_log[peers_idx].filename, "a", FALSE); setlinebuf(bmp_misc_db->peers_log[peers_idx].fd); } else break; } reload_log_bmp_thread = FALSE; } if (reload_log && !bmp_misc_db->is_thread) { reload_logs(PMBMPD_USAGE_HEADER); reload_log = FALSE; } if (bmp_misc_db->msglog_backend_methods || bmp_misc_db->dump_backend_methods) { gettimeofday(&bmp_misc_db->log_tstamp, NULL); compose_timestamp(bmp_misc_db->log_tstamp_str, SRVBUFLEN, &bmp_misc_db->log_tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); /* if dumping, let's reset log sequence at the next dump event */ if (!bmp_misc_db->dump_backend_methods) { if (bgp_peer_log_seq_has_ro_bit(&bmp_misc_db->log_seq)) bgp_peer_log_seq_init(&bmp_misc_db->log_seq); } int refreshTimePerSlot = config.bmp_dump_refresh_time / config.bmp_dump_time_slots; if (bmp_misc_db->dump_backend_methods) { while (bmp_misc_db->log_tstamp.tv_sec > dump_refresh_deadline) { bmp_misc_db->dump.tstamp.tv_sec = dump_refresh_deadline; bmp_misc_db->dump.tstamp.tv_usec = 0; compose_timestamp(bmp_misc_db->dump.tstamp_str, SRVBUFLEN, &bmp_misc_db->dump.tstamp, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bmp_misc_db->dump.period = refreshTimePerSlot; if (bgp_peer_log_seq_has_ro_bit(&bmp_misc_db->log_seq)) bgp_peer_log_seq_init(&bmp_misc_db->log_seq); bmp_handle_dump_event(max_peers_idx); dump_refresh_deadline += refreshTimePerSlot; } } #ifdef WITH_RABBITMQ if (config.bmp_daemon_msglog_amqp_routing_key) { time_t last_fail = P_broker_timers_get_last_fail(&bmp_daemon_msglog_amqp_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&bmp_daemon_msglog_amqp_host.btimers)) <= bmp_misc_db->log_tstamp.tv_sec)) { bmp_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&bmp_daemon_msglog_amqp_host); } } #endif #ifdef WITH_KAFKA if (config.bmp_daemon_msglog_kafka_topic) { time_t last_fail = P_broker_timers_get_last_fail(&bmp_daemon_msglog_kafka_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&bmp_daemon_msglog_kafka_host.btimers)) <= bmp_misc_db->log_tstamp.tv_sec)) bmp_daemon_msglog_init_kafka_host(); if (config.bmp_daemon_msglog_kafka_avro_schema_registry) { #ifdef WITH_SERDES bmp_daemon_msglog_prepare_sd_schemas(); #endif } } #endif } /* If select_num == 0 then we got out of select() due to a timeout rather than because we had a message from a peer to handle. By now we did all routine checks and can happily return to select() again. */ if (!select_num) goto select_again; if (config.pcap_savefile) { struct bmp_peer pcap_savefile_peer; sf_ret = recvfrom_savefile(&device, (void **) &bmp_packet, (struct sockaddr *) &client, NULL, &pcap_savefile_round, &recv_pptrs); if (bmp_packet && (sf_ret >= BMP_CMN_HDRLEN)) { struct bmp_common_hdr *bch = (struct bmp_common_hdr *) bmp_packet; if (bch->version == BMP_V3 || bch->version == BMP_V4) { fd = config.bmp_sock; memset(&pcap_savefile_peer, 0, sizeof(pcap_savefile_peer)); sa_to_addr((struct sockaddr *) &client, &pcap_savefile_peer.self.addr, &pcap_savefile_peer.self.tcp_port); for (peer = NULL, peers_idx = 0; peers_idx < config.bmp_daemon_max_peers; peers_idx++) { if (!sa_addr_cmp((struct sockaddr *) &client, &bmp_peers[peers_idx].self.addr) && !sa_port_cmp((struct sockaddr *) &client, bmp_peers[peers_idx].self.tcp_port)) { peer = &bmp_peers[peers_idx].self; bmpp = &bmp_peers[peers_idx]; FD_CLR(config.bmp_sock, &read_descs); break; } } } else { goto select_again; } } else { goto select_again; } } /* New connection is coming in */ if (FD_ISSET(config.bmp_sock, &read_descs)) { int peers_check_idx, peers_num; if (!config.pcap_savefile) { fd = accept(config.bmp_sock, (struct sockaddr *) &client, &clen); if (fd == ERR) goto read_data; } ipv4_mapped_to_ipv4(&client); /* If an ACL is defined, here we check against and enforce it */ if (allow.num) allowed = check_allow(&allow, (struct sockaddr *)&client); else allowed = TRUE; if (!allowed) { char disallowed_str[INET6_ADDRSTRLEN]; sa_to_str(disallowed_str, sizeof(disallowed_str), (struct sockaddr *) &client, TRUE); Log(LOG_INFO, "INFO ( %s/%s ): [%s] peer '%s' not allowed. close()\n", config.name, bmp_misc_db->log_str, config.bmp_daemon_allow_file, disallowed_str); close(fd); goto read_data; } for (peer = NULL, peers_idx = 0; peers_idx < config.bmp_daemon_max_peers; peers_idx++) { if (!bmp_peers[peers_idx].self.fd) { now = time(NULL); /* Admitted if: * batching feature is disabled or * we have room in the current batch or * we can start a new batch */ if (bgp_batch_is_admitted(&bp_batch, now)) { peer = &bmp_peers[peers_idx].self; bmpp = &bmp_peers[peers_idx]; if (bmp_peer_init(bmpp, FUNC_TYPE_BMP)) { peer = NULL; bmpp = NULL; } else recalc_fds = TRUE; log_notification_unset(&log_notifications.bgp_peers_throttling); if (bgp_batch_is_enabled(&bp_batch) && peer) { if (bgp_batch_is_expired(&bp_batch, now)) bgp_batch_reset(&bp_batch, now); if (bgp_batch_is_not_empty(&bp_batch)) bgp_batch_decrease_counter(&bp_batch); } break; } else { /* throttle */ /* We briefly accept the new connection to be able to drop it */ if (!log_notification_isset(&log_notifications.bmp_peers_throttling, now)) { Log(LOG_INFO, "INFO ( %s/%s ): throttling at BMP peer #%u\n", config.name, bmp_misc_db->log_str, peers_idx); log_notification_set(&log_notifications.bmp_peers_throttling, now, FALSE); } close(fd); goto read_data; } } } if (!peer) { /* We briefly accept the new connection to be able to drop it */ if (!log_notification_isset(&log_notifications.bmp_peers_limit, now)) { log_notification_set(&log_notifications.bmp_peers_limit, now, FALSE); Log(LOG_WARNING, "WARN ( %s/%s ): Insufficient number of BMP peers has been configured by 'bmp_daemon_max_peers' (%d).\n", config.name, bmp_misc_db->log_str, config.bmp_daemon_max_peers); } close(fd); goto read_data; } peer->fd = fd; FD_SET(peer->fd, &bkp_read_descs); sa_to_addr((struct sockaddr *) &client, &peer->addr, &peer->tcp_port); addr_to_str(peer->addr_str, &peer->addr); memcpy(&peer->id, &peer->addr, sizeof(struct host_addr)); /* XXX: some inet_ntoa()'s could be around against peer->id */ if (!config.bmp_daemon_parse_proxy_header) { if (config.bmp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bmp_logdump_tag_peer, &bmp_logdump_tag); bgp_tag_find((struct id_table *)bmp_logdump_tag.tag_table, &bmp_logdump_tag, &bmp_logdump_tag.tag, NULL); } if (bmp_misc_db->msglog_backend_methods) { bgp_peer_log_init(peer, &bmp_logdump_tag, config.bmp_daemon_msglog_output, FUNC_TYPE_BMP); } if (bmp_misc_db->dump_backend_methods) { bmp_dump_init_peer(peer); } } /* Check: multiple TCP connections per peer */ for (peers_check_idx = 0, peers_num = 0; peers_check_idx < config.bmp_daemon_max_peers; peers_check_idx++) { if (peers_idx != peers_check_idx && !memcmp(&bmp_peers[peers_check_idx].self.addr, &peer->addr, sizeof(bmp_peers[peers_check_idx].self.addr))) { if (bmp_misc_db->is_thread && !config.bgp_daemon_to_xflow_agent_map) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple connections from peer and no bgp_agent_map defined.\n", config.name, bmp_misc_db->log_str, bmp_peers[peers_check_idx].self.addr_str); } } else { if (bmp_peers[peers_check_idx].self.fd) peers_num++; } } Log(LOG_INFO, "INFO ( %s/%s ): [%s] BMP peers usage: %u/%u\n", config.name, bmp_misc_db->log_str, peer->addr_str, peers_num, config.bmp_daemon_max_peers); } read_data: if (!config.pcap_savefile) { /* We have something coming in: let's lookup which peer is that. FvD: To avoid starvation of the "later established" peers, we offset the start of the search in a round-robin style. */ for (peer = NULL, peers_idx = 0; peers_idx < max_peers_idx; peers_idx++) { int loc_idx = (peers_idx + peers_idx_rr) % max_peers_idx; if (bmp_peers[loc_idx].self.fd && FD_ISSET(bmp_peers[loc_idx].self.fd, &read_descs)) { peer = &bmp_peers[loc_idx].self; bmpp = &bmp_peers[loc_idx]; peers_idx_rr = (peers_idx_rr + 1) % max_peers_idx; break; } } } if (!peer) goto select_again; /* If first message after connect, check for proxy protocol header */ if (config.bmp_daemon_parse_proxy_header && !peer->parsed_proxy_header) { ret = parse_proxy_header(peer->fd, &peer->addr, &peer->tcp_port); if (ret < 0) { goto select_again; /* partial header */ } addr_to_str(peer->addr_str, &peer->addr); if (config.bmp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bmp_logdump_tag_peer, &bmp_logdump_tag); bgp_tag_find((struct id_table *)bmp_logdump_tag.tag_table, &bmp_logdump_tag, &bmp_logdump_tag.tag, NULL); } if (bmp_misc_db->msglog_backend_methods) { bgp_peer_log_init(peer, &bmp_logdump_tag, config.bmp_daemon_msglog_output, FUNC_TYPE_BMP); } if (bmp_misc_db->dump_backend_methods) { bmp_dump_init_peer(peer); } } peer->parsed_proxy_header = TRUE; if (!config.pcap_savefile) { if (!peer->buf.exp_len) { ret = recv(peer->fd, &peer->buf.base[peer->buf.cur_len], (BMP_CMN_HDRLEN - peer->buf.cur_len), 0); if (ret > 0) { peer->buf.cur_len += ret; if (peer->buf.cur_len == BMP_CMN_HDRLEN) { struct bmp_common_hdr *bhdr = (struct bmp_common_hdr *) peer->buf.base; if (bhdr->version != BMP_V3 && bhdr->version != BMP_V4) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: unknown BMP version: %u (1)\n", config.name, bmp_misc_db->log_str, peer->addr_str, bhdr->version); peer->msglen = 0; peer->buf.cur_len = 0; peer->buf.exp_len = 0; ret = ERR; } else { peer->buf.exp_len = ntohl(bhdr->len); /* commit */ if (peer->buf.cur_len == peer->buf.exp_len) { peer->msglen = peer->buf.exp_len; peer->buf.cur_len = 0; peer->buf.exp_len = 0; } } } else { goto select_again; } } } if (peer->buf.exp_len) { int sink_mode = FALSE; if (peer->buf.exp_len <= peer->buf.tot_len) { ret = recv(peer->fd, &peer->buf.base[peer->buf.cur_len], (peer->buf.exp_len - peer->buf.cur_len), 0); } /* sink mode */ else { ret = recv(peer->fd, peer->buf.base, MIN(peer->buf.tot_len, (peer->buf.exp_len - peer->buf.cur_len)), 0); sink_mode = TRUE; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] long BMP message received: len=%u buf=%u. Sinking.\n", config.name, bmp_misc_db->log_str, peer->addr_str, peer->buf.exp_len, BGP_BUFFER_SIZE); } if (ret > 0) { peer->buf.cur_len += ret; /* commit */ if (peer->buf.cur_len == peer->buf.exp_len) { peer->msglen = peer->buf.exp_len; peer->buf.cur_len = 0; peer->buf.exp_len = 0; } else { goto select_again; } } if (sink_mode) { goto select_again; } } if (ret <= 0) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] BMP connection reset by peer (%d).\n", config.name, bmp_misc_db->log_str, peer->addr_str, errno); FD_CLR(peer->fd, &bkp_read_descs); bmp_peer_close(bmpp, FUNC_TYPE_BMP); recalc_fds = TRUE; goto select_again; } } else { u_int32_t len = MIN(sf_ret, peer->buf.tot_len); /* recvfrom_savefile() already invoked before */ memcpy(peer->buf.base, bmp_packet, len); peer->msglen = len; } if (config.bmp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bmp_logdump_tag_peer, &bmp_logdump_tag); bgp_tag_find((struct id_table *)bmp_logdump_tag.tag_table, &bmp_logdump_tag, &bmp_logdump_tag.tag, NULL); } do_term = FALSE; bmp_process_packet(peer->buf.base, peer->msglen, bmpp, &do_term); if (do_term) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] BMP Term message received. Closing up.\n", config.name, bmp_misc_db->log_str, peer->addr_str); FD_CLR(peer->fd, &bkp_read_descs); bmp_peer_close(bmpp, FUNC_TYPE_BMP); recalc_fds = TRUE; goto select_again; } } return SUCCESS; } void bmp_prepare_thread() { bmp_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_BMP]; memset(bmp_misc_db, 0, sizeof(struct bgp_misc_structs)); bmp_misc_db->is_thread = TRUE; if (config.rpki_roas_file || config.rpki_rtr_cache) { bmp_misc_db->bnv = malloc(sizeof(struct bgp_node_vector)); memset(bmp_misc_db->bnv, 0, sizeof(struct bgp_node_vector)); } bmp_misc_db->log_str = malloc(strlen("core/BMP") + 1); strcpy(bmp_misc_db->log_str, "core/BMP"); } void bmp_prepare_daemon() { bmp_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_BMP]; memset(bmp_misc_db, 0, sizeof(struct bgp_misc_structs)); bmp_misc_db->is_thread = FALSE; if (config.rpki_roas_file || config.rpki_rtr_cache) { bmp_misc_db->bnv = malloc(sizeof(struct bgp_node_vector)); memset(bmp_misc_db->bnv, 0, sizeof(struct bgp_node_vector)); } bmp_misc_db->log_str = malloc(strlen("core") + 1); strcpy(bmp_misc_db->log_str, "core"); } void bmp_daemon_msglog_prepare_sd_schemas() { #ifdef WITH_SERDES time_t last_fail = P_broker_timers_get_last_fail(&bmp_daemon_msglog_kafka_host.sd_schema_timers); if ((last_fail + P_broker_timers_get_retry_interval(&bmp_daemon_msglog_kafka_host.sd_schema_timers)) <= bmp_misc_db->log_tstamp.tv_sec) { if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_ROUTE_MONITOR]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_ROUTE_MONITOR] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_ROUTE_MONITOR], "bmp", "msglog_rm", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_ROUTE_MONITOR]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_STATS]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_STATS] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_STATS], "bmp", "stats", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_STATS]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_UP]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_UP]= compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_UP], "bmp", "peer_up", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_UP]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_DOWN]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_DOWN] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_PEER_DOWN], "bmp", "peer_down", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_PEER_DOWN]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_INIT]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_INIT] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_INIT], "bmp", "init", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_INIT]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TERM]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TERM] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_TERM], "bmp", "term", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TERM]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TMP_RPAT]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TMP_RPAT] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_MSG_TMP_RPAT], "bmp", "rpat", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_MSG_TMP_RPAT]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGINIT]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGINIT] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGINIT], "bmp", "loginit", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGINIT]) goto exit_lane; } if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGCLOSE]) { bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGCLOSE] = compose_avro_schema_registry_name_2(config.bmp_daemon_msglog_kafka_topic, FALSE, bmp_misc_db->msglog_avro_schema[BMP_LOG_TYPE_LOGCLOSE], "bmp", "logclose", config.bmp_daemon_msglog_kafka_avro_schema_registry); if (!bmp_daemon_msglog_kafka_host.sd_schema[BMP_LOG_TYPE_LOGCLOSE]) goto exit_lane; } } return; exit_lane: P_broker_timers_set_last_fail(&bmp_daemon_msglog_kafka_host.sd_schema_timers, time(NULL)); #endif } pmacct-1.7.8/src/bmp/bmp_lookup.h0000644000175000017500000000242314354105275015700 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_LOOKUP_H #define BMP_LOOKUP_H /* includes */ /* defines */ /* prototypes */ extern void bmp_srcdst_lookup(struct packet_ptrs *); extern struct bgp_peer *bgp_lookup_find_bmp_peer(struct sockaddr *, struct xflow_status_entry *, u_int16_t, int); extern u_int32_t bmp_route_info_modulo_pathid(struct bgp_peer *, path_id_t *, int); extern int bgp_lookup_node_match_cmp_bmp(struct bgp_info *, struct node_match_cmp_term2 *); #endif //BMP_LOOKUP_H pmacct-1.7.8/src/bmp/bmp_util.c0000644000175000017500000004646214354105275015352 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #ifdef WITH_AVRO #include "plugin_cmn_avro.h" #endif char *bmp_get_and_check_length(char **bmp_packet_ptr, u_int32_t *pkt_size, u_int32_t len) { char *current_ptr = NULL; if (bmp_packet_ptr && (*bmp_packet_ptr) && pkt_size) { if ((*pkt_size) >= len) { current_ptr = (*bmp_packet_ptr); (*pkt_size) -= len; (*bmp_packet_ptr) += len; } } return current_ptr; } int bmp_jump_offset(char **bmp_packet_ptr, u_int32_t *len, u_int32_t offset) { int ret = ERR; if (bmp_packet_ptr && (*bmp_packet_ptr) && len) { if (offset <= (*len)) { (*bmp_packet_ptr) += offset; (*len) -= offset; ret = offset; } } return ret; } void bgp_peer_log_msg_extras_bmp(struct bgp_peer *peer, int etype, int log_type, int output, void *void_obj) { struct bgp_misc_structs *bms; struct bmp_peer *bmpp; if (!peer || !void_obj) return; bms = bgp_select_misc_db(peer->type); bmpp = peer->bmp_se; if (!bms || !bmpp) return; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = void_obj; if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "timestamp_arrival", json_string(decode_tstamp_arrival(bms->log_tstamp_str))); } addr_to_str(ip_address, &bmpp->self.addr); json_object_set_new_nocheck(obj, "bmp_router", json_string(ip_address)); json_object_set_new_nocheck(obj, "bmp_router_port", json_integer((json_int_t)bmpp->self.tcp_port)); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, "peer_ip", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_tcp_port", json_integer((json_int_t)peer->tcp_port)); if (log_type == BGP_LOG_TYPE_DELETE) { json_object_set_new_nocheck(obj, "bmp_msg_type", json_string("internal")); } else { json_object_set_new_nocheck(obj, "bmp_msg_type", json_string("route_monitor")); } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO char ip_address[INET6_ADDRSTRLEN]; avro_value_t *obj = (avro_value_t *) void_obj, p_avro_field, p_avro_branch; if (etype == BGP_LOGDUMP_ET_LOG) { pm_avro_check(avro_value_get_by_name(obj, "timestamp_arrival", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, decode_tstamp_arrival(bms->log_tstamp_str))); } else if (etype == BGP_LOGDUMP_ET_DUMP) { pm_avro_check(avro_value_get_by_name(obj, "timestamp_arrival", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } addr_to_str(ip_address, &bmpp->self.addr); pm_avro_check(avro_value_get_by_name(obj, "bmp_router", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); pm_avro_check(avro_value_get_by_name(obj, "bmp_router_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmpp->self.tcp_port)); addr_to_str(ip_address, &peer->addr); pm_avro_check(avro_value_get_by_name(obj, "peer_ip", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); pm_avro_check(avro_value_get_by_name(obj, "peer_tcp_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); if (log_type == BGP_LOG_TYPE_DELETE) { pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, "internal")); } else { pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, "route_monitor")); } #endif } } void bmp_link_misc_structs(struct bgp_misc_structs *bms) { #if defined WITH_RABBITMQ bms->msglog_amqp_host = &bmp_daemon_msglog_amqp_host; #endif #if defined WITH_KAFKA bms->msglog_kafka_host = &bmp_daemon_msglog_kafka_host; #endif bms->max_peers = config.bmp_daemon_max_peers; bms->peers = bmp_peers; bms->peers_cache = NULL; bms->peers_port_cache = NULL; bms->peers_limit_log = &log_notifications.bmp_peers_limit; bms->xconnects = NULL; bms->dump_file = config.bmp_dump_file; bms->dump_amqp_routing_key = config.bmp_dump_amqp_routing_key; bms->dump_amqp_routing_key_rr = config.bmp_dump_amqp_routing_key_rr; bms->dump_kafka_topic = config.bmp_dump_kafka_topic; bms->dump_kafka_topic_rr = config.bmp_dump_kafka_topic_rr; bms->dump_kafka_partition_key = config.bmp_dump_kafka_partition_key; bms->dump_kafka_avro_schema_registry = config.bmp_dump_kafka_avro_schema_registry; bms->msglog_file = config.bmp_daemon_msglog_file; bms->msglog_output = config.bmp_daemon_msglog_output; bms->msglog_amqp_routing_key = config.bmp_daemon_msglog_amqp_routing_key; bms->msglog_amqp_routing_key_rr = config.bmp_daemon_msglog_amqp_routing_key_rr; bms->msglog_kafka_topic = config.bmp_daemon_msglog_kafka_topic; bms->msglog_kafka_topic_rr = config.bmp_daemon_msglog_kafka_topic_rr; bms->msglog_kafka_partition_key = config.bmp_daemon_msglog_kafka_partition_key; bms->msglog_kafka_avro_schema_registry = config.bmp_daemon_msglog_kafka_avro_schema_registry; bms->peer_str = malloc(strlen("bmp_router") + 1); strcpy(bms->peer_str, "bmp_router"); bms->peer_port_str = malloc(strlen("bmp_router_port") + 1); strcpy(bms->peer_port_str, "bmp_router_port"); bms->bgp_peer_log_msg_extras = bgp_peer_log_msg_extras_bmp; bms->bgp_peer_logdump_initclose_extras = NULL; bms->bgp_peer_logdump_extra_data = bgp_extra_data_print_bmp; bms->bgp_extra_data_process = bgp_extra_data_process_bmp; bms->bgp_extra_data_cmp = bgp_extra_data_cmp_bmp; bms->bgp_extra_data_free = bgp_extra_data_free_bmp; bms->table_peer_buckets = config.bmp_table_peer_buckets; bms->table_per_peer_buckets = config.bmp_table_per_peer_buckets; bms->table_attr_hash_buckets = config.bmp_table_attr_hash_buckets; bms->table_per_peer_hash = config.bmp_table_per_peer_hash; bms->route_info_modulo = bmp_route_info_modulo; bms->bgp_lookup_find_peer = bgp_lookup_find_bmp_peer; bms->bgp_lookup_node_match_cmp = bgp_lookup_node_match_cmp_bmp; bms->bgp_msg_open_router_id_check = NULL; if (!bms->is_thread && !bms->dump_backend_methods) bms->skip_rib = TRUE; bms->tag = &bmp_logdump_tag; bms->tag_map = config.bmp_daemon_tag_map; bms->tag_peer = &bmp_logdump_tag_peer; bms->bgp_table_info_delete_tag_find = bgp_table_info_delete_tag_find_bmp; } struct bgp_peer *bmp_sync_loc_rem_peers(struct bgp_peer *bgp_peer_loc, struct bgp_peer *bgp_peer_rem) { if (!bgp_peer_loc || !bgp_peer_rem) return NULL; if (!bgp_peer_loc->cap_4as || !bgp_peer_rem->cap_4as) bgp_peer_rem->cap_4as = FALSE; /* XXX: since BGP OPENs are fabricated, we assume that if remote peer is marked as able to send ADD-PATH capability, the local pper will be able to receive it just fine */ /* Checking peers do agree on add-path capability; above comment left for historical reference in case checks below have to be further fine tuned */ { afi_t afi, afi_max; safi_t safi, safi_max; if (bgp_peer_loc->cap_add_paths.afi_max > bgp_peer_rem->cap_add_paths.afi_max) { afi_max = bgp_peer_loc->cap_add_paths.afi_max; } else { afi_max = bgp_peer_rem->cap_add_paths.afi_max; } if (bgp_peer_loc->cap_add_paths.safi_max > bgp_peer_rem->cap_add_paths.safi_max) { safi_max = bgp_peer_loc->cap_add_paths.safi_max; } else { safi_max = bgp_peer_rem->cap_add_paths.safi_max; } for (afi = 0; afi <= afi_max; afi++) { for (safi = 0; safi <= safi_max; safi++) { if ((bgp_peer_loc->cap_add_paths.cap[afi][safi] && !bgp_peer_rem->cap_add_paths.cap[afi][safi]) || (!bgp_peer_loc->cap_add_paths.cap[afi][safi] && bgp_peer_rem->cap_add_paths.cap[afi][safi])) { bgp_peer_loc->cap_add_paths.cap[afi][safi] = FALSE; bgp_peer_rem->cap_add_paths.cap[afi][safi] = FALSE; } } } } bgp_peer_rem->type = FUNC_TYPE_BMP; memcpy(&bgp_peer_rem->id, &bgp_peer_rem->addr, sizeof(struct host_addr)); return bgp_peer_rem; } int bmp_peer_init(struct bmp_peer *bmpp, int type) { int ret; if (!bmpp) return ERR; ret = bgp_peer_init(&bmpp->self, type); log_notification_init(&bmpp->missing_peer_up); return ret; } void bmp_peer_close(struct bmp_peer *bmpp, int type) { struct bgp_misc_structs *bms; struct bgp_peer *peer; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; pm_twalk(bmpp->bgp_peers_v4, bgp_peers_bintree_walk_delete, NULL); pm_twalk(bmpp->bgp_peers_v6, bgp_peers_bintree_walk_delete, NULL); pm_tdestroy(&bmpp->bgp_peers_v4, bgp_peer_free); pm_tdestroy(&bmpp->bgp_peers_v6, bgp_peer_free); if (bms->dump_file || bms->dump_amqp_routing_key || bms->dump_kafka_topic) { bmp_dump_close_peer(peer); } bgp_peer_close(peer, type, FALSE, FALSE, FALSE, FALSE, NULL); } void bgp_msg_data_set_data_bmp(struct bmp_chars *bmed_bmp, struct bmp_data *bdata) { memcpy(bmed_bmp, &bdata->chars, sizeof(struct bmp_chars)); } int bgp_extra_data_cmp_bmp(struct bgp_msg_extra_data *a, struct bgp_msg_extra_data *b) { if (a->id == b->id && a->len == b->len && a->id == BGP_MSG_EXTRA_DATA_BMP) { struct bmp_chars *bca = a->data; struct bmp_chars *bcb = b->data; if (bca->peer_type == bcb->peer_type && bca->is_post == bcb->is_post && bca->is_filtered == bcb->is_filtered && bca->is_out == bcb->is_out && bca->is_loc == bcb->is_loc && !memcmp(&bca->rd, &bcb->rd, sizeof(bca->rd))) { return FALSE; } else { return TRUE; } } else { return ERR; } } int bgp_extra_data_process_bmp(struct bgp_msg_extra_data *bmed, struct bgp_info *ri, int idx, int nlri_type) { struct bmp_chars *bmed_bmp_src = NULL, *bmed_bmp_dst = NULL; int ret = BGP_MSG_EXTRA_DATA_NONE; if (bmed && ri && bmed->id == BGP_MSG_EXTRA_DATA_BMP) { if (ri->bmed.data && (ri->bmed.len != bmed->len)) { free(ri->bmed.data); ri->bmed.data = NULL; } if (!ri->bmed.data) ri->bmed.data = malloc(bmed->len); if (ri->bmed.data) { memcpy(ri->bmed.data, bmed->data, bmed->len); ri->bmed.len = bmed->len; ri->bmed.id = bmed->id; bmed_bmp_src = (struct bmp_chars *) bmed->data; bmed_bmp_dst = (struct bmp_chars *) ri->bmed.data; if (bmed_bmp_src->tlvs) { bmed_bmp_dst->tlvs = bmp_tlv_list_copy(bmed_bmp_src->tlvs); /* post process copied TLV list */ { struct pm_listnode *node = NULL, *next_node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS(bmed_bmp_dst->tlvs, node, next_node, tlv)) { if (tlv->type == BMP_ROUTE_MONITOR_INFO_MARKING) { struct bmp_rm_pm_tlv *tlv_pm = tlv->val; if (idx != ntohs(tlv_pm->path_index)) { pm_list_delete_node(bmed_bmp_dst->tlvs, node); } } } } } ret = BGP_MSG_EXTRA_DATA_BMP; } } return ret; } void bgp_extra_data_free_bmp(struct bgp_msg_extra_data *bmed) { struct bmp_chars *bmed_bmp; if (bmed && bmed->id == BGP_MSG_EXTRA_DATA_BMP) { if (bmed->data) { bmed_bmp = (struct bmp_chars *) bmed->data; if (bmed_bmp->tlvs) { bmp_tlv_list_destroy(bmed_bmp->tlvs); } free(bmed->data); } memset(bmed, 0, sizeof(struct bgp_msg_extra_data)); } } void bgp_extra_data_print_bmp(struct bgp_msg_extra_data *bmed, int output, void *void_obj) { struct bmp_chars *bmed_bmp; if (!bmed || !void_obj || bmed->id != BGP_MSG_EXTRA_DATA_BMP) return; bmed_bmp = bmed->data; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = void_obj; if (!bmed_bmp->is_loc && !bmed_bmp->is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bmed_bmp->is_post)); json_object_set_new_nocheck(obj, "is_in", json_integer(1)); } else if (bmed_bmp->is_loc) { json_object_set_new_nocheck(obj, "is_filtered", json_integer((json_int_t)bmed_bmp->is_filtered)); json_object_set_new_nocheck(obj, "is_loc", json_integer((json_int_t)bmed_bmp->is_loc)); } else if (bmed_bmp->is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bmed_bmp->is_post)); json_object_set_new_nocheck(obj, "is_out", json_integer((json_int_t)bmed_bmp->is_out)); } if (!is_empty_256b(&bmed_bmp->rd, sizeof(bmed_bmp->rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bmed_bmp->rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(bmed_bmp->rd.type))); } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_t *obj = (avro_value_t *) void_obj, p_avro_field, p_avro_branch; if (!bmed_bmp->is_loc && !bmed_bmp->is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, 1)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmed_bmp->is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bmed_bmp->is_loc) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmed_bmp->is_filtered)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmed_bmp->is_loc)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bmed_bmp->is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmed_bmp->is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bmed_bmp->is_out)); } if (!is_empty_256b(&bmed_bmp->rd, sizeof(bmed_bmp->rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bmed_bmp->rd); pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, rd_str)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_rd_origin_print(bmed_bmp->rd.type))); } else { pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } #endif } if (bmed_bmp->tlvs) { bmp_log_msg_route_monitor_tlv(bmed_bmp->tlvs, output, void_obj); } } char *bmp_term_reason_print(u_int16_t in) { char *out = NULL; int value_len; if (in <= BMP_TERM_REASON_MAX) { value_len = strlen(bmp_term_reason_types[in]); out = malloc(value_len + 1 /* null */); sprintf(out, "%s", bmp_term_reason_types[in]); } else { out = malloc(5 /* value len */ + 1 /* null */); sprintf(out, "%u", in); } return out; } void encode_tstamp_arrival(char *buf, int buflen, struct timeval *tv, int usec) { char *tstamp_arrival; int tstamp_len; tstamp_len = strlen(buf); tstamp_arrival = (buf + tstamp_len); (*tstamp_arrival) = '\0'; tstamp_arrival++; compose_timestamp(tstamp_arrival, (buflen - tstamp_len), tv, usec, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); } char *decode_tstamp_arrival(char *buf) { int tstamp_len; tstamp_len = strlen(buf); return &buf[tstamp_len + 1]; } void bgp_table_info_delete_tag_find_bmp(struct bgp_peer *peer) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); struct bmp_peer *bmpp = NULL; struct bgp_peer *bgpp = NULL; if (peer && peer->bmp_se) bmpp = peer->bmp_se; if (bmpp) bgpp = &bmpp->self; bgp_tag_init_find(bgpp ? bgpp : peer, (struct sockaddr *) bms->tag_peer, bms->tag); bgp_tag_find((struct id_table *)bms->tag->tag_table, bms->tag, &bms->tag->tag, NULL); } pmacct-1.7.8/src/bmp/bmp_rpat.c0000644000175000017500000004352414354105275015337 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" #ifdef WITH_AVRO #include "plugin_cmn_avro.h" #endif /* functions */ void bmp_process_msg_rpat(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_rpat_common_hdr *brch; struct bmp_rpat_event_hdr *breh; struct bmp_log_rpat blrpat; int idx, tecount, telen; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); memset(&blrpat, 0, sizeof(blrpat)); if (!(brch = (struct bmp_rpat_common_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_rpat_common_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [rpat] packet discarded: failed bmp_get_and_check_length() BMP rpat common hdr\n", config.name, bms->log_str, peer->addr_str); return; } gettimeofday(&bdata.tstamp_arrival, NULL); bmp_rpat_common_hdr_get_v_flag(brch, &bdata.family); bmp_rpat_common_hdr_get_bgp_id(brch, &bdata.bgp_id); bmp_rpat_common_hdr_get_rd(brch, &bdata.chars.rd); bmp_rpat_common_hdr_get_prefix(brch, &blrpat.prefix, &bdata.family); bmp_rpat_common_hdr_get_prefix_len(brch, &blrpat.prefix_len); tecount = brch->events_count; telen = ntohs(brch->events_length); /* Events parsing */ for (idx = 0; (idx < tecount) && (telen > 0); idx++) { u_int32_t orig_loc_len, rmn_loc_len; int ret, elen; /* TLV vars */ struct bmp_tlv_hdr *bth; u_int16_t bmp_tlv_type, bmp_tlv_len; char *bmp_tlv_value; struct pm_list *tlvs = NULL; tlvs = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); if (!tlvs) return; if (!(breh = (struct bmp_rpat_event_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_rpat_event_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [rpat] packet discarded: failed bmp_get_and_check_length() BMP rpat event hdr\n", config.name, bms->log_str, peer->addr_str); bmp_tlv_list_destroy(tlvs); return; } elen = rmn_loc_len = ntohs(breh->len); orig_loc_len = rmn_loc_len = (rmn_loc_len - sizeof(struct bmp_rpat_event_hdr)); bmp_rpat_event_hdr_get_index(breh, &blrpat.event_idx); bmp_rpat_event_hdr_get_tstamp(breh, &bdata.tstamp); bmp_rpat_event_hdr_get_path_id(breh, &blrpat.path_id); bmp_rpat_event_hdr_get_afi_safi(breh, &blrpat.afi, &blrpat.safi); /* event TLVs parsing */ while (rmn_loc_len) { if (!(bth = (struct bmp_tlv_hdr *) bmp_get_and_check_length(bmp_packet, &rmn_loc_len, sizeof(struct bmp_tlv_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [rpat] packet discarded: failed bmp_get_and_check_length() BMP TLV hdr\n", config.name, bms->log_str, peer->addr_str); (*len) -= (orig_loc_len - rmn_loc_len); bmp_tlv_list_destroy(tlvs); return; } bmp_tlv_hdr_get_type(bth, &bmp_tlv_type); bmp_tlv_hdr_get_len(bth, &bmp_tlv_len); if (!(bmp_tlv_value = bmp_get_and_check_length(bmp_packet, &rmn_loc_len, bmp_tlv_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [rpat] packet discarded: failed bmp_get_and_check_length() BMP TLV info\n", config.name, bms->log_str, peer->addr_str); (*len) -= (orig_loc_len - rmn_loc_len); bmp_tlv_list_destroy(tlvs); return; } ret = bmp_tlv_list_add(tlvs, 0, bmp_tlv_type, bmp_tlv_len, bmp_tlv_value); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] [rpat] bmp_tlv_list_add() failed.\n", config.name, bms->log_str, peer->addr_str); exit_gracefully(1); } } if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, tlvs, &bmp_logdump_tag, &blrpat, bgp_peer_log_seq_get(&bms->log_seq), event_type, config.bmp_daemon_msglog_output, BMP_LOG_TYPE_RPAT); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, tlvs, &blrpat, BMP_LOG_TYPE_RPAT); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); if (!pm_listcount(tlvs) || !bms->dump_backend_methods) bmp_tlv_list_destroy(tlvs); (*len) -= orig_loc_len; telen -= elen; } } void bmp_rpat_common_hdr_get_v_flag(struct bmp_rpat_common_hdr *brch, u_int8_t *family) { u_int8_t version; if (brch && family) { version = (brch->flags & BMP_PEER_FLAGS_ARI_V); (*family) = FALSE; if (version == 0) (*family) = AF_INET; else (*family) = AF_INET6; } } void bmp_rpat_common_hdr_get_bgp_id(struct bmp_rpat_common_hdr *brch, struct host_addr *a) { if (brch && a) { a->family = AF_INET; a->address.ipv4.s_addr = brch->bgp_id; } } void bmp_rpat_common_hdr_get_rd(struct bmp_rpat_common_hdr *brch, rd_t *rd) { if (brch && rd) { memcpy(rd, brch->rd, RD_LEN); bgp_rd_ntoh(rd); if (!is_empty_256b(rd, RD_LEN)) { bgp_rd_origin_set(rd, RD_ORIGIN_BMP); } } } void bmp_rpat_common_hdr_get_prefix(struct bmp_rpat_common_hdr *brch, struct host_addr *a, u_int8_t *family) { if (brch && a) { if ((*family) == AF_INET) a->address.ipv4.s_addr = brch->prefix[3]; else if ((*family) == AF_INET6) memcpy(&a->address.ipv6, &brch->prefix, 16); else { memset(a, 0, sizeof(struct host_addr)); if (!brch->prefix[0] && !brch->prefix[1] && !brch->prefix[2] && !brch->prefix[3]) { (*family) = AF_INET; /* we just set this up to something non-zero */ } } a->family = (*family); } } void bmp_rpat_common_hdr_get_prefix_len(struct bmp_rpat_common_hdr *brch, u_int8_t *plen) { if (brch && plen) (*plen) = brch->prefix_len; } void bmp_rpat_event_hdr_get_index(struct bmp_rpat_event_hdr *breh, u_int8_t *idx) { if (breh && idx) (*idx) = breh->idx; } void bmp_rpat_event_hdr_get_tstamp(struct bmp_rpat_event_hdr *breh, struct timeval *tv) { u_int32_t sec, usec; if (breh && tv) { if (breh->tstamp_sec) { sec = ntohl(breh->tstamp_sec); usec = ntohl(breh->tstamp_usec); tv->tv_sec = sec; tv->tv_usec = usec; } } } void bmp_rpat_event_hdr_get_path_id(struct bmp_rpat_event_hdr *breh, u_int32_t *path_id) { if (breh && path_id) (*path_id) = ntohl(breh->path_id); } void bmp_rpat_event_hdr_get_afi_safi(struct bmp_rpat_event_hdr *breh, afi_t *afi, safi_t *safi) { if (breh) { if (afi && safi) { (*afi) = ntohs(breh->afi); (*safi) = breh->safi; } } } void bmp_rpat_policy_tlv_get_m_flag(struct bmp_rpat_policy_tlv_hdr *brpth, u_int8_t *is_match) { if (brpth && is_match) { if (brpth->flag & BMP_RPAT_POLICY_FLAG_M) (*is_match) = TRUE; else (*is_match) = FALSE; } } void bmp_rpat_policy_tlv_get_p_flag(struct bmp_rpat_policy_tlv_hdr *brpth, u_int8_t *is_permit) { if (brpth && is_permit) { if (brpth->flag & BMP_RPAT_POLICY_FLAG_P) (*is_permit) = TRUE; else (*is_permit) = FALSE; } } void bmp_rpat_policy_tlv_get_d_flag(struct bmp_rpat_policy_tlv_hdr *brpth, u_int8_t *is_diff) { if (brpth && is_diff) { if (brpth->flag & BMP_RPAT_POLICY_FLAG_D) (*is_diff) = TRUE; else (*is_diff) = FALSE; } } void bmp_rpat_policy_tlv_np_get_c_flag(u_int8_t *np_flags, u_int8_t *is_chained) { if (np_flags && is_chained) { if ((*np_flags) & BMP_RPAT_POLICY_NP_FLAG_C) (*is_chained) = TRUE; else (*is_chained) = FALSE; } } void bmp_rpat_policy_tlv_np_get_r_flag(u_int8_t *np_flags, u_int8_t *is_recursive) { if (np_flags && is_recursive) { if ((*np_flags) & BMP_RPAT_POLICY_NP_FLAG_R) (*is_recursive) = TRUE; else (*is_recursive) = FALSE; } } void bmp_rpat_policy_tlv_get_bgp_id(struct bmp_rpat_policy_tlv_hdr *brpth, struct host_addr *a) { if (brpth && a) { a->family = AF_INET; a->address.ipv4.s_addr = brpth->peer_bgp_id; } } void bmp_rpat_policy_tlv_get_peer_ip(struct bmp_rpat_policy_tlv_hdr *brpth, struct host_addr *a, u_int8_t *family) { if (brpth && a) { if ((*family) == AF_INET) a->address.ipv4.s_addr = brpth->peer_ip[3]; else if ((*family) == AF_INET6) memcpy(&a->address.ipv6, &brpth->peer_ip, 16); else { memset(a, 0, sizeof(struct host_addr)); if (!brpth->peer_ip[0] && !brpth->peer_ip[1] && !brpth->peer_ip[2] && !brpth->peer_ip[3]) { (*family) = AF_INET; /* we just set this up to something non-zero */ } } a->family = (*family); } } int bmp_log_msg_rpat(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, struct bmp_log_rpat *blrpat, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !bdata || !blrpat || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char bmp_msg_type[] = "rpat"; char ip_address[INET6_ADDRSTRLEN]; json_t *obj = (json_t *) vobj; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(bdata->chars.rd.type))); } addr_to_str(ip_address, &blrpat->prefix); json_object_set_new_nocheck(obj, "prefix", json_string(ip_address)); json_object_set_new_nocheck(obj, "prefix_len", json_integer((json_int_t)blrpat->prefix_len)); json_object_set_new_nocheck(obj, "bgp_id", json_string(inet_ntoa(bdata->bgp_id.address.ipv4))); if (blrpat->path_id) { json_object_set_new_nocheck(obj, "path_id", json_integer((json_int_t)blrpat->path_id)); } json_object_set_new_nocheck(obj, "afi", json_integer((json_int_t)blrpat->afi)); json_object_set_new_nocheck(obj, "safi", json_integer((json_int_t)blrpat->safi)); if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->type) { case BMP_RPAT_INFO_VRF: (*bmp_rpat_info_types[tlv->type].logdump_func)(peer, bdata, tlv, blrpat, event_type, output, vobj); break; case BMP_RPAT_INFO_POLICY: (*bmp_rpat_info_types[tlv->type].logdump_func)(peer, bdata, tlv, blrpat, event_type, output, vobj); break; default: type = bmp_tlv_type_print(tlv, "bmp_rpat_info", bmp_rpat_info_types, BMP_RPAT_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_rpat_info_types, BMP_RPAT_INFO_MAX); break; } if (type) { if (value) { /* Allow for multiple String TLVs */ if (tlv->type == BMP_RPAT_INFO_STRING) { json_t *string_tlv_array = NULL; string_tlv_array = json_object_get(obj, bmp_rpat_info_types[tlv->type].name); if (!string_tlv_array || !json_is_array(string_tlv_array)) { string_tlv_array = json_array(); json_array_append_new(string_tlv_array, json_string(value)); json_object_set_new_nocheck(obj, type, string_tlv_array); } else { json_array_append_new(string_tlv_array, json_string(value)); } } else { json_object_set_new_nocheck(obj, type, json_string(value)); } free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_t *obj = (avro_value_t *) vobj, p_avro_field; char bmp_msg_type[] = "rpat"; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); // XXX: to be worked out later #endif } return ret; } int bmp_log_msg_rpat_vrf(struct bgp_peer *peer, struct bmp_data *bdata, void *vtlv, void *bl, char *event_type, int output, void *vobj) { struct bmp_log_rpat *blrpat = bl; struct bmp_log_tlv *tlv = vtlv; int ret = 0; if (!peer || !bdata || !blrpat || !tlv || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; struct bmp_rpat_vrf_tlv_hdr *vrf_tlv = NULL; char *vrf_name = NULL, *str_ptr = NULL; int vrf_name_len = 0; vrf_tlv = (struct bmp_rpat_vrf_tlv_hdr *) tlv->val; str_ptr = (char *)(tlv->val + 4); vrf_name_len = (tlv->len - 4); json_object_set_new_nocheck(obj, "vrf_id", json_integer((json_int_t)ntohl(vrf_tlv->id))); if (vrf_name_len) { vrf_name = null_terminate(str_ptr, vrf_name_len); json_object_set_new_nocheck(obj, "vrf_name", json_string(vrf_name)); free(vrf_name); } else { json_object_set_new_nocheck(obj, "vrf_name", json_null()); } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO // XXX: to be worked out later #endif } return ret; } int bmp_log_msg_rpat_policy(struct bgp_peer *peer, struct bmp_data *bdata, void *vtlv, void *bl, char *event_type, int output, void *vobj) { struct bmp_log_rpat *blrpat = bl; struct bmp_log_tlv *tlv = vtlv; int ret = 0; if (!peer || !bdata || !blrpat || !tlv || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; struct bmp_rpat_policy_tlv_hdr *policy_tlv = NULL; char ip_address[INET6_ADDRSTRLEN]; struct host_addr ha; u_int8_t flag = 0, idx = 0; policy_tlv = (struct bmp_rpat_policy_tlv_hdr *) tlv->val; bmp_rpat_policy_tlv_get_m_flag(policy_tlv, &flag); json_object_set_new_nocheck(obj, "policy_is_match", json_integer((json_int_t)flag)); bmp_rpat_policy_tlv_get_p_flag(policy_tlv, &flag); json_object_set_new_nocheck(obj, "policy_is_permit", json_integer((json_int_t)flag)); bmp_rpat_policy_tlv_get_d_flag(policy_tlv, &flag); json_object_set_new_nocheck(obj, "policy_is_diff", json_integer((json_int_t)flag)); if (policy_tlv->class <= BMP_RPAT_POLICY_CLASS_MAX) { json_object_set_new_nocheck(obj, "policy_class", json_string(bmp_rpat_class_types[policy_tlv->class])); } else { json_object_set_new_nocheck(obj, "policy_class", json_string("Unknown")); } bmp_rpat_policy_tlv_get_bgp_id(policy_tlv, &ha); json_object_set_new_nocheck(obj, "peer_bgp_id", json_string(inet_ntoa(ha.address.ipv4))); bmp_rpat_policy_tlv_get_peer_ip(policy_tlv, &ha, &bdata->family); addr_to_str(ip_address, &ha); json_object_set_new_nocheck(obj, "peer_ip", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_asn", json_integer((json_int_t)ntohl(policy_tlv->peer_asn))); if (policy_tlv->count) { json_t *policy_name_array = json_array(); json_t *policy_id_array = json_array(); json_t *policy_nf_array = json_array(); void *policy_ptr = tlv->val + sizeof(struct bmp_rpat_policy_tlv_hdr); json_object_set_new_nocheck(obj, "policy_name", policy_name_array); json_object_set_new_nocheck(obj, "policy_id", policy_id_array); json_object_set_new_nocheck(obj, "policy_nf", policy_nf_array); for (idx = 0; idx < policy_tlv->count; idx++) { struct bmp_rpat_policy_hdr *brph = policy_ptr; char *policy_id = NULL, *policy_name = NULL, *str_ptr = NULL; int is_last = ((idx + 1) < policy_tlv->count) ? FALSE : TRUE; int is_first = (idx == 0) ? TRUE : FALSE; brph->name_len = ntohs(brph->name_len); brph->id_len = ntohs(brph->id_len); str_ptr = (policy_ptr + 4 /* lenghts */); if (brph->name_len) { policy_name = null_terminate((char *) str_ptr, brph->name_len); json_array_append_new(policy_name_array, json_string(policy_name)); free(policy_name); } else { json_array_append_new(policy_name_array, json_null()); } str_ptr = (policy_ptr + 4 /* lengths */ + brph->name_len); if (brph->id_len) { policy_id = null_terminate((char *) str_ptr, brph->id_len); json_array_append_new(policy_id_array, json_string(policy_id)); free(policy_id); } else { json_array_append_new(policy_id_array, json_null()); } if (is_first) { json_array_append_new(policy_nf_array, json_null()); } if (!is_last) { u_int8_t *np_flags = (policy_ptr + 4 /* lengths */ + brph->name_len + brph->id_len); bmp_rpat_policy_tlv_np_get_c_flag(np_flags, &flag); json_object_set_new_nocheck(obj, "policy_nf_is_chained", json_integer((json_int_t)flag)); bmp_rpat_policy_tlv_np_get_r_flag(np_flags, &flag); json_object_set_new_nocheck(obj, "policy_nf_is_recursive", json_integer((json_int_t)flag)); policy_ptr = (policy_ptr + 4 /* lengths */ + brph->name_len + brph->id_len + 1 /* next policy flags */); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO // XXX: to be worked out later #endif } return ret; } #ifdef WITH_AVRO avro_schema_t p_avro_schema_build_bmp_rpat(char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); /* XXX: incomplete, more work needed */ avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } #endif pmacct-1.7.8/src/bmp/bmp_logdump.c0000644000175000017500000026002414354105275016034 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" #include "thread_pool.h" #include "util.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #ifdef WITH_AVRO #include "plugin_cmn_avro.h" #endif int bmp_log_msg(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, bgp_tag_t *tag, void *log_data, u_int64_t log_seq, char *event_type, int output, int log_type) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BMP); int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = BGP_LOGDUMP_ET_NONE; if (!bms || !peer || !peer->log || !bdata || !event_type) return ERR; if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP; else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG; if ((config.bmp_daemon_msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_RABBITMQ p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif } if ((config.bmp_daemon_msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_KAFKA p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); if (config.bmp_daemon_msglog_kafka_partition_key && etype == BGP_LOGDUMP_ET_LOG) { p_kafka_set_key(peer->log->kafka_host, peer->log->partition_key, strlen(peer->log->partition_key)); } #endif } if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = json_object(); char tstamp_str[SRVBUFLEN]; json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)log_seq)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp", json_string(tstamp_str)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_arrival", json_string(tstamp_str)); } else if (etype == BGP_LOGDUMP_ET_DUMP) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_event", json_string(tstamp_str)); } json_object_set_new_nocheck(obj, "bmp_router", json_string(peer->addr_str)); json_object_set_new_nocheck(obj, "bmp_router_port", json_integer((json_int_t)peer->tcp_port)); if (config.bmp_daemon_tag_map && tag) { bgp_tag_print_json(obj, tag); } switch (log_type) { case BMP_LOG_TYPE_STATS: ret = bmp_log_msg_stats(peer, bdata, tlvs, (struct bmp_log_stats *) log_data, event_type, output, obj); break; case BMP_LOG_TYPE_INIT: ret = bmp_log_msg_init(peer, bdata, tlvs, event_type, output, obj); break; case BMP_LOG_TYPE_TERM: ret = bmp_log_msg_term(peer, bdata, tlvs, event_type, output, obj); break; case BMP_LOG_TYPE_PEER_UP: ret = bmp_log_msg_peer_up(peer, bdata, tlvs, (struct bmp_log_peer_up *) log_data, event_type, output, obj); break; case BMP_LOG_TYPE_PEER_DOWN: ret = bmp_log_msg_peer_down(peer, bdata, tlvs, (struct bmp_log_peer_down *) log_data, event_type, output, obj); break; case BMP_LOG_TYPE_RPAT: ret = bmp_log_msg_rpat(peer, bdata, tlvs, (struct bmp_log_rpat *) log_data, event_type, output, obj); break; default: Log(LOG_INFO, "INFO ( %s/%s ): [%s] bmp_log_msg(): unknown message type (%u)\n", config.name, bms->log_str, peer->addr_str, log_type); break; } if ((config.bmp_daemon_msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_file && etype == BGP_LOGDUMP_ET_DUMP)) write_and_free_json(peer->log->fd, obj); if ((config.bmp_daemon_msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); #ifdef WITH_RABBITMQ amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); #endif } if ((config.bmp_daemon_msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &bms->writer_id_tokens); #ifdef WITH_KAFKA kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); #endif } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_writer_t p_avro_writer = {0}; avro_value_iface_t *p_avro_iface = NULL; avro_value_t p_avro_obj, p_avro_field, p_avro_branch; size_t p_avro_obj_len, p_avro_len; void *p_avro_local_buf = NULL; char tstamp_str[SRVBUFLEN]; p_avro_writer = avro_writer_memory(bms->avro_buf, LARGEBUFLEN); if (etype == BGP_LOGDUMP_ET_LOG) { p_avro_iface = avro_generic_class_from_schema(bms->msglog_avro_schema[log_type]); } else if (etype == BGP_LOGDUMP_ET_DUMP) { p_avro_iface = avro_generic_class_from_schema(bms->dump_avro_schema[log_type]); } pm_avro_check(avro_generic_value_new(p_avro_iface, &p_avro_obj)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "event_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, event_type)); if (etype == BGP_LOGDUMP_ET_LOG) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, log_seq)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, tstamp_str)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp_arrival", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, tstamp_str)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp_event", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (etype == BGP_LOGDUMP_ET_DUMP) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "seq", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bgp_peer_log_seq_get(&bms->log_seq))); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bms->dump.tstamp_str)); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp_arrival", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata->tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&p_avro_obj, "timestamp_event", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, tstamp_str)); } pm_avro_check(avro_value_get_by_name(&p_avro_obj, "bmp_router", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, peer->addr_str)); if (bms->peer_port_str) { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "bmp_router_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, peer->tcp_port)); } else { pm_avro_check(avro_value_get_by_name(&p_avro_obj, "bmp_router_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (config.bmp_daemon_tag_map && tag) { bgp_tag_print_avro(p_avro_obj, tag); } switch (log_type) { case BMP_LOG_TYPE_STATS: ret = bmp_log_msg_stats(peer, bdata, tlvs, (struct bmp_log_stats *) log_data, event_type, output, &p_avro_obj); break; case BMP_LOG_TYPE_INIT: ret = bmp_log_msg_init(peer, bdata, tlvs, event_type, output, &p_avro_obj); break; case BMP_LOG_TYPE_TERM: ret = bmp_log_msg_term(peer, bdata, tlvs, event_type, output, &p_avro_obj); break; case BMP_LOG_TYPE_PEER_UP: ret = bmp_log_msg_peer_up(peer, bdata, tlvs, (struct bmp_log_peer_up *) log_data, event_type, output, &p_avro_obj); break; case BMP_LOG_TYPE_PEER_DOWN: ret = bmp_log_msg_peer_down(peer, bdata, tlvs, (struct bmp_log_peer_down *) log_data, event_type, output, &p_avro_obj); break; case BMP_LOG_TYPE_RPAT: ret = bmp_log_msg_rpat(peer, bdata, tlvs, (struct bmp_log_rpat *) log_data, event_type, output, &p_avro_obj); break; default: Log(LOG_INFO, "INFO ( %s/%s ): [%s] bmp_log_msg(): unknown message type (%u)\n", config.name, bms->log_str, peer->addr_str, log_type); break; } add_writer_name_and_pid_avro_v2(p_avro_obj, &bms->writer_id_tokens); if (((config.bmp_daemon_msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_file && etype == BGP_LOGDUMP_ET_DUMP) || (config.bmp_daemon_msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP) || (config.bmp_daemon_msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG && !bms->msglog_kafka_avro_schema_registry) || (config.bmp_dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP && !bms->dump_kafka_avro_schema_registry)) && (output == PRINT_OUTPUT_AVRO_BIN)) { avro_value_sizeof(&p_avro_obj, &p_avro_obj_len); assert(p_avro_obj_len < LARGEBUFLEN); if (avro_value_write(p_avro_writer, &p_avro_obj)) { Log(LOG_ERR, "ERROR ( %s/%s ): bmp_log_msg(): avro_value_write() failed: %s\n", config.name, bms->log_str, avro_strerror()); exit_gracefully(1); } p_avro_len = avro_writer_tell(p_avro_writer); p_avro_local_buf = bms->avro_buf; } if ((config.bmp_daemon_msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_file && etype == BGP_LOGDUMP_ET_DUMP)) { if (output == PRINT_OUTPUT_AVRO_BIN) { write_file_binary(peer->log->fd, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(peer->log->fd, p_avro_obj); } } if ((config.bmp_daemon_msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_RABBITMQ if (output == PRINT_OUTPUT_AVRO_BIN) { amqp_ret = write_binary_amqp(peer->log->amqp_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { amqp_ret = write_string_amqp(peer->log->amqp_host, avro_local_str); free(avro_local_str); } } p_amqp_unset_routing_key(peer->log->amqp_host); #endif } if ((config.bmp_daemon_msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (config.bmp_dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_KAFKA if ((bms->msglog_kafka_avro_schema_registry && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_avro_schema_registry && etype == BGP_LOGDUMP_ET_DUMP)) { #ifdef WITH_SERDES struct p_kafka_host *kafka_host = (struct p_kafka_host *) peer->log->kafka_host; if (kafka_host->sd_schema[log_type]) { if (serdes_schema_serialize_avro(kafka_host->sd_schema[log_type], &p_avro_obj, &p_avro_local_buf, &p_avro_len, kafka_host->errstr, sizeof(kafka_host->errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): bmp_log_msg(): serdes_schema_serialize_avro() failed for %s: %s\n", config.name, bms->log_str, bmp_msg_types[log_type], kafka_host->errstr); exit_gracefully(1); } } #endif } if (output == PRINT_OUTPUT_AVRO_BIN) { kafka_ret = write_binary_kafka(peer->log->kafka_host, p_avro_local_buf, p_avro_len); } else if (output == PRINT_OUTPUT_AVRO_JSON) { char *avro_local_str = NULL; avro_value_to_json(&p_avro_obj, TRUE, &avro_local_str); if (avro_local_str) { kafka_ret = write_binary_kafka(peer->log->kafka_host, avro_local_str, (strlen(avro_local_str) + 1)); free(avro_local_str); } } p_kafka_unset_topic(peer->log->kafka_host); #endif } avro_value_decref(&p_avro_obj); avro_value_iface_decref(p_avro_iface); avro_writer_reset(p_avro_writer); avro_writer_free(p_avro_writer); if (bms->msglog_kafka_avro_schema_registry || bms->dump_kafka_avro_schema_registry) { free(p_avro_local_buf); } #endif } return (ret | amqp_ret | kafka_ret); } int bmp_log_msg_stats(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, struct bmp_log_stats *blstats, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !bdata || !blstats || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; char bmp_msg_type[] = "stats"; char ip_address[INET6_ADDRSTRLEN]; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); json_object_set_new_nocheck(obj, "peer_ip", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_asn", json_integer((json_int_t)bdata->peer_asn)); json_object_set_new_nocheck(obj, "peer_type", json_integer((json_int_t)bdata->chars.peer_type)); if (!bdata->chars.is_loc && !bdata->chars.is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bdata->chars.is_post)); json_object_set_new_nocheck(obj, "is_in", json_integer(1)); } else if (bdata->chars.is_loc) { json_object_set_new_nocheck(obj, "is_filtered", json_integer((json_int_t)bdata->chars.is_filtered)); json_object_set_new_nocheck(obj, "is_loc", json_integer((json_int_t)bdata->chars.is_loc)); } else if (bdata->chars.is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bdata->chars.is_post)); json_object_set_new_nocheck(obj, "is_out", json_integer((json_int_t)bdata->chars.is_out)); } if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(bdata->chars.rd.type))); } json_object_set_new_nocheck(obj, "counter_type", json_integer((json_int_t)blstats->cnt_type)); if (blstats->cnt_type <= BMP_STATS_MAX) { json_object_set_new_nocheck(obj, "counter_type_str", json_string(bmp_stats_cnt_types[blstats->cnt_type])); } else { json_object_set_new_nocheck(obj, "counter_type_str", json_string("Unknown")); } if (blstats->cnt_type == BMP_STATS_TYPE9 || blstats->cnt_type == BMP_STATS_TYPE10) { json_object_set_new_nocheck(obj, "afi", json_integer((json_int_t)blstats->cnt_afi)); json_object_set_new_nocheck(obj, "safi", json_integer((json_int_t)blstats->cnt_safi)); } if (!tlvs || !pm_listcount(tlvs)) { json_object_set_new_nocheck(obj, "counter_value", json_integer((json_int_t)blstats->cnt_data)); } else { char *value = NULL; struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { value = bmp_tlv_value_print(tlv, bmp_stats_info_types, BMP_STATS_INFO_MAX); if (value) { json_object_set_new_nocheck(obj, "counter_value", json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, "counter_value", json_null()); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_t *obj = (avro_value_t *) vobj, p_avro_field, p_avro_branch; char bmp_msg_type[] = "stats"; char ip_address[INET6_ADDRSTRLEN]; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); pm_avro_check(avro_value_get_by_name(obj, "peer_ip", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); pm_avro_check(avro_value_get_by_name(obj, "peer_asn", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bdata->peer_asn)); pm_avro_check(avro_value_get_by_name(obj, "peer_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, bdata->chars.peer_type)); if (!bdata->chars.is_loc && !bdata->chars.is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, 1)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bdata->chars.is_loc) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_filtered)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_loc)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bdata->chars.is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_out)); } if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, rd_str)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_rd_origin_print(bdata->chars.rd.type))); } else { pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } pm_avro_check(avro_value_get_by_name(obj, "counter_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, blstats->cnt_type)); if (blstats->cnt_type <= BMP_STATS_MAX) { pm_avro_check(avro_value_get_by_name(obj, "counter_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_stats_cnt_types[blstats->cnt_type])); } else { pm_avro_check(avro_value_get_by_name(obj, "counter_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, "Unknown")); } if (blstats->cnt_type == BMP_STATS_TYPE9 || blstats->cnt_type == BMP_STATS_TYPE10) { pm_avro_check(avro_value_get_by_name(obj, "afi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, blstats->cnt_afi)); pm_avro_check(avro_value_get_by_name(obj, "safi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, blstats->cnt_safi)); } else { pm_avro_check(avro_value_get_by_name(obj, "afi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "safi", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } pm_avro_check(avro_value_get_by_name(obj, "counter_value", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, blstats->cnt_data)); #endif } return ret; } int bmp_log_msg_init(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char bmp_msg_type[] = "init"; json_t *obj = (json_t *) vobj; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->pen) { case BMP_TLV_PEN_STD: type = bmp_tlv_type_print(tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_init_info_types, BMP_INIT_INFO_MAX); break; default: type = bmp_tlv_type_print(tlv, "bmp_init_info", NULL, -1); value = bmp_tlv_value_print(tlv, NULL, -1); break; } if (type) { if (value) { json_object_set_new_nocheck(obj, type, json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO int idx = 0, bmp_init_tlvs[BMP_INIT_INFO_MAX + 1]; avro_value_t *obj = (avro_value_t *) vobj, p_avro_field, p_avro_branch; char bmp_msg_type[] = "init"; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); memset(&bmp_init_tlvs, 0, sizeof(bmp_init_tlvs)); if (tlvs) { char *type = NULL, *value = NULL; struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; /* No PEN defined so far so we short-circuit to standard elements */ for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { if (tlv->type <= BMP_INIT_INFO_MAX) { type = bmp_tlv_type_print(tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_init_info_types, BMP_INIT_INFO_MAX); if (type) { pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); if (value) { pm_avro_check(avro_value_set_string(&p_avro_branch, value)); free(value); } else { pm_avro_check(avro_value_set_null(&p_avro_branch)); } free(type); } bmp_init_tlvs[tlv->type] = TRUE; } } } for (idx = 0; idx <= BMP_INIT_INFO_MAX; idx++) { struct bmp_log_tlv dummy_tlv; char *type; memset(&dummy_tlv, 0, sizeof(dummy_tlv)); dummy_tlv.type = idx; if (!bmp_init_tlvs[idx]) { type = bmp_tlv_type_print(&dummy_tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } #endif } return ret; } int bmp_log_msg_term(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char bmp_msg_type[] = "term"; json_t *obj = (json_t *) vobj; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->pen) { case BMP_TLV_PEN_STD: type = bmp_tlv_type_print(tlv, "bmp_term_info", bmp_term_info_types, BMP_TERM_INFO_MAX); if (tlv->type == BMP_TERM_INFO_REASON && tlv->len == 2) { char *value_tmp = NULL; u_int16_t reas_type = 0; value_tmp = bmp_tlv_value_print(tlv, bmp_term_info_types, BMP_TERM_INFO_MAX); if (value_tmp) { reas_type = atoi(value_tmp); free(value_tmp); } value = bmp_term_reason_print(reas_type); } else { value = bmp_tlv_value_print(tlv, bmp_term_info_types, BMP_TERM_INFO_MAX); } break; default: type = bmp_tlv_type_print(tlv, "bmp_term_info", NULL, -1); value = bmp_tlv_value_print(tlv, NULL, -1); break; } if (type) { if (value) { json_object_set_new_nocheck(obj, type, json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO int idx = 0, bmp_term_tlvs[BMP_TERM_INFO_MAX + 1]; avro_value_t *obj = (avro_value_t *) vobj, p_avro_field, p_avro_branch; char bmp_msg_type[] = "term"; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); memset(&bmp_term_tlvs, 0, sizeof(bmp_term_tlvs)); if (tlvs) { char *type = NULL, *value = NULL; struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; /* No PEN defined so far so we short-circuit to standard elements */ for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { if (tlv->type <= BMP_TERM_INFO_MAX) { type = bmp_tlv_type_print(tlv, "bmp_term_info", bmp_term_info_types, BMP_TERM_INFO_MAX); if (tlv->type == BMP_TERM_INFO_REASON && tlv->len == 2) { u_int16_t reas_type; memcpy(&reas_type, tlv->val, 2); reas_type = ntohs(reas_type); value = bmp_term_reason_print(reas_type); } else { value = null_terminate(tlv->val, tlv->len); } if (type) { pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); if (value) { pm_avro_check(avro_value_set_string(&p_avro_branch, value)); free(value); } else { pm_avro_check(avro_value_set_null(&p_avro_branch)); } free(type); } bmp_term_tlvs[tlv->type] = TRUE; } } } for (idx = 0; idx <= BMP_TERM_INFO_MAX; idx++) { struct bmp_log_tlv dummy_tlv; char *type; memset(&dummy_tlv, 0, sizeof(dummy_tlv)); dummy_tlv.type = idx; if (!bmp_term_tlvs[idx]) { type = bmp_tlv_type_print(&dummy_tlv, "bmp_term_info", bmp_term_info_types, BMP_TERM_INFO_MAX); pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } #endif } return ret; } int bmp_log_msg_peer_up(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, struct bmp_log_peer_up *blpu, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !bdata || !blpu || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char bmp_msg_type[] = "peer_up"; char ip_address[INET6_ADDRSTRLEN]; json_t *obj = (json_t *) vobj; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); json_object_set_new_nocheck(obj, "peer_ip", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_asn", json_integer((json_int_t)bdata->peer_asn)); json_object_set_new_nocheck(obj, "peer_type", json_integer((json_int_t)bdata->chars.peer_type)); if (bdata->chars.peer_type <= BMP_PEER_TYPE_MAX) { json_object_set_new_nocheck(obj, "peer_type_str", json_string(bmp_peer_types[bdata->chars.peer_type])); } if (!bdata->chars.is_loc && !bdata->chars.is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bdata->chars.is_post)); json_object_set_new_nocheck(obj, "is_in", json_integer(1)); } else if (bdata->chars.is_loc) { json_object_set_new_nocheck(obj, "is_filtered", json_integer((json_int_t)bdata->chars.is_filtered)); json_object_set_new_nocheck(obj, "is_loc", json_integer((json_int_t)bdata->chars.is_loc)); } else if (bdata->chars.is_out) { json_object_set_new_nocheck(obj, "is_post", json_integer((json_int_t)bdata->chars.is_post)); json_object_set_new_nocheck(obj, "is_out", json_integer((json_int_t)bdata->chars.is_out)); } json_object_set_new_nocheck(obj, "bgp_id", json_string(inet_ntoa(bdata->bgp_id.address.ipv4))); json_object_set_new_nocheck(obj, "local_port", json_integer((json_int_t)blpu->loc_port)); json_object_set_new_nocheck(obj, "remote_port", json_integer((json_int_t)blpu->rem_port)); addr_to_str(ip_address, &blpu->local_ip); json_object_set_new_nocheck(obj, "local_ip", json_string(ip_address)); if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(bdata->chars.rd.type))); } if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->pen) { case BMP_TLV_PEN_STD: type = bmp_tlv_type_print(tlv, "bmp_peer_up_info", bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); break; default: type = bmp_tlv_type_print(tlv, "bmp_peer_up_info", NULL, -1); value = bmp_tlv_value_print(tlv, NULL, -1); break; } if (type) { if (value) { json_object_set_new_nocheck(obj, type, json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO int idx = 0, bmp_peer_up_tlvs[BMP_PEER_UP_INFO_MAX + 1]; avro_value_t *obj = (avro_value_t *) vobj, p_avro_field, p_avro_branch; char bmp_msg_type[] = "peer_up"; char ip_address[INET6_ADDRSTRLEN]; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); pm_avro_check(avro_value_get_by_name(obj, "peer_ip", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); pm_avro_check(avro_value_get_by_name(obj, "peer_asn", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bdata->peer_asn)); pm_avro_check(avro_value_get_by_name(obj, "peer_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, bdata->chars.peer_type)); if (bdata->chars.peer_type <= BMP_PEER_TYPE_MAX) { pm_avro_check(avro_value_get_by_name(obj, "peer_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bmp_peer_types[bdata->chars.peer_type])); } else { pm_avro_check(avro_value_get_by_name(obj, "peer_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (!bdata->chars.is_loc && !bdata->chars.is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, 1)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bdata->chars.is_loc) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_filtered)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_loc)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } else if (bdata->chars.is_out) { pm_avro_check(avro_value_get_by_name(obj, "is_in", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_filtered", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_loc", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "is_post", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_post)); pm_avro_check(avro_value_get_by_name(obj, "is_out", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, bdata->chars.is_out)); } pm_avro_check(avro_value_get_by_name(obj, "bgp_id", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, inet_ntoa(bdata->bgp_id.address.ipv4))); pm_avro_check(avro_value_get_by_name(obj, "local_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, blpu->loc_port)); pm_avro_check(avro_value_get_by_name(obj, "remote_port", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, blpu->rem_port)); addr_to_str(ip_address, &blpu->local_ip); pm_avro_check(avro_value_get_by_name(obj, "local_ip", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, rd_str)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_rd_origin_print(bdata->chars.rd.type))); } else { pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } memset(&bmp_peer_up_tlvs, 0, sizeof(bmp_peer_up_tlvs)); if (tlvs) { char *type = NULL, *value = NULL; struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; /* No PEN defined so far so we short-circuit to standard elements */ for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { if (tlv->type <= BMP_PEER_UP_INFO_MAX) { type = bmp_tlv_type_print(tlv, "bmp_peer_up_info", bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); if (type) { pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); if (value) { pm_avro_check(avro_value_set_string(&p_avro_branch, value)); free(value); } else { pm_avro_check(avro_value_set_null(&p_avro_branch)); } free(type); } bmp_peer_up_tlvs[tlv->type] = TRUE; } } } /* mark missing tlv types */ for (idx = 0; idx <= BMP_PEER_UP_INFO_MAX; idx++) { struct bmp_log_tlv dummy_tlv; char *type; memset(&dummy_tlv, 0, sizeof(dummy_tlv)); dummy_tlv.type = idx; if (!bmp_peer_up_tlvs[idx]) { type = bmp_tlv_type_print(&dummy_tlv, "bmp_peer_up_info", bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } #endif } return ret; } int bmp_log_msg_peer_down(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, struct bmp_log_peer_down *blpd, char *event_type, int output, void *vobj) { int ret = 0; if (!peer || !bdata || !blpd || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char bmp_msg_type[] = "peer_down"; char ip_address[INET6_ADDRSTRLEN]; json_t *obj = (json_t *) vobj; json_object_set_new_nocheck(obj, "bmp_msg_type", json_string(bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); json_object_set_new_nocheck(obj, "peer_ip", json_string(ip_address)); json_object_set_new_nocheck(obj, "peer_asn", json_integer((json_int_t)bdata->peer_asn)); json_object_set_new_nocheck(obj, "peer_type", json_integer((json_int_t)bdata->chars.peer_type)); if (bdata->chars.peer_type <= BMP_PEER_TYPE_MAX) { json_object_set_new_nocheck(obj, "peer_type_str", json_string(bmp_peer_types[bdata->chars.peer_type])); } if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); json_object_set_new_nocheck(obj, "rd_origin", json_string(bgp_rd_origin_print(bdata->chars.rd.type))); } json_object_set_new_nocheck(obj, "reason_type", json_integer((json_int_t)blpd->reason)); if (blpd->reason <= BMP_PEER_DOWN_MAX) { json_object_set_new_nocheck(obj, "reason_str", json_string(bmp_peer_down_reason_types[blpd->reason])); } if (blpd->reason == BMP_PEER_DOWN_LOC_CODE) { json_object_set_new_nocheck(obj, "reason_loc_code", json_integer((json_int_t)blpd->loc_code)); } if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->pen) { case BMP_TLV_PEN_STD: type = bmp_tlv_type_print(tlv, "bmp_peer_down_info", bmp_peer_down_info_types, BMP_PEER_DOWN_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_peer_down_info_types, BMP_PEER_DOWN_INFO_MAX); break; default: type = bmp_tlv_type_print(tlv, "bmp_peer_down_info", NULL, -1); value = bmp_tlv_value_print(tlv, NULL, -1); break; } if (type) { if (value) { json_object_set_new_nocheck(obj, type, json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO int idx = 0, bmp_peer_down_tlvs[BMP_PEER_DOWN_INFO_MAX + 1]; avro_value_t *obj = (avro_value_t *) vobj, p_avro_field, p_avro_branch; char bmp_msg_type[] = "peer_down"; char ip_address[INET6_ADDRSTRLEN]; pm_avro_check(avro_value_get_by_name(obj, "bmp_msg_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, bmp_msg_type)); addr_to_str(ip_address, &bdata->peer_ip); pm_avro_check(avro_value_get_by_name(obj, "peer_ip", &p_avro_field, NULL)); pm_avro_check(avro_value_set_string(&p_avro_field, ip_address)); pm_avro_check(avro_value_get_by_name(obj, "peer_asn", &p_avro_field, NULL)); pm_avro_check(avro_value_set_long(&p_avro_field, bdata->peer_asn)); pm_avro_check(avro_value_get_by_name(obj, "peer_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, bdata->chars.peer_type)); if (bdata->chars.peer_type <= BMP_PEER_TYPE_MAX) { pm_avro_check(avro_value_get_by_name(obj, "peer_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bmp_peer_types[bdata->chars.peer_type])); } else { pm_avro_check(avro_value_get_by_name(obj, "peer_type_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (!is_empty_256b(&bdata->chars.rd, sizeof(bdata->chars.rd))) { char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &bdata->chars.rd); pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, rd_str)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bgp_rd_origin_print(bdata->chars.rd.type))); } else { pm_avro_check(avro_value_get_by_name(obj, "rd", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); pm_avro_check(avro_value_get_by_name(obj, "rd_origin", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } pm_avro_check(avro_value_get_by_name(obj, "reason_type", &p_avro_field, NULL)); pm_avro_check(avro_value_set_int(&p_avro_field, blpd->reason)); if (blpd->reason <= BMP_PEER_DOWN_MAX) { pm_avro_check(avro_value_get_by_name(obj, "reason_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_string(&p_avro_branch, bmp_peer_down_reason_types[blpd->reason])); } else { pm_avro_check(avro_value_get_by_name(obj, "reason_str", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } if (blpd->reason == BMP_PEER_DOWN_LOC_CODE) { pm_avro_check(avro_value_get_by_name(obj, "reason_loc_code", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); pm_avro_check(avro_value_set_int(&p_avro_branch, blpd->loc_code)); } else { pm_avro_check(avro_value_get_by_name(obj, "reason_loc_code", &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } memset(&bmp_peer_down_tlvs, 0, sizeof(bmp_peer_down_tlvs)); /* No Peer Down TLVs defined, BMP_PEER_DOWN_INFO_MAX is hence set to -1 and this requires converting to int to sanitize comparisons */ if (tlvs) { char *type = NULL, *value = NULL; struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; /* No PEN defined so far so we short-circuit to standard elements */ for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { if ((int)tlv->type <= (int)BMP_PEER_DOWN_INFO_MAX) { type = bmp_tlv_type_print(tlv, "bmp_peer_down_info", bmp_peer_down_info_types, BMP_PEER_DOWN_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_peer_down_info_types, BMP_PEER_DOWN_INFO_MAX); if (type) { pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, TRUE, &p_avro_branch)); if (value) { pm_avro_check(avro_value_set_string(&p_avro_branch, value)); free(value); } else { pm_avro_check(avro_value_set_null(&p_avro_branch)); } free(type); } bmp_peer_down_tlvs[tlv->type] = TRUE; } } } /* mark missing tlv types */ for (idx = 0; idx <= BMP_PEER_DOWN_INFO_MAX; idx++) { struct bmp_log_tlv dummy_tlv; char *type; memset(&dummy_tlv, 0, sizeof(dummy_tlv)); dummy_tlv.type = idx; if (!bmp_peer_down_tlvs[idx]) { type = bmp_tlv_type_print(&dummy_tlv, "bmp_peer_down_info", bmp_peer_down_info_types, BMP_PEER_DOWN_INFO_MAX); pm_avro_check(avro_value_get_by_name(obj, type, &p_avro_field, NULL)); pm_avro_check(avro_value_set_branch(&p_avro_field, FALSE, &p_avro_branch)); } } #endif } return ret; } int bmp_log_msg_route_monitor_tlv(struct pm_list *tlvs, int output, void *vobj) { int ret = 0; if (!vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; if (tlvs) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS_RO(tlvs, node, tlv)) { char *type = NULL, *value = NULL; switch (tlv->pen) { case BMP_TLV_PEN_STD: switch (tlv->type) { case BMP_ROUTE_MONITOR_INFO_MARKING: (*bmp_rm_info_types[tlv->type].logdump_func)(NULL, NULL, tlv, NULL, FALSE, output, vobj); break; default: type = bmp_tlv_type_print(tlv, "bmp_rm_info", bmp_rm_info_types, BMP_ROUTE_MONITOR_INFO_MAX); value = bmp_tlv_value_print(tlv, bmp_rm_info_types, BMP_ROUTE_MONITOR_INFO_MAX); break; } break; default: type = bmp_tlv_type_print(tlv, "bmp_rm_info", NULL, -1); value = bmp_tlv_value_print(tlv, NULL, -1); break; } if (type) { if (value) { json_object_set_new_nocheck(obj, type, json_string(value)); free(value); } else { json_object_set_new_nocheck(obj, type, json_null()); } free(type); } } } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO /* TBD: once IANA-governed TLVs are defined or E-bit is implemented */ #endif } return ret; } int bmp_log_rm_tlv_path_marking(struct bgp_peer *null1, struct bmp_data *null2, void *vtlv, void *null3, char *null4, int output, void *vobj) { struct bmp_log_tlv *tlv = vtlv; int ret = 0; if (!tlv || !vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; struct bmp_rm_pm_tlv *pm_tlv = NULL; char value_str[SUPERSHORTBUFLEN]; unsigned char *value; pm_tlv = (struct bmp_rm_pm_tlv *) tlv->val; bmp_log_rm_tlv_pm_status(ntohl(pm_tlv->path_status), output, vobj); if (tlv->len == 8 /* index (2) + status (4) + reason code (2) */) { value = (unsigned char *) &pm_tlv->reason_code; snprintf(value_str, SUPERSHORTBUFLEN, "0x%02x%02x", value[0], value[1]); json_object_set_new_nocheck(obj, "reason_code", json_string(value_str)); } #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO // XXX: to be worked out later #endif } return ret; } int bmp_log_rm_tlv_pm_status(u_int32_t path_status, int output, void *vobj) { int ret = 0; if (!vobj) return ERR; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *obj = (json_t *) vobj; json_t *ps_array = json_array(); char *value = NULL, value_str[SUPERSHORTBUFLEN]; if (!path_status) { json_array_append_new(ps_array, json_string("Unknown")); } else { if (path_status & BMP_RM_PM_PS_INVALID) { json_array_append_new(ps_array, json_string("Invalid")); path_status ^= BMP_RM_PM_PS_INVALID; } if (path_status & BMP_RM_PM_PS_BEST) { json_array_append_new(ps_array, json_string("Best")); path_status ^= BMP_RM_PM_PS_BEST; } if (path_status & BMP_RM_PM_PS_NO_SELECT) { json_array_append_new(ps_array, json_string("Non-selected")); path_status ^= BMP_RM_PM_PS_NO_SELECT; } if (path_status & BMP_RM_PM_PS_PRIMARY) { json_array_append_new(ps_array, json_string("Primary")); path_status ^= BMP_RM_PM_PS_PRIMARY; } if (path_status & BMP_RM_PM_PS_BACKUP) { json_array_append_new(ps_array, json_string("Backup")); path_status ^= BMP_RM_PM_PS_BACKUP; } if (path_status & BMP_RM_PM_PS_NO_INSTALL) { json_array_append_new(ps_array, json_string("Non-installed")); path_status ^= BMP_RM_PM_PS_NO_INSTALL; } if (path_status & BMP_RM_PM_PS_BEST_EXT) { json_array_append_new(ps_array, json_string("Best-external")); path_status ^= BMP_RM_PM_PS_BEST_EXT; } if (path_status & BMP_RM_PM_PS_ADD_PATH) { json_array_append_new(ps_array, json_string("Add-Path")); path_status ^= BMP_RM_PM_PS_ADD_PATH; } if (path_status) { value = (char *) &path_status; snprintf(value_str, SUPERSHORTBUFLEN, "0x%02x%02x%02x%02x", value[0], value[1], value[2], value[3]); json_array_append_new(ps_array, json_string(value_str)); path_status = FALSE; } } json_object_set_new_nocheck(obj, "path_status", ps_array); #endif } else if ((output == PRINT_OUTPUT_AVRO_BIN) || (output == PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO // XXX: to be worked out later #endif } return ret; } void bmp_dump_init_peer(struct bgp_peer *peer) { struct bgp_misc_structs *bms; if (!peer) return; bms = bgp_select_misc_db(peer->type); if (!bms) return; assert(!peer->bmp_se); peer->bmp_se = malloc(sizeof(struct bmp_dump_se_ll)); if (!peer->bmp_se) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() bmp_se structure. Terminating thread.\n", config.name, bms->log_str); exit_gracefully(1); } memset(peer->bmp_se, 0, sizeof(struct bmp_dump_se_ll)); } void bmp_dump_close_peer(struct bgp_peer *peer) { struct bmp_dump_se_ll *bdsell; if (!peer) return; bdsell = (struct bmp_dump_se_ll *) peer->bmp_se; if (bdsell && bdsell->start) bmp_dump_se_ll_destroy(bdsell); free(peer->bmp_se); peer->bmp_se = NULL; } void bmp_dump_se_ll_append(struct bgp_peer *peer, struct bmp_data *bdata, struct pm_list *tlvs, void *extra, int log_type) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BMP); struct bmp_dump_se_ll *se_ll; struct bmp_dump_se_ll_elem *se_ll_elem; if (!peer) return; assert(peer->bmp_se); se_ll_elem = malloc(sizeof(struct bmp_dump_se_ll_elem)); if (!se_ll_elem) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() se_ll_elem structure. Terminating thread.\n", config.name, bms->log_str); exit_gracefully(1); } memset(se_ll_elem, 0, sizeof(struct bmp_dump_se_ll_elem)); if (bdata) memcpy(&se_ll_elem->rec.bdata, bdata, sizeof(struct bmp_data)); if (extra && log_type) { switch (log_type) { case BMP_LOG_TYPE_STATS: memcpy(&se_ll_elem->rec.se.stats, extra, sizeof(struct bmp_log_stats)); break; case BMP_LOG_TYPE_PEER_UP: memcpy(&se_ll_elem->rec.se.peer_up, extra, sizeof(struct bmp_log_peer_up)); break; case BMP_LOG_TYPE_PEER_DOWN: memcpy(&se_ll_elem->rec.se.peer_down, extra, sizeof(struct bmp_log_peer_down)); break; default: break; } } if (tlvs && pm_listcount(tlvs)) { se_ll_elem->rec.tlvs = tlvs; } se_ll_elem->rec.seq = bgp_peer_log_seq_get(&bms->log_seq); se_ll_elem->rec.se_type = log_type; se_ll_elem->next = NULL; /* pedantic */ se_ll = (struct bmp_dump_se_ll *) peer->bmp_se; /* append to an empty ll */ if (!se_ll->start) { assert(!se_ll->last); se_ll->start = se_ll_elem; se_ll->last = se_ll_elem; } /* append to an existing ll */ else { assert(se_ll->last); se_ll->last->next = se_ll_elem; se_ll->last = se_ll_elem; } } void bmp_dump_se_ll_destroy(struct bmp_dump_se_ll *bdsell) { struct bmp_dump_se_ll_elem *se_ll_elem, *se_ll_elem_next; if (!bdsell) return; if (!bdsell->start) return; assert(bdsell->last); for (se_ll_elem = bdsell->start; se_ll_elem; se_ll_elem = se_ll_elem_next) { if (se_ll_elem->rec.tlvs) { bmp_tlv_list_destroy(se_ll_elem->rec.tlvs); } se_ll_elem_next = se_ll_elem->next; free(se_ll_elem); } bdsell->start = NULL; bdsell->last = NULL; } void bmp_handle_dump_event(int max_peers_idx) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BMP); thread_pool_t *bmp_dump_workers_pool; struct pm_dump_runner pdr[config.bmp_dump_workers]; u_int64_t dump_seqno; int idx, ret; struct bgp_peer *peer; struct bmp_dump_se_ll *bdsell; /* pre-flight check */ if (!bms->dump_backend_methods || !config.bmp_dump_refresh_time) { return; } /* Sequencing the dump event */ dump_seqno = bgp_peer_log_seq_get(&bms->log_seq); bgp_peer_log_seq_increment(&bms->log_seq); switch (ret = fork()) { case 0: /* Child */ /* we have to ignore signals to avoid loops: because we are already forked */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); pm_setproctitle("%s %s [%s]", config.type, "Core Process -- BMP Dump Writer", config.name); config.is_forked = TRUE; /* setting ourselves as read-only */ bms->is_readonly = TRUE; /* Arranging workers data */ distribute_work(pdr, dump_seqno, config.bmp_dump_workers, max_peers_idx); /* creating the thread pool */ bmp_dump_workers_pool = allocate_thread_pool(config.bmp_dump_workers); assert(bmp_dump_workers_pool); for (idx = 0; idx < config.bmp_dump_workers; idx++) { if (!pdr[idx].noop) { send_to_pool(bmp_dump_workers_pool, bmp_dump_event_runner, &pdr[idx]); } } deallocate_thread_pool(&bmp_dump_workers_pool); exit_gracefully(0); default: /* Parent */ if (ret == -1) { /* Something went wrong */ Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork BMP table dump writer: %s\n", config.name, bms->log_str, strerror(errno)); } /* destroy bmp_se linked-list content after dump event */ for (peer = NULL, idx = 0; idx < max_peers_idx; idx++) { if (bmp_peers[idx].self.fd) { peer = &bmp_peers[idx].self; bdsell = peer->bmp_se; if (bdsell && bdsell->start && abs((int) pm_djb2_string_hash((unsigned char*) peer->addr_str)) % config.bmp_dump_time_slots == bms->current_slot) { bmp_dump_se_ll_destroy(bdsell); } } } break; } bms->current_slot = (bms->current_slot + 1) % config.bmp_dump_time_slots; } int bmp_dump_event_runner(struct pm_dump_runner *pdr) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_BMP); char current_filename[SRVBUFLEN], last_filename[SRVBUFLEN], tmpbuf[SRVBUFLEN]; char latest_filename[SRVBUFLEN], dump_partition_key[SRVBUFLEN]; char event_type[] = "dump", *fd_buf = NULL; int peers_idx, duration, tables_num; struct bgp_rt_structs *inter_domain_routing_db; struct bgp_table *table; struct bgp_node *node; afi_t afi; safi_t safi; pid_t dumper_pid; time_t start; u_int64_t dump_elems = 0, dump_seqno = pdr->seq; struct bgp_peer *peer, *saved_peer; struct bmp_dump_se_ll *bdsell; struct bgp_peer_log peer_log; #ifdef WITH_RABBITMQ struct p_amqp_host bmp_dump_amqp_host; #endif #ifdef WITH_KAFKA struct p_kafka_host bmp_dump_kafka_host; #endif memset(last_filename, 0, sizeof(last_filename)); memset(current_filename, 0, sizeof(current_filename)); fd_buf = malloc(OUTPUT_FILE_BUFSZ); bgp_peer_log_seq_set(&bms->log_seq, dump_seqno); #ifdef WITH_RABBITMQ if (config.bmp_dump_amqp_routing_key) { int ret; bmp_dump_init_amqp_host(&bmp_dump_amqp_host); ret = p_amqp_connect_to_publish(&bmp_dump_amqp_host); if (ret) exit_gracefully(ret); } #endif #ifdef WITH_KAFKA if (config.bmp_dump_kafka_topic) { int ret; ret = bmp_dump_init_kafka_host(&bmp_dump_kafka_host); if (ret) exit_gracefully(ret); } #endif dumper_pid = getpid(); Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BMP tables - START (PID: %u RID: %u) ***\n", config.name, bms->log_str, dumper_pid, pdr->id); start = time(NULL); tables_num = 0; #ifdef WITH_SERDES if (config.bmp_dump_kafka_avro_schema_registry) { if (strchr(config.bmp_dump_kafka_topic, '$')) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'bmp_dump_kafka_topic' is not compatible with 'bmp_dump_kafka_avro_schema_registry'. Exiting.\n", config.name, bms->log_str); exit_gracefully(1); } bmp_dump_kafka_host.sd_schema[BMP_MSG_ROUTE_MONITOR] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_ROUTE_MONITOR], "bmp", "dump_rm", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_STATS] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_STATS], "bmp", "stats", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_PEER_UP] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_UP], "bmp", "peer_up", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_PEER_DOWN] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_PEER_DOWN], "bmp", "peer_down", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_INIT] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_INIT], "bmp", "init", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_TERM] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_TERM], "bmp", "term", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_MSG_TMP_RPAT] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_MSG_TMP_RPAT], "bmp", "rpat", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_LOG_TYPE_DUMPINIT] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPINIT], "bmp", "dumpinit", config.bmp_dump_kafka_avro_schema_registry); bmp_dump_kafka_host.sd_schema[BMP_LOG_TYPE_DUMPCLOSE] = compose_avro_schema_registry_name_2(config.bmp_dump_kafka_topic, FALSE, bmp_misc_db->dump_avro_schema[BMP_LOG_TYPE_DUMPCLOSE], "bmp", "dumpclose", config.bmp_dump_kafka_avro_schema_registry); } #endif if (config.bmp_dump_time_slots > 1) { Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BMP tables - SLOT %d / %d ***\n", config.name, bms->log_str, bms->current_slot + 1, config.bmp_dump_time_slots); } for (peer = NULL, saved_peer = NULL, peers_idx = pdr->first; peers_idx <= pdr->last; peers_idx++) { peer = &bmp_peers[peers_idx].self; int bmp_router_slot = abs((int) pm_djb2_string_hash((unsigned char*) peer->addr_str)) % config.bmp_dump_time_slots; if (bmp_peers[peers_idx].self.fd && bmp_router_slot == bms->current_slot) { peer->log = &peer_log; /* abusing struct bgp_peer a bit, but we are in a child */ bdsell = peer->bmp_se; if (config.bmp_dump_file) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bmp_dump_file, peer); } if (config.bmp_dump_amqp_routing_key) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bmp_dump_amqp_routing_key, peer); } if (config.bmp_dump_kafka_topic) { bgp_peer_log_dynname(current_filename, SRVBUFLEN, config.bmp_dump_kafka_topic, peer); } if (config.bmp_dump_kafka_partition_key) { bgp_peer_log_dynname(dump_partition_key, SRVBUFLEN, config.bmp_dump_kafka_partition_key, peer); } pm_strftime_same(current_filename, SRVBUFLEN, tmpbuf, &bms->dump.tstamp.tv_sec, config.timestamps_utc); /* we close last_filename and open current_filename in case they differ; we are safe with this approach until time and BMP peer (IP, port) are the only variables supported as part of bmp_dump_file. */ if (config.bmp_dump_file) { if (strcmp(last_filename, current_filename)) { if (saved_peer && saved_peer->log && strlen(last_filename)) { close_output_file(saved_peer->log->fd); if (config.bmp_dump_latest_file) { bgp_peer_log_dynname(latest_filename, SRVBUFLEN, config.bmp_dump_latest_file, saved_peer); link_latest_output_file(latest_filename, last_filename); } } peer->log->fd = open_output_file(current_filename, "w", TRUE); if (fd_buf) { if (setvbuf(peer->log->fd, fd_buf, _IOFBF, OUTPUT_FILE_BUFSZ)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] setvbuf() failed: %s\n", config.name, bms->log_str, current_filename, strerror(errno)); } else { memset(fd_buf, 0, OUTPUT_FILE_BUFSZ); } } } } /* a bit pedantic maybe but should come at little cost and emulating bmp_dump_file behaviour will work */ #ifdef WITH_RABBITMQ if (config.bmp_dump_amqp_routing_key) { peer->log->amqp_host = &bmp_dump_amqp_host; strcpy(peer->log->filename, current_filename); } #endif #ifdef WITH_KAFKA if (config.bmp_dump_kafka_topic) { peer->log->kafka_host = &bmp_dump_kafka_host; strcpy(peer->log->filename, current_filename); if (config.bmp_dump_kafka_partition_key) { p_kafka_set_key(peer->log->kafka_host, dump_partition_key, strlen(dump_partition_key)); } } #endif /* Being bmp_daemon_tag_map limited to 'ip' key lookups, this is finely placed here. Should further lookups be possible, this may be very possibly moved inside the loop */ if (config.bmp_daemon_tag_map) { bgp_tag_init_find(peer, (struct sockaddr *) &bmp_logdump_tag_peer, &bmp_logdump_tag); bgp_tag_find((struct id_table *)bmp_logdump_tag.tag_table, &bmp_logdump_tag, &bmp_logdump_tag.tag, NULL); } bgp_peer_dump_init(peer, &bmp_logdump_tag, config.bmp_dump_output, FUNC_TYPE_BMP); inter_domain_routing_db = bgp_select_routing_db(FUNC_TYPE_BMP); if (!inter_domain_routing_db) return ERR; for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { table = inter_domain_routing_db->rib[afi][safi]; node = bgp_table_top(peer, table); while (node) { u_int32_t modulo = bms->route_info_modulo(peer, NULL, bms->table_per_peer_buckets); u_int32_t peer_buckets; struct bgp_info *ri; for (peer_buckets = 0; peer_buckets < config.bmp_table_per_peer_buckets; peer_buckets++) { for (ri = node->info[modulo+peer_buckets]; ri; ri = ri->next) { struct bmp_peer *local_bmpp = ri->peer->bmp_se; if (local_bmpp && (&local_bmpp->self == peer)) { ri->peer->log = peer->log; bgp_peer_log_msg(node, ri, afi, safi, &bmp_logdump_tag, event_type, config.bmp_dump_output, NULL, BGP_LOG_TYPE_MISC); dump_elems++; } } } node = bgp_route_next(peer, node); } } } if (bdsell && bdsell->start) { struct bmp_dump_se_ll_elem *se_ll_elem; char event_type[] = "dump"; for (se_ll_elem = bdsell->start; se_ll_elem; se_ll_elem = se_ll_elem->next) { switch (se_ll_elem->rec.se_type) { case BMP_LOG_TYPE_STATS: bmp_log_msg(peer, &se_ll_elem->rec.bdata, NULL, &bmp_logdump_tag, &se_ll_elem->rec.se.stats, se_ll_elem->rec.seq, event_type, config.bmp_dump_output, BMP_LOG_TYPE_STATS); break; case BMP_LOG_TYPE_INIT: bmp_log_msg(peer, &se_ll_elem->rec.bdata, se_ll_elem->rec.tlvs, &bmp_logdump_tag, NULL, se_ll_elem->rec.seq, event_type, config.bmp_dump_output, BMP_LOG_TYPE_INIT); break; case BMP_LOG_TYPE_TERM: bmp_log_msg(peer, &se_ll_elem->rec.bdata, se_ll_elem->rec.tlvs, &bmp_logdump_tag, NULL, se_ll_elem->rec.seq, event_type, config.bmp_dump_output, BMP_LOG_TYPE_TERM); break; case BMP_LOG_TYPE_PEER_UP: bmp_log_msg(peer, &se_ll_elem->rec.bdata, se_ll_elem->rec.tlvs, &bmp_logdump_tag, &se_ll_elem->rec.se.peer_up, se_ll_elem->rec.seq, event_type, config.bmp_dump_output, BMP_LOG_TYPE_PEER_UP); break; case BMP_LOG_TYPE_PEER_DOWN: bmp_log_msg(peer, &se_ll_elem->rec.bdata, se_ll_elem->rec.tlvs, &bmp_logdump_tag, &se_ll_elem->rec.se.peer_down, se_ll_elem->rec.seq, event_type, config.bmp_dump_output, BMP_LOG_TYPE_PEER_DOWN); break; default: break; } } } saved_peer = peer; strlcpy(last_filename, current_filename, SRVBUFLEN); bgp_peer_dump_close(peer, &bmp_logdump_tag, NULL, config.bmp_dump_output, FUNC_TYPE_BMP); tables_num++; } } #ifdef WITH_RABBITMQ if (config.bmp_dump_amqp_routing_key) { p_amqp_close(&bmp_dump_amqp_host, FALSE); } #endif #ifdef WITH_KAFKA if (config.bmp_dump_kafka_topic) { p_kafka_close(&bmp_dump_kafka_host, FALSE); } #endif if (config.bmp_dump_file && peer) { close_output_file(peer->log->fd); } if (config.bmp_dump_latest_file && peer) { bgp_peer_log_dynname(latest_filename, SRVBUFLEN, config.bmp_dump_latest_file, peer); link_latest_output_file(latest_filename, last_filename); } duration = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping BMP tables - END (PID: %u RID: %u TABLES: %u ENTRIES: %" PRIu64 " ET: %u) ***\n", config.name, bms->log_str, dumper_pid, pdr->id, tables_num, dump_elems, duration); return FALSE; } #if defined WITH_RABBITMQ void bmp_daemon_msglog_init_amqp_host() { p_amqp_init_host(&bmp_daemon_msglog_amqp_host); if (!config.bmp_daemon_msglog_amqp_user) config.bmp_daemon_msglog_amqp_user = rabbitmq_user; if (!config.bmp_daemon_msglog_amqp_passwd) config.bmp_daemon_msglog_amqp_passwd = rabbitmq_pwd; if (!config.bmp_daemon_msglog_amqp_exchange) config.bmp_daemon_msglog_amqp_exchange = default_amqp_exchange; if (!config.bmp_daemon_msglog_amqp_exchange_type) config.bmp_daemon_msglog_amqp_exchange_type = default_amqp_exchange_type; if (!config.bmp_daemon_msglog_amqp_host) config.bmp_daemon_msglog_amqp_host = default_amqp_host; if (!config.bmp_daemon_msglog_amqp_vhost) config.bmp_daemon_msglog_amqp_vhost = default_amqp_vhost; if (!config.bmp_daemon_msglog_amqp_retry) config.bmp_daemon_msglog_amqp_retry = AMQP_DEFAULT_RETRY; p_amqp_set_user(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_user); p_amqp_set_passwd(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_passwd); p_amqp_set_exchange(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_exchange); p_amqp_set_exchange_type(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_exchange_type); p_amqp_set_host(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_host); p_amqp_set_vhost(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_vhost); p_amqp_set_persistent_msg(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_persistent_msg); p_amqp_set_frame_max(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_frame_max); p_amqp_set_content_type_json(&bmp_daemon_msglog_amqp_host); p_amqp_set_heartbeat_interval(&bmp_daemon_msglog_amqp_host, config.bmp_daemon_msglog_amqp_heartbeat_interval); P_broker_timers_set_retry_interval(&bmp_daemon_msglog_amqp_host.btimers, config.bmp_daemon_msglog_amqp_retry); } #else void bmp_daemon_msglog_init_amqp_host() { } #endif #if defined WITH_RABBITMQ void bmp_dump_init_amqp_host(void *bdah) { struct p_amqp_host *bmp_dump_amqp_host = bdah; p_amqp_init_host(bmp_dump_amqp_host); if (!config.bmp_dump_amqp_user) config.bmp_dump_amqp_user = rabbitmq_user; if (!config.bmp_dump_amqp_passwd) config.bmp_dump_amqp_passwd = rabbitmq_pwd; if (!config.bmp_dump_amqp_exchange) config.bmp_dump_amqp_exchange = default_amqp_exchange; if (!config.bmp_dump_amqp_exchange_type) config.bmp_dump_amqp_exchange_type = default_amqp_exchange_type; if (!config.bmp_dump_amqp_host) config.bmp_dump_amqp_host = default_amqp_host; if (!config.bmp_dump_amqp_vhost) config.bmp_dump_amqp_vhost = default_amqp_vhost; p_amqp_set_user(bmp_dump_amqp_host, config.bmp_dump_amqp_user); p_amqp_set_passwd(bmp_dump_amqp_host, config.bmp_dump_amqp_passwd); p_amqp_set_exchange(bmp_dump_amqp_host, config.bmp_dump_amqp_exchange); p_amqp_set_exchange_type(bmp_dump_amqp_host, config.bmp_dump_amqp_exchange_type); p_amqp_set_host(bmp_dump_amqp_host, config.bmp_dump_amqp_host); p_amqp_set_vhost(bmp_dump_amqp_host, config.bmp_dump_amqp_vhost); p_amqp_set_persistent_msg(bmp_dump_amqp_host, config.bmp_dump_amqp_persistent_msg); p_amqp_set_frame_max(bmp_dump_amqp_host, config.bmp_dump_amqp_frame_max); p_amqp_set_content_type_json(bmp_dump_amqp_host); p_amqp_set_heartbeat_interval(bmp_dump_amqp_host, config.bmp_dump_amqp_heartbeat_interval); } #else void bmp_dump_init_amqp_host(void *bdah) { } #endif #if defined WITH_KAFKA int bmp_daemon_msglog_init_kafka_host() { int ret; p_kafka_init_host(&bmp_daemon_msglog_kafka_host, config.bmp_daemon_msglog_kafka_config_file); ret = p_kafka_connect_to_produce(&bmp_daemon_msglog_kafka_host); if (!config.bmp_daemon_msglog_kafka_broker_host) config.bmp_daemon_msglog_kafka_broker_host = default_kafka_broker_host; if (!config.bmp_daemon_msglog_kafka_broker_port) config.bmp_daemon_msglog_kafka_broker_port = default_kafka_broker_port; if (!config.bmp_daemon_msglog_kafka_retry) config.bmp_daemon_msglog_kafka_retry = PM_KAFKA_DEFAULT_RETRY; p_kafka_set_broker(&bmp_daemon_msglog_kafka_host, config.bmp_daemon_msglog_kafka_broker_host, config.bmp_daemon_msglog_kafka_broker_port); p_kafka_set_topic(&bmp_daemon_msglog_kafka_host, config.bmp_daemon_msglog_kafka_topic); p_kafka_set_partition(&bmp_daemon_msglog_kafka_host, config.bmp_daemon_msglog_kafka_partition); p_kafka_set_key(&bmp_daemon_msglog_kafka_host, config.bmp_daemon_msglog_kafka_partition_key, config.bmp_daemon_msglog_kafka_partition_keylen); p_kafka_set_content_type(&bmp_daemon_msglog_kafka_host, PM_KAFKA_CNT_TYPE_STR); P_broker_timers_set_retry_interval(&bmp_daemon_msglog_kafka_host.btimers, config.bmp_daemon_msglog_kafka_retry); #ifdef WITH_SERDES P_broker_timers_set_retry_interval(&bmp_daemon_msglog_kafka_host.sd_schema_timers, config.bmp_daemon_msglog_kafka_retry); #endif return ret; } #else int bmp_daemon_msglog_init_kafka_host() { return ERR; } #endif #if defined WITH_KAFKA int bmp_dump_init_kafka_host(void *bmkh) { struct p_kafka_host *bmp_dump_kafka_host = bmkh; int ret; p_kafka_init_host(bmp_dump_kafka_host, config.bmp_dump_kafka_config_file); ret = p_kafka_connect_to_produce(bmp_dump_kafka_host); if (!config.bmp_dump_kafka_broker_host) config.bmp_dump_kafka_broker_host = default_kafka_broker_host; if (!config.bmp_dump_kafka_broker_port) config.bmp_dump_kafka_broker_port = default_kafka_broker_port; p_kafka_set_broker(bmp_dump_kafka_host, config.bmp_dump_kafka_broker_host, config.bmp_dump_kafka_broker_port); p_kafka_set_topic(bmp_dump_kafka_host, config.bmp_dump_kafka_topic); p_kafka_set_partition(bmp_dump_kafka_host, config.bmp_dump_kafka_partition); p_kafka_set_key(bmp_dump_kafka_host, config.bmp_dump_kafka_partition_key, config.bmp_dump_kafka_partition_keylen); p_kafka_set_content_type(bmp_dump_kafka_host, PM_KAFKA_CNT_TYPE_STR); return ret; } #else int bmp_dump_init_kafka_host(void *bmkh) { return ERR; } #endif #if defined WITH_AVRO avro_schema_t p_avro_schema_build_bmp_rm(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_LOG && log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BMP); p_avro_schema_build_bgp_route(&schema, &optlong_s, &optstr_s, &optint_s); /* also cherry-picking from avro_schema_build_bmp_common() */ avro_schema_record_field_append(schema, "peer_ip", avro_schema_string()); avro_schema_record_field_append(schema, "peer_tcp_port", optint_s); avro_schema_record_field_append(schema, "timestamp_arrival", optstr_s); avro_schema_record_field_append(schema, "bmp_router", avro_schema_string()); avro_schema_record_field_append(schema, "bmp_router_port", optint_s); avro_schema_record_field_append(schema, "bmp_msg_type", avro_schema_string()); avro_schema_record_field_append(schema, "is_in", optint_s); avro_schema_record_field_append(schema, "is_filtered", optint_s); avro_schema_record_field_append(schema, "is_loc", optint_s); avro_schema_record_field_append(schema, "is_post", optint_s); avro_schema_record_field_append(schema, "is_out", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_init(char *schema_name) { char *type = NULL; struct bmp_log_tlv dummy_tlv; avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); memset(&dummy_tlv, 0, sizeof(dummy_tlv)); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); dummy_tlv.type = BMP_INIT_INFO_STRING; type = bmp_tlv_type_print(&dummy_tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); dummy_tlv.type = BMP_INIT_INFO_SYSDESCR; type = bmp_tlv_type_print(&dummy_tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); dummy_tlv.type = BMP_INIT_INFO_SYSNAME; type = bmp_tlv_type_print(&dummy_tlv, "bmp_init_info", bmp_init_info_types, BMP_INIT_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_term(char *schema_name) { char *type = NULL; struct bmp_log_tlv dummy_tlv; avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); memset(&dummy_tlv, 0, sizeof(dummy_tlv)); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); dummy_tlv.type = BMP_TERM_INFO_STRING; type = bmp_tlv_type_print(&dummy_tlv, "bmp_term_info", bmp_term_info_types, BMP_TERM_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); dummy_tlv.type = BMP_TERM_INFO_REASON; type = bmp_tlv_type_print(&dummy_tlv, "bmp_term_info", bmp_term_info_types, BMP_TERM_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_peer_up(char *schema_name) { char *type = NULL; struct bmp_log_tlv dummy_tlv; avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); memset(&dummy_tlv, 0, sizeof(dummy_tlv)); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); avro_schema_record_field_append(schema, "peer_ip", avro_schema_string()); avro_schema_record_field_append(schema, "peer_asn", avro_schema_long()); avro_schema_record_field_append(schema, "peer_type", avro_schema_int()); avro_schema_record_field_append(schema, "peer_type_str", optstr_s); avro_schema_record_field_append(schema, "is_in", optint_s); avro_schema_record_field_append(schema, "is_filtered", optint_s); avro_schema_record_field_append(schema, "is_loc", optint_s); avro_schema_record_field_append(schema, "is_post", optint_s); avro_schema_record_field_append(schema, "is_out", optint_s); avro_schema_record_field_append(schema, "rd", optstr_s); avro_schema_record_field_append(schema, "rd_origin", optstr_s); avro_schema_record_field_append(schema, "bgp_id", avro_schema_string()); avro_schema_record_field_append(schema, "local_port", avro_schema_int()); avro_schema_record_field_append(schema, "remote_port", avro_schema_int()); avro_schema_record_field_append(schema, "local_ip", avro_schema_string()); dummy_tlv.type = BMP_PEER_UP_INFO_STRING; type = bmp_tlv_type_print(&dummy_tlv, "bmp_peer_up_info", bmp_peer_up_info_types, BMP_PEER_UP_INFO_MAX); avro_schema_record_field_append(schema, type, optstr_s); free(type); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_peer_down(char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); avro_schema_record_field_append(schema, "peer_ip", avro_schema_string()); avro_schema_record_field_append(schema, "peer_asn", avro_schema_long()); avro_schema_record_field_append(schema, "peer_type", avro_schema_int()); avro_schema_record_field_append(schema, "peer_type_str", optstr_s); avro_schema_record_field_append(schema, "rd", optstr_s); avro_schema_record_field_append(schema, "rd_origin", optstr_s); avro_schema_record_field_append(schema, "reason_type", avro_schema_int()); avro_schema_record_field_append(schema, "reason_str", optstr_s); avro_schema_record_field_append(schema, "reason_loc_code", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_stats(char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bmp_common(&schema, &optlong_s, &optstr_s, &optint_s); avro_schema_record_field_append(schema, "peer_ip", avro_schema_string()); avro_schema_record_field_append(schema, "peer_asn", avro_schema_long()); avro_schema_record_field_append(schema, "peer_type", avro_schema_int()); avro_schema_record_field_append(schema, "peer_type_str", avro_schema_string()); avro_schema_record_field_append(schema, "is_in", optint_s); avro_schema_record_field_append(schema, "is_filtered", optint_s); avro_schema_record_field_append(schema, "is_loc", optint_s); avro_schema_record_field_append(schema, "is_post", optint_s); avro_schema_record_field_append(schema, "is_out", optint_s); avro_schema_record_field_append(schema, "rd", optstr_s); avro_schema_record_field_append(schema, "rd_origin", optstr_s); avro_schema_record_field_append(schema, "counter_type", avro_schema_int()); avro_schema_record_field_append(schema, "counter_type_str", avro_schema_string()); avro_schema_record_field_append(schema, "counter_value", avro_schema_long()); avro_schema_record_field_append(schema, "afi", optint_s); avro_schema_record_field_append(schema, "safi", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_log_initclose(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_LOG) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); /* prevent log_type from being added to Avro schema */ log_type = BGP_LOGDUMP_ET_NONE; p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BMP); log_type = BGP_LOGDUMP_ET_LOG; avro_schema_record_field_append(schema, "bmp_router", avro_schema_string()); avro_schema_record_field_append(schema, "bmp_router_port", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_dump_init(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BMP); avro_schema_record_field_append(schema, "bmp_router", avro_schema_string()); avro_schema_record_field_append(schema, "bmp_router_port", optint_s); avro_schema_record_field_append(schema, "dump_period", avro_schema_long()); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } avro_schema_t p_avro_schema_build_bmp_dump_close(int log_type, char *schema_name) { avro_schema_t schema = NULL; avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); avro_schema_t optint_s = avro_schema_union(); if (log_type != BGP_LOGDUMP_ET_DUMP) return NULL; p_avro_schema_init_bgp(&schema, &optlong_s, &optstr_s, &optint_s, FUNC_TYPE_BMP, schema_name); p_avro_schema_build_bgp_common(&schema, &optlong_s, &optstr_s, &optint_s, log_type, FUNC_TYPE_BMP); avro_schema_record_field_append(schema, "bmp_router", avro_schema_string()); avro_schema_record_field_append(schema, "bmp_router_port", optint_s); avro_schema_record_field_append(schema, "entries", optlong_s); avro_schema_record_field_append(schema, "tables", optint_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); avro_schema_decref(optint_s); return schema; } void p_avro_schema_build_bmp_common(avro_schema_t *schema, avro_schema_t *optlong_s, avro_schema_t *optstr_s, avro_schema_t *optint_s) { avro_schema_record_field_append((*schema), "seq", avro_schema_long()); avro_schema_record_field_append((*schema), "timestamp", avro_schema_string()); avro_schema_record_field_append((*schema), "timestamp_event", (*optstr_s)); avro_schema_record_field_append((*schema), "timestamp_arrival", (*optstr_s)); avro_schema_record_field_append((*schema), "event_type", avro_schema_string()); avro_schema_record_field_append((*schema), "bmp_router", avro_schema_string()); avro_schema_record_field_append((*schema), "bmp_router_port", (*optint_s)); avro_schema_record_field_append((*schema), "bmp_msg_type", avro_schema_string()); avro_schema_record_field_append((*schema), "writer_id", avro_schema_string()); if (config.bmp_daemon_tag_map) { avro_schema_record_field_append((*schema), "tag", (*optlong_s)); if (config.pretag_label_encode_as_map) { compose_label_avro_schema_opt((*schema)); } else { avro_schema_record_field_append((*schema), "label", (*optstr_s)); } } } #endif pmacct-1.7.8/src/bmp/bmp_msg.h0000644000175000017500000000701314354105275015155 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_MSG_H #define BMP_MSG_H /* includes */ /* defines */ /* prototypes */ extern u_int32_t bmp_process_packet(char *, u_int32_t, struct bmp_peer *, int *); extern void bmp_process_msg_init(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_term(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_peer_up(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_peer_down(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_stats(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_route_monitor(char **, u_int32_t *, struct bmp_peer *); extern void bmp_process_msg_route_mirror(char **, u_int32_t *, struct bmp_peer *); extern void bmp_common_hdr_get_len(struct bmp_common_hdr *, u_int32_t *); extern void bmp_tlv_hdr_get_type(struct bmp_tlv_hdr *, u_int16_t *); extern void bmp_tlv_hdr_get_len(struct bmp_tlv_hdr *, u_int16_t *); extern void bmp_term_hdr_get_reason_type(char **, u_int32_t *, u_int16_t *); extern void bmp_peer_hdr_get_v_flag(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_hdr_get_l_flag(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_hdr_get_a_flag(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_hdr_get_f_flag(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_hdr_get_o_flag(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_hdr_get_peer_ip(struct bmp_peer_hdr *, struct host_addr *, u_int8_t *); extern void bmp_peer_hdr_get_bgp_id(struct bmp_peer_hdr *, struct host_addr *); extern void bmp_peer_hdr_get_rd(struct bmp_peer_hdr *, rd_t *); extern void bmp_peer_hdr_get_tstamp(struct bmp_peer_hdr *, struct timeval *); extern void bmp_peer_hdr_get_peer_asn(struct bmp_peer_hdr *, u_int32_t *); extern void bmp_peer_hdr_get_peer_type(struct bmp_peer_hdr *, u_int8_t *); extern void bmp_peer_up_hdr_get_local_ip(struct bmp_peer_up_hdr *, struct host_addr *, u_int8_t); extern void bmp_peer_up_hdr_get_loc_port(struct bmp_peer_up_hdr *, u_int16_t *); extern void bmp_peer_up_hdr_get_rem_port(struct bmp_peer_up_hdr *, u_int16_t *); extern void bmp_peer_down_hdr_get_reason(struct bmp_peer_down_hdr *, u_char *); extern void bmp_peer_down_hdr_get_loc_code(char **, u_int32_t *, u_int16_t *); extern void bmp_stats_hdr_get_count(struct bmp_stats_hdr *, u_int32_t *); extern void bmp_stats_cnt_hdr_get_type(struct bmp_stats_cnt_hdr *, u_int16_t *); extern void bmp_stats_cnt_hdr_get_len(struct bmp_stats_cnt_hdr *, u_int16_t *); extern void bmp_stats_cnt_get_data32(char **, u_int32_t *, u_int32_t *); extern void bmp_stats_cnt_get_data64(char **, u_int32_t *, u_int64_t *); extern void bmp_stats_cnt_get_afi_safi_data64(char **, u_int32_t *, afi_t *, safi_t *, u_int64_t *); #endif //BMP_MSG_H pmacct-1.7.8/src/bmp/bmp.h0000644000175000017500000003137514354105275014317 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_H #define BMP_H /* includes */ /* defines */ #define BMP_TCP_PORT 1790 #define BMP_MAX_PEERS_DEFAULT 4 #define BMP_V3 3 #define BMP_V4 4 #define BMP_CMN_HDRLEN 5 #define BMP_PEER_HDRLEN 42 #define BMP_MISSING_PEER_UP_LOG_TOUT 60 /* BMP message types */ #define BMP_MSG_ROUTE_MONITOR 0 #define BMP_MSG_STATS 1 #define BMP_MSG_PEER_DOWN 2 #define BMP_MSG_PEER_UP 3 #define BMP_MSG_INIT 4 #define BMP_MSG_TERM 5 #define BMP_MSG_ROUTE_MIRROR 6 #define BMP_MSG_TMP_RPAT 100 #define BMP_MSG_TYPE_MAX 100 /* set to the highest BMP_MSG_* value */ static const char __attribute__((unused)) *bmp_msg_types[] = { "Route Monitoring", "Statistics Report", "Peer Down Notification", "Peer Up Notification", "Initiation Message", "Termination Message", "Route Mirroring", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "RPAT" }; struct bmp_common_hdr { u_char version; u_int32_t len; u_char type; } __attribute__ ((packed)); #define BMP_PEER_TYPE_GLOBAL 0 #define BMP_PEER_TYPE_L3VPN 1 #define BMP_PEER_TYPE_LOCAL 2 #define BMP_PEER_TYPE_LOC_RIB 3 /* draft-ietf-grow-bmp-local-rib */ #define BMP_PEER_TYPE_MAX 3 /* set to the highest BMP_PEER_TYPE_* value */ static const char __attribute__((unused)) *bmp_peer_types[] = { "Global Instance Peer", "RD Instance Peer", "Local Instance Peer", "Loc-RIB Instance Peer" }; #define BMP_PEER_FLAGS_ARI_V 0x80 #define BMP_PEER_FLAGS_ARI_L 0x40 #define BMP_PEER_FLAGS_ARI_A 0x20 #define BMP_PEER_FLAGS_LR_F 0x80 /* draft-ietf-grow-bmp-local-rib */ #define BMP_PEER_FLAGS_ARO_O 0x10 /* rfc8671 */ struct bmp_chars { /* key */ u_int8_t peer_type; u_int8_t is_post; u_int8_t is_2b_asn; u_int8_t is_filtered; u_int8_t is_out; u_int8_t is_loc; rd_t rd; /* non-key */ struct pm_list *tlvs; }; struct bmp_data { u_int8_t family; struct host_addr peer_ip; struct host_addr bgp_id; u_int32_t peer_asn; struct bmp_chars chars; struct timeval tstamp; struct timeval tstamp_arrival; }; struct bmp_peer_hdr { u_char type; u_char flags; u_char rd[RD_LEN]; u_int32_t addr[4]; u_int32_t asn; u_int32_t bgp_id; u_int32_t tstamp_sec; u_int32_t tstamp_usec; } __attribute__ ((packed)); struct bmp_tlv_hdr { u_int16_t type; u_int16_t len; } __attribute__ ((packed)); #define BMP_TLV_EBIT 0x8000 /* BMP TLV enterprise bit */ #define BMP_TLV_PEN_STD 0 /* PEN for standardized TLVs */ typedef int (*bmp_logdump_func)(struct bgp_peer *, struct bmp_data *, void *, void *, char *, int, void *); struct bmp_tlv_def { char *name; int semantics; bmp_logdump_func logdump_func; }; #define BMP_TLV_SEM_UNKNOWN CUSTOM_PRIMITIVE_TYPE_UNKNOWN #define BMP_TLV_SEM_UINT CUSTOM_PRIMITIVE_TYPE_UINT #define BMP_TLV_SEM_HEX CUSTOM_PRIMITIVE_TYPE_HEX #define BMP_TLV_SEM_STRING CUSTOM_PRIMITIVE_TYPE_STRING #define BMP_TLV_SEM_IP CUSTOM_PRIMITIVE_TYPE_IP #define BMP_TLV_SEM_MAC CUSTOM_PRIMITIVE_TYPE_MAC #define BMP_TLV_SEM_RAW CUSTOM_PRIMITIVE_TYPE_RAW #define BMP_TLV_SEM_COMPLEX CUSTOM_PRIMITIVE_TYPE_COMPLEX #define BMP_INIT_INFO_STRING 0 #define BMP_INIT_INFO_SYSDESCR 1 #define BMP_INIT_INFO_SYSNAME 2 #define BMP_INIT_INFO_MAX 2 #define BMP_INIT_INFO_ENTRIES 8 static const struct bmp_tlv_def __attribute__((unused)) bmp_init_info_types[] = { { "string", BMP_TLV_SEM_STRING, NULL }, { "sysdescr", BMP_TLV_SEM_STRING, NULL }, { "sysname", BMP_TLV_SEM_STRING, NULL } }; #define BMP_TERM_INFO_STRING 0 #define BMP_TERM_INFO_REASON 1 #define BMP_TERM_INFO_MAX 1 #define BMP_TERM_INFO_ENTRIES 8 #define BMP_TERM_REASON_ADM 0 #define BMP_TERM_REASON_UNK 1 #define BMP_TERM_REASON_OOR 2 #define BMP_TERM_REASON_DUP 3 #define BMP_TERM_REASON_PERM 4 #define BMP_TERM_REASON_MAX 4 /* set to the highest BMP_TERM_* value */ static const struct bmp_tlv_def __attribute__((unused)) bmp_term_info_types[] = { { "string", BMP_TLV_SEM_STRING, NULL }, { "reason", BMP_TLV_SEM_UINT, NULL } }; static const char __attribute__((unused)) *bmp_term_reason_types[] = { "Session administratively closed", "Unspecified reason", "Out of resources", "Redundant connection", "Session permanently administratively closed" }; struct bmp_stats_hdr { u_int32_t count; } __attribute__ ((packed)); struct bmp_peer { struct bgp_peer self; void *bgp_peers_v4; void *bgp_peers_v6; struct log_notification missing_peer_up; }; #define BMP_STATS_TYPE0 0 /* (32-bit Counter) Number of prefixes rejected by inbound policy */ #define BMP_STATS_TYPE1 1 /* (32-bit Counter) Number of (known) duplicate prefix advertisements */ #define BMP_STATS_TYPE2 2 /* (32-bit Counter) Number of (known) duplicate withdraws */ #define BMP_STATS_TYPE3 3 /* (32-bit Counter) Number of updates invalidated due to CLUSTER_LIST loop */ #define BMP_STATS_TYPE4 4 /* (32-bit Counter) Number of updates invalidated due to AS_PATH loop */ #define BMP_STATS_TYPE5 5 /* (32-bit Counter) Number of updates invalidated due to ORIGINATOR_ID */ #define BMP_STATS_TYPE6 6 /* (32-bit Counter) Number of updates invalidated due to AS_CONFED loop */ #define BMP_STATS_TYPE7 7 /* (64-bit Gauge) Number of routes in Adj-RIB-In */ #define BMP_STATS_TYPE8 8 /* (64-bit Gauge) Number of routes in Loc-RIB */ #define BMP_STATS_TYPE9 9 /* (64-bit Gauge) Number of routes in per-AFI/SAFI Abj-RIB-In */ #define BMP_STATS_TYPE10 10 /* (64-bit Gauge) Number of routes in per-AFI/SAFI Loc-RIB */ #define BMP_STATS_TYPE11 11 /* (32-bit Counter) Number of updates subjected to treat-as-withdraw */ #define BMP_STATS_TYPE12 12 /* (32-bit Counter) Number of prefixes subjected to treat-as-withdraw */ #define BMP_STATS_TYPE13 13 /* (32-bit Counter) Number of duplicate update messages received */ #define BMP_STATS_TYPE14 14 /* (64-bit Gauge) Number of routes in Adj-RIBs-Out Pre-Policy */ #define BMP_STATS_TYPE15 15 /* (64-bit Gauge) Number of routes in Adj-RIBs-Out Post-Policy */ #define BMP_STATS_TYPE16 16 /* (64-bit Gauge) Number of routes in per-AFI/SAFI Abj-RIB-Out */ #define BMP_STATS_TYPE17 17 /* (64-bit Gauge) Number of routes in per-AFI/SAFI Abj-RIB-Out */ #define BMP_STATS_MAX 17 /* set to the highest BMP_STATS_* value */ /* dummy */ static const struct bmp_tlv_def __attribute__((unused)) bmp_stats_info_types[] = { { "", BMP_TLV_SEM_UNKNOWN, NULL } }; #define BMP_STATS_INFO_MAX -1 static const char __attribute__((unused)) *bmp_stats_cnt_types[] = { "Number of prefixes rejected by inbound policy", "Number of (known) duplicate prefix advertisements", "Number of (known) duplicate withdraws", "Number of updates invalidated due to CLUSTER_LIST loop", "Number of updates invalidated due to AS_PATH loop", "Number of updates invalidated due to ORIGINATOR_ID", "Number of updates invalidated due to AS_CONFED loop", "Number of routes in Adj-RIBs-In", "Number of routes in Loc-RIB", "Number of routes in per-AFI/SAFI Abj-RIB-In", "Number of routes in per-AFI/SAFI Loc-RIB", "Number of updates subjected to treat-as-withdraw", "Number of prefixes subjected to treat-as-withdraw", "Number of duplicate update messages received", "Number of routes in Adj-RIBs-Out Pre-Policy", "Number of routes in Adj-RIBs-Out Post-Policy", "Number of routes in per-AFI/SAFI Abj-RIB-Out Pre-Policy", "Number of routes in per-AFI/SAFI Abj-RIB-Out Post-Policy" }; struct bmp_stats_cnt_hdr { u_int16_t type; u_int16_t len; } __attribute__ ((packed)); static const struct bmp_tlv_def __attribute__((unused)) bmp_peer_up_info_types[] = { { "string", BMP_TLV_SEM_STRING, NULL } }; #define BMP_PEER_UP_INFO_STRING 0 #define BMP_PEER_UP_INFO_MAX 0 #define BMP_PEER_UP_INFO_ENTRIES 8 #define BMP_PEER_DOWN_RESERVED 0 #define BMP_PEER_DOWN_LOC_NOT_MSG 1 #define BMP_PEER_DOWN_LOC_CODE 2 #define BMP_PEER_DOWN_REM_NOT_MSG 3 #define BMP_PEER_DOWN_REM_CODE 4 #define BMP_PEER_DOWN_DECFG 5 #define BMP_PEER_DOWN_MAX 5 /* set to the highest BMP_PEER_DOWN_* value */ #define BMP_PEER_DOWN_INFO_MAX -1 #define BMP_PEER_DOWN_INFO_ENTRIES BMP_PEER_UP_INFO_ENTRIES static const char __attribute__((unused)) *bmp_peer_down_reason_types[] = { "Reserved", "The local system closed the session", "The local system closed the session without a notification message", "The remote system closed the session", "The remote system closed the session without a notification message", "Info for this peer will no longer be sent for configuration reasons" }; static const struct bmp_tlv_def __attribute__((unused)) bmp_peer_down_info_types[] = { { "", BMP_TLV_SEM_UNKNOWN } }; struct bmp_peer_down_hdr { u_char reason; } __attribute__ ((packed)); struct bmp_peer_up_hdr { u_int32_t loc_addr[4]; u_int16_t loc_port; u_int16_t rem_port; /* Sent OPEN Message */ /* Received OPEN Message */ } __attribute__ ((packed)); /* more includes */ #include "bmp_logdump.h" /* draft-cppy-grow-bmp-path-marking-tlv */ static const struct bmp_tlv_def __attribute__((unused)) bmp_rm_info_types[] = { { "path_marking", BMP_TLV_SEM_COMPLEX, bmp_log_rm_tlv_path_marking } }; #define BMP_ROUTE_MONITOR_INFO_MARKING 0 #define BMP_ROUTE_MONITOR_INFO_MAX 0 #define BMP_ROUTE_MONITOR_INFO_ENTRIES 4 struct bmp_rm_pm_tlv { u_int16_t path_index; u_int32_t path_status; u_int16_t reason_code; } __attribute__ ((packed)); #define BMP_RM_PM_PS_UNKNOWN 0x00000000 #define BMP_RM_PM_PS_INVALID 0x00000001 #define BMP_RM_PM_PS_BEST 0x00000002 #define BMP_RM_PM_PS_NO_SELECT 0x00000004 #define BMP_RM_PM_PS_PRIMARY 0x00000008 #define BMP_RM_PM_PS_BACKUP 0x00000010 #define BMP_RM_PM_PS_NO_INSTALL 0x00000020 #define BMP_RM_PM_PS_BEST_EXT 0x00000040 #define BMP_RM_PM_PS_ADD_PATH 0x00000080 static const char __attribute__((unused)) *bmp_rm_pm_reason_types[] = { "invalid for unknown", "invalid for super network", "invalid for dampening", "invalid for history", "invalid for policy deny", "invalid for ROA not validation", "invalid for interface error", "invalid for nexthop route unreachable", "invalid for nexthop tunnel unreachable", "invalid for nexthop restrain", "invalid for relay BGP LSP", "invalid for being inactive within VPN instance", "invalid for prefix-sid not exist", "not preferred for peer address", "not preferred for router ID", "not preferred for Cluster List", "not preferred for IGP cost", "not preferred for peer type", "not preferred for MED", "not preferred for origin", "not preferred for AS-Path", "not preferred for route type", "not preferred for Local_Pref", "not preferred for PreVal", "not preferred for not direct route", "not preferred for nexthop bit error", "not preferred for received path-id", "not preferred for validation", "not preferred for originate IP", "not preferred for route distinguisher", "not preferred for route-select delay", "not preferred for being imported route", "not preferred for med-plus-igp", "not preferred for AIGP", "not preferred for nexthop-resolved aigp", "not preferred for nexthop unreachable", "not preferred for nexthop IP", "not preferred for high-priority", "not preferred for nexthop-priority", "not preferred for process ID", "no reason code" }; /* more includes */ #include "bmp_msg.h" #include "bmp_util.h" #include "bmp_lookup.h" #include "bmp_tlv.h" #include "bmp_rpat.h" /* prototypes */ extern void bmp_daemon_wrapper(); extern int skinny_bmp_daemon(); extern void bmp_prepare_thread(); extern void bmp_prepare_daemon(); extern void bmp_daemon_msglog_prepare_sd_schemas(); /* global variables */ extern struct bmp_peer *bmp_peers; extern u_int32_t (*bmp_route_info_modulo)(struct bgp_peer *, path_id_t *, int); extern struct bgp_rt_structs *bmp_routing_db; extern struct bgp_misc_structs *bmp_misc_db; extern bgp_tag_t bmp_logdump_tag; extern struct sockaddr_storage bmp_logdump_tag_peer; #endif //BMP_H pmacct-1.7.8/src/bmp/bmp_rpat.h0000644000175000017500000001233214354105275015335 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_RPAT_H #define BMP_RPAT_H /* defines */ struct bmp_rpat_common_hdr { u_char flags; u_char rd[RD_LEN]; u_char prefix_len; u_int32_t prefix[4]; u_int32_t bgp_id; u_char events_count; u_int16_t events_length; } __attribute__ ((packed)); struct bmp_rpat_event_hdr { u_int16_t len; u_int8_t idx; u_int32_t tstamp_sec; u_int32_t tstamp_usec; u_int32_t path_id; u_int16_t afi; u_int8_t safi; } __attribute__ ((packed)); struct bmp_rpat_vrf_tlv_hdr { u_int32_t id; } __attribute__ ((packed)); struct bmp_rpat_policy_tlv_hdr { u_int8_t flag; u_int8_t count; u_int8_t class; u_int32_t peer_ip[4]; u_int32_t peer_bgp_id; u_int32_t peer_asn; } __attribute__ ((packed)); struct bmp_rpat_policy_hdr { u_int16_t name_len; u_int16_t id_len; } __attribute__ ((packed)); #define BMP_RPAT_POLICY_CLASS_INBOUND 0 #define BMP_RPAT_POLICY_CLASS_OUTBOUND 1 #define BMP_RPAT_POLICY_CLASS_MP_REDISTRIBUTE 2 #define BMP_RPAT_POLICY_CLASS_VRF_REDISTRIBUTE 3 #define BMP_RPAT_POLICY_CLASS_VRF_IMPORT 4 #define BMP_RPAT_POLICY_CLASS_VRF_EXPORT 5 #define BMP_RPAT_POLICY_CLASS_NETWORK 6 #define BMP_RPAT_POLICY_CLASS_AGGREGATION 7 #define BMP_RPAT_POLICY_CLASS_ROUTE_WITHDRAW 8 #define BMP_RPAT_POLICY_CLASS_MAX 8 static const char __attribute__((unused)) *bmp_rpat_class_types[] = { "Inbound policy", "Outbound policy", "Multi-protocol Redistribute", "Cross-VRF Redistribute", "VRF import", "VRF export", "Network", "Aggregation", "Route Withdraw" }; #define BMP_RPAT_POLICY_FLAG_M 0x80 #define BMP_RPAT_POLICY_FLAG_P 0x40 #define BMP_RPAT_POLICY_FLAG_D 0x20 #define BMP_RPAT_POLICY_NP_FLAG_C 0x80 #define BMP_RPAT_POLICY_NP_FLAG_R 0x40 struct bmp_log_rpat { struct host_addr prefix; u_int8_t prefix_len; u_int8_t event_idx; u_int32_t path_id; afi_t afi; safi_t safi; }; /* prototypes needed for bmp_tlv_def */ extern int bmp_log_msg_rpat_vrf(struct bgp_peer *, struct bmp_data *, void *, void *, char *, int, void *); extern int bmp_log_msg_rpat_policy(struct bgp_peer *, struct bmp_data *, void *, void *, char *, int, void *); static const struct bmp_tlv_def __attribute__((unused)) bmp_rpat_info_types[] = { { "vrf", BMP_TLV_SEM_COMPLEX, bmp_log_msg_rpat_vrf }, { "policy", BMP_TLV_SEM_COMPLEX, bmp_log_msg_rpat_policy }, { "pre_policy_attr", BMP_TLV_SEM_COMPLEX, NULL }, { "post_policy_attr", BMP_TLV_SEM_COMPLEX, NULL }, { "string", BMP_TLV_SEM_STRING, NULL } }; #define BMP_RPAT_INFO_VRF 0 #define BMP_RPAT_INFO_POLICY 1 #define BMP_RPAT_INFO_PRE_POLICY_ATTR 2 #define BMP_RPAT_INFO_POST_POLICY_ATTR 3 #define BMP_RPAT_INFO_STRING 4 #define BMP_RPAT_INFO_MAX 4 #define BMP_RPAT_INFO_ENTRIES 8 /* prototypes */ extern void bmp_process_msg_rpat(char **, u_int32_t *, struct bmp_peer *); extern void bmp_rpat_common_hdr_get_v_flag(struct bmp_rpat_common_hdr *, u_int8_t *); extern void bmp_rpat_common_hdr_get_bgp_id(struct bmp_rpat_common_hdr *, struct host_addr *); extern void bmp_rpat_common_hdr_get_rd(struct bmp_rpat_common_hdr *, rd_t *); extern void bmp_rpat_common_hdr_get_prefix(struct bmp_rpat_common_hdr *, struct host_addr *, u_int8_t *); extern void bmp_rpat_common_hdr_get_prefix_len(struct bmp_rpat_common_hdr *, u_int8_t *); extern void bmp_rpat_event_hdr_get_index(struct bmp_rpat_event_hdr *, u_int8_t *); extern void bmp_rpat_event_hdr_get_tstamp(struct bmp_rpat_event_hdr *, struct timeval *tv); extern void bmp_rpat_event_hdr_get_path_id(struct bmp_rpat_event_hdr *, u_int32_t *); extern void bmp_rpat_event_hdr_get_afi_safi(struct bmp_rpat_event_hdr *, afi_t *, safi_t *); extern void bmp_rpat_policy_tlv_get_m_flag(struct bmp_rpat_policy_tlv_hdr *, u_int8_t *); extern void bmp_rpat_policy_tlv_get_p_flag(struct bmp_rpat_policy_tlv_hdr *, u_int8_t *); extern void bmp_rpat_policy_tlv_get_d_flag(struct bmp_rpat_policy_tlv_hdr *, u_int8_t *); extern void bmp_rpat_policy_tlv_get_bgp_id(struct bmp_rpat_policy_tlv_hdr *, struct host_addr *); extern void bmp_rpat_policy_tlv_get_peer_ip(struct bmp_rpat_policy_tlv_hdr *, struct host_addr *, u_int8_t *); extern void bmp_rpat_policy_tlv_np_get_c_flag(u_int8_t *, u_int8_t *); extern void bmp_rpat_policy_tlv_np_get_r_flag(u_int8_t *, u_int8_t *); extern int bmp_log_msg_rpat(struct bgp_peer *, struct bmp_data *, struct pm_list *, struct bmp_log_rpat *, char *, int, void *); #ifdef WITH_AVRO extern avro_schema_t p_avro_schema_build_bmp_rpat(char *); #endif #endif //BMP_RPAT_H pmacct-1.7.8/src/bmp/Makefile.in0000644000175000017500000007254714354105415015437 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/bmp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmbmp_la_LIBADD = am_libpmbmp_la_OBJECTS = libpmbmp_la-bmp.lo libpmbmp_la-bmp_logdump.lo \ libpmbmp_la-bmp_msg.lo libpmbmp_la-bmp_util.lo \ libpmbmp_la-bmp_lookup.lo libpmbmp_la-bmp_tlv.lo \ libpmbmp_la-bmp_rpat.lo libpmbmp_la-bmp-globals.lo libpmbmp_la_OBJECTS = $(am_libpmbmp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmbmp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpmbmp_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmbmp_la-bmp-globals.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_logdump.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_lookup.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_msg.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_rpat.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_tlv.Plo \ ./$(DEPDIR)/libpmbmp_la-bmp_util.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmbmp_la_SOURCES) DIST_SOURCES = $(libpmbmp_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmbmp.la libpmbmp_la_SOURCES = bmp.c bmp_logdump.c bmp_msg.c bmp_util.c \ bmp_lookup.c bmp.h bmp_logdump.h bmp_msg.h bmp_util.h \ bmp_lookup.h bmp_tlv.c bmp_tlv.h bmp_rpat.c bmp_rpat.h \ bmp-globals.c libpmbmp_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/bmp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/bmp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmbmp.la: $(libpmbmp_la_OBJECTS) $(libpmbmp_la_DEPENDENCIES) $(EXTRA_libpmbmp_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmbmp_la_LINK) $(libpmbmp_la_OBJECTS) $(libpmbmp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp-globals.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_logdump.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_lookup.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_msg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_rpat.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_tlv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmbmp_la-bmp_util.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmbmp_la-bmp.lo: bmp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp.Tpo -c -o libpmbmp_la-bmp.lo `test -f 'bmp.c' || echo '$(srcdir)/'`bmp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp.Tpo $(DEPDIR)/libpmbmp_la-bmp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp.c' object='libpmbmp_la-bmp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp.lo `test -f 'bmp.c' || echo '$(srcdir)/'`bmp.c libpmbmp_la-bmp_logdump.lo: bmp_logdump.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_logdump.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_logdump.Tpo -c -o libpmbmp_la-bmp_logdump.lo `test -f 'bmp_logdump.c' || echo '$(srcdir)/'`bmp_logdump.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_logdump.Tpo $(DEPDIR)/libpmbmp_la-bmp_logdump.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_logdump.c' object='libpmbmp_la-bmp_logdump.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_logdump.lo `test -f 'bmp_logdump.c' || echo '$(srcdir)/'`bmp_logdump.c libpmbmp_la-bmp_msg.lo: bmp_msg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_msg.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_msg.Tpo -c -o libpmbmp_la-bmp_msg.lo `test -f 'bmp_msg.c' || echo '$(srcdir)/'`bmp_msg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_msg.Tpo $(DEPDIR)/libpmbmp_la-bmp_msg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_msg.c' object='libpmbmp_la-bmp_msg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_msg.lo `test -f 'bmp_msg.c' || echo '$(srcdir)/'`bmp_msg.c libpmbmp_la-bmp_util.lo: bmp_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_util.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_util.Tpo -c -o libpmbmp_la-bmp_util.lo `test -f 'bmp_util.c' || echo '$(srcdir)/'`bmp_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_util.Tpo $(DEPDIR)/libpmbmp_la-bmp_util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_util.c' object='libpmbmp_la-bmp_util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_util.lo `test -f 'bmp_util.c' || echo '$(srcdir)/'`bmp_util.c libpmbmp_la-bmp_lookup.lo: bmp_lookup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_lookup.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_lookup.Tpo -c -o libpmbmp_la-bmp_lookup.lo `test -f 'bmp_lookup.c' || echo '$(srcdir)/'`bmp_lookup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_lookup.Tpo $(DEPDIR)/libpmbmp_la-bmp_lookup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_lookup.c' object='libpmbmp_la-bmp_lookup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_lookup.lo `test -f 'bmp_lookup.c' || echo '$(srcdir)/'`bmp_lookup.c libpmbmp_la-bmp_tlv.lo: bmp_tlv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_tlv.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_tlv.Tpo -c -o libpmbmp_la-bmp_tlv.lo `test -f 'bmp_tlv.c' || echo '$(srcdir)/'`bmp_tlv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_tlv.Tpo $(DEPDIR)/libpmbmp_la-bmp_tlv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_tlv.c' object='libpmbmp_la-bmp_tlv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_tlv.lo `test -f 'bmp_tlv.c' || echo '$(srcdir)/'`bmp_tlv.c libpmbmp_la-bmp_rpat.lo: bmp_rpat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp_rpat.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp_rpat.Tpo -c -o libpmbmp_la-bmp_rpat.lo `test -f 'bmp_rpat.c' || echo '$(srcdir)/'`bmp_rpat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp_rpat.Tpo $(DEPDIR)/libpmbmp_la-bmp_rpat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp_rpat.c' object='libpmbmp_la-bmp_rpat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp_rpat.lo `test -f 'bmp_rpat.c' || echo '$(srcdir)/'`bmp_rpat.c libpmbmp_la-bmp-globals.lo: bmp-globals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -MT libpmbmp_la-bmp-globals.lo -MD -MP -MF $(DEPDIR)/libpmbmp_la-bmp-globals.Tpo -c -o libpmbmp_la-bmp-globals.lo `test -f 'bmp-globals.c' || echo '$(srcdir)/'`bmp-globals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmbmp_la-bmp-globals.Tpo $(DEPDIR)/libpmbmp_la-bmp-globals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmp-globals.c' object='libpmbmp_la-bmp-globals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmbmp_la_CFLAGS) $(CFLAGS) -c -o libpmbmp_la-bmp-globals.lo `test -f 'bmp-globals.c' || echo '$(srcdir)/'`bmp-globals.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmbmp_la-bmp-globals.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_logdump.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_lookup.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_msg.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_rpat.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_tlv.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_util.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmbmp_la-bmp-globals.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_logdump.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_lookup.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_msg.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_rpat.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_tlv.Plo -rm -f ./$(DEPDIR)/libpmbmp_la-bmp_util.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/bmp/bmp_lookup.c0000644000175000017500000001142314354105275015673 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" void bmp_srcdst_lookup(struct packet_ptrs *pptrs) { bgp_srcdst_lookup(pptrs, FUNC_TYPE_BMP); } struct bgp_peer *bgp_lookup_find_bmp_peer(struct sockaddr *sa, struct xflow_status_entry *xs_entry, u_int16_t l3_proto, int compare_bgp_port) { struct bgp_peer *peer; u_int32_t peer_idx, *peer_idx_ptr; int peers_idx; peer_idx = 0; peer_idx_ptr = NULL; if (xs_entry) { if (l3_proto == ETHERTYPE_IP) { peer_idx = xs_entry->peer_v4_idx; peer_idx_ptr = &xs_entry->peer_v4_idx; } else if (l3_proto == ETHERTYPE_IPV6) { peer_idx = xs_entry->peer_v6_idx; peer_idx_ptr = &xs_entry->peer_v6_idx; } } if (xs_entry && peer_idx) { if (!sa_addr_cmp(sa, &bmp_peers[peer_idx].self.addr) || !sa_addr_cmp(sa, &bmp_peers[peer_idx].self.id)) peer = &bmp_peers[peer_idx].self; /* If no match then let's invalidate the entry */ else { *peer_idx_ptr = 0; peer = NULL; } } else { for (peer = NULL, peers_idx = 0; peers_idx < config.bmp_daemon_max_peers; peers_idx++) { /* use-case #1: BMP peer being the edge router */ if (!sa_addr_cmp(sa, &bmp_peers[peers_idx].self.addr) || !sa_addr_cmp(sa, &bmp_peers[peers_idx].self.id)) { peer = &bmp_peers[peers_idx].self; if (xs_entry && peer_idx_ptr) *peer_idx_ptr = peers_idx; break; } /* use-case #2: BMP peer being the reflector; XXX: fix caching */ else { void *ret = NULL; if (sa->sa_family == AF_INET) { ret = pm_tfind(sa, &bmp_peers[peers_idx].bgp_peers_v4, bgp_peer_sa_addr_cmp); } else if (sa->sa_family == AF_INET6) { ret = pm_tfind(sa, &bmp_peers[peers_idx].bgp_peers_v6, bgp_peer_sa_addr_cmp); } if (ret) { peer = (*(struct bgp_peer **) ret); break; } } } } return peer; } u_int32_t bmp_route_info_modulo_pathid(struct bgp_peer *peer, path_id_t *path_id, int per_peer_buckets) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); struct bmp_peer *bmpp = peer->bmp_se; path_id_t local_path_id = 1; int fd = 0; if (path_id && *path_id) local_path_id = *path_id; if (peer->fd) fd = peer->fd; else { if (bmpp && bmpp->self.fd) fd = bmpp->self.fd; } return (((fd * per_peer_buckets) + ((local_path_id - 1) % per_peer_buckets)) % (bms->table_peer_buckets * per_peer_buckets)); } int bgp_lookup_node_match_cmp_bmp(struct bgp_info *info, struct node_match_cmp_term2 *nmct2) { struct bmp_peer *bmpp = info->peer->bmp_se; struct bgp_peer *peer_local = &bmpp->self; struct bgp_peer *peer_remote = info->peer; int no_match = FALSE, compare_rd = FALSE; /* peer_local: edge router use-case; peer_remote: replicator use-case */ if (peer_local == nmct2->peer || peer_remote == nmct2->peer) { if (nmct2->safi == SAFI_MPLS_VPN || !is_empty_256b(nmct2->rd, sizeof(rd_t))) { no_match++; compare_rd = TRUE; } if (nmct2->peer->cap_add_paths.cap[nmct2->afi][nmct2->safi]) no_match++; if (compare_rd) { /* RD typical location */ if (info->attr_extra && !memcmp(&info->attr_extra->rd, nmct2->rd, sizeof(rd_t))) { no_match--; } /* RD location when decoded from Peer Distinguisher */ else { if (info->bmed.id == BGP_MSG_EXTRA_DATA_BMP) { struct bmp_chars *bmed_bmp = (struct bmp_chars *) info->bmed.data; if (bmed_bmp && !memcmp(&bmed_bmp->rd, nmct2->rd, sizeof(rd_t))) { no_match--; } } } } if (nmct2->peer->cap_add_paths.cap[nmct2->afi][nmct2->safi]) { if (info->attr && nmct2->peer_dst_ip) { if (info->attr->mp_nexthop.family) { if (!host_addr_cmp(&info->attr->mp_nexthop, nmct2->peer_dst_ip)) { no_match--; } } else if (info->attr->nexthop.s_addr && nmct2->peer_dst_ip->family == AF_INET) { if (info->attr->nexthop.s_addr == nmct2->peer_dst_ip->address.ipv4.s_addr) { no_match--; } } } } if (!no_match) return FALSE; } return TRUE; } pmacct-1.7.8/src/bmp/bmp_tlv.h0000644000175000017500000000323114354105275015172 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_TLV_H #define BMP_TLV_H /* includes */ /* defines */ /* prototypes */ extern int bmp_tlv_handle_ebit(u_int16_t *); extern int bmp_tlv_get_pen(char **, u_int32_t *, u_int16_t *, u_int32_t *); extern char *bmp_tlv_type_print(struct bmp_log_tlv *, const char *, const struct bmp_tlv_def *, int); extern char *bmp_tlv_value_print(struct bmp_log_tlv *, const struct bmp_tlv_def *, int); extern struct pm_list *bmp_tlv_list_new(int (*cmp)(void *val1, void *val2), void (*del)(void *val)); extern int bmp_tlv_list_add(struct pm_list *, u_int32_t, u_int16_t, u_int16_t, char *); extern void bmp_tlv_list_node_del(void *node); extern struct pm_list *bmp_tlv_list_copy(struct pm_list *); extern void *bmp_tlv_list_find(struct pm_list *, struct pm_listnode *, u_int16_t); extern void bmp_tlv_list_destroy(struct pm_list *); #endif //BMP_TLV_H pmacct-1.7.8/src/bmp/Makefile.am0000644000175000017500000000046314354105275015416 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmbmp.la libpmbmp_la_SOURCES = bmp.c bmp_logdump.c bmp_msg.c bmp_util.c \ bmp_lookup.c bmp.h bmp_logdump.h bmp_msg.h bmp_util.h \ bmp_lookup.h bmp_tlv.c bmp_tlv.h bmp_rpat.c bmp_rpat.h \ bmp-globals.c libpmbmp_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/bmp/bmp_logdump.h0000644000175000017500000001102514354105275016034 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BMP_LOGDUMP_H_ #define _BMP_LOGDUMP_H_ /* defines */ #define BMP_LOG_TYPE_STATS BMP_MSG_STATS #define BMP_LOG_TYPE_INIT BMP_MSG_INIT #define BMP_LOG_TYPE_TERM BMP_MSG_TERM #define BMP_LOG_TYPE_PEER_UP BMP_MSG_PEER_UP #define BMP_LOG_TYPE_PEER_DOWN BMP_MSG_PEER_DOWN #define BMP_LOG_TYPE_ROUTE BMP_MSG_ROUTE_MONITOR #define BMP_LOG_TYPE_RPAT BMP_MSG_TMP_RPAT #define BMP_LOG_TYPE_LOGINIT BGP_LOG_TYPE_LOGINIT #define BMP_LOG_TYPE_LOGCLOSE BGP_LOG_TYPE_LOGCLOSE #define BMP_LOG_TYPE_DUMPINIT BGP_LOG_TYPE_DUMPINIT #define BMP_LOG_TYPE_DUMPCLOSE BGP_LOG_TYPE_DUMPCLOSE #define BMP_LOG_TYPE_MAX BGP_LOG_TYPE_DUMPCLOSE struct bmp_log_stats { u_int16_t cnt_type; afi_t cnt_afi; safi_t cnt_safi; u_int64_t cnt_data; }; struct bmp_log_tlv { u_int32_t pen; u_int16_t type; u_int16_t len; void *val; }; struct bmp_log_peer_up { struct host_addr local_ip; u_int16_t loc_port; u_int16_t rem_port; }; struct bmp_log_peer_down { u_char reason; u_int16_t loc_code; }; struct bmp_dump_se { struct bmp_data bdata; u_int64_t seq; int se_type; union { struct bmp_log_stats stats; struct bmp_log_peer_up peer_up; struct bmp_log_peer_down peer_down; } se; struct pm_list *tlvs; }; struct bmp_dump_se_ll_elem { struct bmp_dump_se rec; struct bmp_dump_se_ll_elem *next; }; struct bmp_dump_se_ll { struct bmp_dump_se_ll_elem *start; struct bmp_dump_se_ll_elem *last; }; /* prototypes */ extern void bmp_daemon_msglog_init_amqp_host(); extern void bmp_dump_init_peer(struct bgp_peer *); extern void bmp_dump_close_peer(struct bgp_peer *); extern int bmp_log_msg(struct bgp_peer *, struct bmp_data *, struct pm_list *tlvs, bgp_tag_t *, void *, u_int64_t, char *, int, int); extern int bmp_log_msg_stats(struct bgp_peer *, struct bmp_data *, struct pm_list *, struct bmp_log_stats *, char *, int, void *); extern int bmp_log_msg_init(struct bgp_peer *, struct bmp_data *, struct pm_list *, char *, int, void *); extern int bmp_log_msg_term(struct bgp_peer *, struct bmp_data *, struct pm_list *, char *, int, void *); extern int bmp_log_msg_peer_up(struct bgp_peer *, struct bmp_data *, struct pm_list *, struct bmp_log_peer_up *, char *, int, void *); extern int bmp_log_msg_peer_down(struct bgp_peer *, struct bmp_data *, struct pm_list *, struct bmp_log_peer_down *, char *, int, void *); extern int bmp_log_msg_route_monitor_tlv(struct pm_list *, int, void *); extern int bmp_log_rm_tlv_path_marking(struct bgp_peer *, struct bmp_data *, void *, void *, char *, int , void *); extern int bmp_log_rm_tlv_pm_status(u_int32_t, int, void *); extern void bmp_dump_se_ll_append(struct bgp_peer *, struct bmp_data *, struct pm_list *tlvs, void *, int); extern void bmp_dump_se_ll_destroy(struct bmp_dump_se_ll *); extern void bmp_handle_dump_event(int); extern int bmp_dump_event_runner(struct pm_dump_runner *); extern void bmp_daemon_msglog_init_amqp_host(); extern void bmp_dump_init_amqp_host(void *); extern int bmp_daemon_msglog_init_kafka_host(); extern int bmp_dump_init_kafka_host(void *); #if defined WITH_AVRO extern avro_schema_t p_avro_schema_build_bmp_rm(int, char *); extern avro_schema_t p_avro_schema_build_bmp_init(char *); extern avro_schema_t p_avro_schema_build_bmp_term(char *); extern avro_schema_t p_avro_schema_build_bmp_peer_up(char *); extern avro_schema_t p_avro_schema_build_bmp_peer_down(char *); extern avro_schema_t p_avro_schema_build_bmp_stats(char *); extern avro_schema_t p_avro_schema_build_bmp_log_initclose(int, char *); extern avro_schema_t p_avro_schema_build_bmp_dump_init(int, char *); extern avro_schema_t p_avro_schema_build_bmp_dump_close(int, char *); extern void p_avro_schema_build_bmp_common(avro_schema_t *, avro_schema_t *, avro_schema_t *, avro_schema_t *); #endif #endif pmacct-1.7.8/src/bmp/bmp_tlv.c0000644000175000017500000001152214354105275015167 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" int bmp_tlv_handle_ebit(u_int16_t *type) { if ((*type) & BMP_TLV_EBIT) { (*type) ^= BMP_TLV_EBIT; return TRUE; } else { return FALSE; } } int bmp_tlv_get_pen(char **bmp_packet_ptr, u_int32_t *pkt_size, u_int16_t *len, u_int32_t *pen) { char *pen_ptr = NULL; if (((*pkt_size) < (*len)) || ((*len) < 4)) return FALSE; pen_ptr = bmp_get_and_check_length(bmp_packet_ptr, pkt_size, 4); if (pen_ptr) { (*len) -= 4; memcpy(pen, pen_ptr, 4); (*pen) = ntohl((*pen)); return TRUE; } return FALSE; } char *bmp_tlv_type_print(struct bmp_log_tlv *tlv, const char *prefix, const struct bmp_tlv_def *registry, int max_registry_entries) { char *out = NULL; int prefix_len, value_len; u_int16_t idx; if (!tlv) return out; idx = tlv->type; prefix_len = strlen(prefix); if (registry && (max_registry_entries >= 0)) { if (idx <= max_registry_entries) { value_len = strlen(registry[idx].name); out = malloc(prefix_len + value_len + 1 /* sep */ + 1 /* null */); sprintf(out, "%s_%s", prefix, registry[idx].name); return out; } } if (!tlv->pen) { out = malloc(prefix_len + 5 /* value len */ + 1 /* sep */ + 1 /* null */); sprintf(out, "%s_%u", prefix, idx); } else { out = malloc(prefix_len + 10 /* PEN */ + 5 /* value len */ + 2 /* seps */ + 1 /* null */); sprintf(out, "%s_%u_%u", prefix, tlv->pen, idx); } return out; } char *bmp_tlv_value_print(struct bmp_log_tlv *tlv, const struct bmp_tlv_def *registry, int max_registry_entries) { u_int16_t idx = tlv->type; char *value = NULL; if (tlv->len) { if (registry && (max_registry_entries >= 0)) { if (idx <= max_registry_entries) { switch (registry[idx].semantics) { case BMP_TLV_SEM_STRING: value = null_terminate(tlv->val, tlv->len); return value; case BMP_TLV_SEM_UINT: value = uint_print(tlv->val, tlv->len, TRUE); return value; default: break; } } } value = malloc(tlv->len * 3); /* 2 bytes hex + 1 byte '-' separator + 1 byte null */ serialize_hex(tlv->val, (u_char *) value, tlv->len); } return value; } struct pm_list *bmp_tlv_list_new(int (*cmp)(void *val1, void *val2), void (*del)(void *val)) { struct pm_list *tlvs = NULL; tlvs = pm_list_new(); if (tlvs) { tlvs->cmp = cmp; tlvs->del = del; } return tlvs; } int bmp_tlv_list_add(struct pm_list *tlvs, u_int32_t pen, u_int16_t type, u_int16_t len, char *val) { struct bmp_log_tlv *tlv; if (!tlvs || (len && !val)) return ERR; tlv = malloc(sizeof(struct bmp_log_tlv)); if (!tlv) return ERR; memset(tlv, 0, sizeof(struct bmp_log_tlv)); tlv->pen = pen; tlv->type = type; tlv->len = len; if (len) { tlv->val = malloc(len); if (!tlv->val) { free(tlv); return ERR; }; memcpy(tlv->val, val, len); } else { tlv->val = NULL; } pm_listnode_add(tlvs, tlv); return SUCCESS; } void bmp_tlv_list_node_del(void *node) { struct bmp_log_tlv *tlv = NULL; tlv = (struct bmp_log_tlv *) node; if (tlv) { if (tlv->val) free(tlv->val); tlv->len = 0; tlv->val = NULL; free(tlv); } } struct pm_list *bmp_tlv_list_copy(struct pm_list *src) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; struct pm_list *dst = NULL; int ret; dst = bmp_tlv_list_new(NULL, bmp_tlv_list_node_del); for (PM_ALL_LIST_ELEMENTS_RO(src, node, tlv)) { ret = bmp_tlv_list_add(dst, tlv->pen, tlv->type, tlv->len, tlv->val); if (ret == ERR) { bmp_tlv_list_destroy(dst); dst = NULL; break; } } return dst; } void *bmp_tlv_list_find(struct pm_list *tlvs, struct pm_listnode *next_node, u_int16_t type) { struct pm_listnode *node = NULL; struct bmp_log_tlv *tlv = NULL; for (PM_ALL_LIST_ELEMENTS(tlvs, node, next_node, tlv)) { if (tlv->type == type) { return tlv; } } return NULL; } void bmp_tlv_list_destroy(struct pm_list *tlvs) { if (!tlvs) return; pm_list_delete(tlvs); } pmacct-1.7.8/src/bmp/bmp_util.h0000644000175000017500000000401714354105275015345 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BMP_UTIL_H #define BMP_UTIL_H /* includes */ /* defines */ /* prototypes */ extern char *bmp_get_and_check_length(char **, u_int32_t *, u_int32_t); extern int bmp_jump_offset(char **, u_int32_t *, u_int32_t); extern void bmp_link_misc_structs(struct bgp_misc_structs *); extern struct bgp_peer *bmp_sync_loc_rem_peers(struct bgp_peer *, struct bgp_peer *); extern int bmp_peer_init(struct bmp_peer *, int); extern void bmp_peer_close(struct bmp_peer *, int); extern char *bmp_term_reason_print(u_int16_t); extern void bgp_peer_log_msg_extras_bmp(struct bgp_peer *, int, int, int, void *); extern void bgp_msg_data_set_data_bmp(struct bmp_chars *, struct bmp_data *); extern int bgp_extra_data_cmp_bmp(struct bgp_msg_extra_data *, struct bgp_msg_extra_data *); extern int bgp_extra_data_process_bmp(struct bgp_msg_extra_data *, struct bgp_info *, int, int); extern void bgp_extra_data_free_bmp(struct bgp_msg_extra_data *); extern void bgp_extra_data_print_bmp(struct bgp_msg_extra_data *, int, void *); extern void encode_tstamp_arrival(char *, int, struct timeval *, int); extern char *decode_tstamp_arrival(char *); extern void bgp_table_info_delete_tag_find_bmp(struct bgp_peer *); #endif //BMP_UTIL_H pmacct-1.7.8/src/bmp/bmp-globals.c0000644000175000017500000000041114354105275015716 0ustar paolopaolo#include "pmacct.h" #include "bgp/bgp.h" #include "bmp.h" struct bmp_peer *bmp_peers = NULL; u_int32_t (*bmp_route_info_modulo)(struct bgp_peer *, path_id_t *, int) = NULL; struct bgp_rt_structs *bmp_routing_db = NULL; struct bgp_misc_structs *bmp_misc_db = NULL; pmacct-1.7.8/src/log.c0000644000175000017500000000634514354105275013536 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" /* Global variables */ struct _log_notifications log_notifications; /* functions */ void Log(short int level, char *msg, ...) { va_list ap; if ((level == LOG_DEBUG) && (!config.debug && !debug)) return; if (!config.syslog && !config.logfile_fd) { va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap); fflush(stderr); } else { if (config.syslog) { va_start(ap, msg); vsyslog(level, msg, ap); va_end(ap); } if (config.logfile_fd) { char timebuf[SRVBUFLEN]; struct tm *tmnow; time_t now; now = time(NULL); if (!config.timestamps_utc) tmnow = localtime(&now); else tmnow = gmtime(&now); strftime(timebuf, SRVBUFLEN, "%Y-%m-%dT%H:%M:%S", tmnow); append_rfc3339_timezone(timebuf, SRVBUFLEN, tmnow); fprintf(config.logfile_fd, "%s ", timebuf); va_start(ap, msg); vfprintf(config.logfile_fd, msg, ap); va_end(ap); fflush(config.logfile_fd); } } } int parse_log_facility(const char *facility) { int i; for (i = 0; facility_map[i].num != -1; i++) { if (!strcmp(facility, facility_map[i].string)) return facility_map[i].num; } return ERR; } void log_notification_init(struct log_notification *ln) { if (ln) { memset(ln, 0, sizeof(struct log_notification)); } } void log_notifications_init(struct _log_notifications *ln) { if (ln) { memset(ln, 0, sizeof(struct _log_notifications)); } } int log_notification_set(struct log_notification *ln, time_t now, int timeout) { if (ln) { ln->knob = TRUE; if (now) ln->stamp = now; else ln->stamp = time(NULL); ln->timeout = timeout; return SUCCESS; } else return ERR; } int log_notification_unset(struct log_notification *ln) { if (ln) { log_notification_init(ln); return SUCCESS; } else return ERR; } int log_notification_isset(struct log_notification *ln, time_t now) { time_t now_local; if (ln) { if (ln->timeout) { if (!now) now_local = time(NULL); else now_local = now; if (now_local < (ln->stamp + ln->timeout)) { /* valid */ if (ln->knob == TRUE) return TRUE; else return FALSE; } else { /* expired */ log_notification_unset(ln); return FALSE; } } else { if (ln->knob == TRUE) return TRUE; else return FALSE; } } return ERR; } pmacct-1.7.8/src/jhash.h0000644000175000017500000000662114354105275014054 0ustar paolopaolo#ifndef _LINUX_JHASH_H #define _LINUX_JHASH_H /* jhash.h: Jenkins hash support. * * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) * * http://burtleburtle.net/bob/hash/ * * These are the credits from Bob's sources: * * lookup2.c, by Bob Jenkins, December 1996, Public Domain. * hash(), hash2(), hash3, and mix() are externally useful functions. * Routines to test the hash are included if SELF_TEST is defined. * You can use this free for any purpose. It has no warranty. * * Copyright (C) 2003 David S. Miller (davem@redhat.com) * * I've modified Bob's hash to be useful in the Linux kernel, and * any bugs present are surely my fault. -DaveM */ /* NOTE: Arguments are modified. */ #define __jhash_mix(a, b, c) \ { \ a -= b; a -= c; a ^= (c>>13); \ b -= c; b -= a; b ^= (a<<8); \ c -= a; c -= b; c ^= (b>>13); \ a -= b; a -= c; a ^= (c>>12); \ b -= c; b -= a; b ^= (a<<16); \ c -= a; c -= b; c ^= (b>>5); \ a -= b; a -= c; a ^= (c>>3); \ b -= c; b -= a; b ^= (a<<10); \ c -= a; c -= b; c ^= (b>>15); \ } /* The golden ration: an arbitrary value */ #define JHASH_GOLDEN_RATIO 0x9e3779b9 /* The most generic version, hashes an arbitrary sequence * of bytes. No alignment or length assumptions are made about * the input key. */ static inline u_int32_t jhash(void *key, u_int32_t length, u_int32_t initval) { u_int32_t a, b, c, len; u_int8_t *k = key; len = length; a = b = JHASH_GOLDEN_RATIO; c = initval; while (len >= 12) { a += (k[0] +((u_int32_t)k[1]<<8) +((u_int32_t)k[2]<<16) +((u_int32_t)k[3]<<24)); b += (k[4] +((u_int32_t)k[5]<<8) +((u_int32_t)k[6]<<16) +((u_int32_t)k[7]<<24)); c += (k[8] +((u_int32_t)k[9]<<8) +((u_int32_t)k[10]<<16)+((u_int32_t)k[11]<<24)); __jhash_mix(a,b,c); k += 12; len -= 12; } c += length; switch (len) { case 11: c += ((u_int32_t)k[10]<<24); case 10: c += ((u_int32_t)k[9]<<16); case 9 : c += ((u_int32_t)k[8]<<8); case 8 : b += ((u_int32_t)k[7]<<24); case 7 : b += ((u_int32_t)k[6]<<16); case 6 : b += ((u_int32_t)k[5]<<8); case 5 : b += k[4]; case 4 : a += ((u_int32_t)k[3]<<24); case 3 : a += ((u_int32_t)k[2]<<16); case 2 : a += ((u_int32_t)k[1]<<8); case 1 : a += k[0]; }; __jhash_mix(a,b,c); return c; } /* A special optimized version that handles 1 or more of u_int32_ts. * The length parameter here is the number of u_int32_ts in the key. */ static inline u_int32_t jhash2(u_int32_t *k, u_int32_t length, u_int32_t initval) { u_int32_t a, b, c, len; a = b = JHASH_GOLDEN_RATIO; c = initval; len = length; while (len >= 3) { a += k[0]; b += k[1]; c += k[2]; __jhash_mix(a, b, c); k += 3; len -= 3; } c += length * 4; switch (len) { case 2 : b += k[1]; case 1 : a += k[0]; }; __jhash_mix(a,b,c); return c; } /* A special ultra-optimized versions that knows they are hashing exactly * 3, 2 or 1 word(s). * * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally * done at the end is not done here. */ static inline u_int32_t jhash_3words(u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t initval) { a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += initval; __jhash_mix(a, b, c); return c; } static inline u_int32_t jhash_2words(u_int32_t a, u_int32_t b, u_int32_t initval) { return jhash_3words(a, b, 0, initval); } static inline u_int32_t jhash_1word(u_int32_t a, u_int32_t initval) { return jhash_3words(a, 0, 0, initval); } #endif /* _LINUX_JHASH_H */ pmacct-1.7.8/src/zmq_common.h0000644000175000017500000001145214354105275015134 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include /* defines */ #define PLUGIN_PIPE_ZMQ_NONE 0 #define PLUGIN_PIPE_ZMQ_MICRO 1 #define PLUGIN_PIPE_ZMQ_SMALL 2 #define PLUGIN_PIPE_ZMQ_MEDIUM 3 #define PLUGIN_PIPE_ZMQ_LARGE 4 #define PLUGIN_PIPE_ZMQ_XLARGE 5 #define PLUGIN_PIPE_ZMQ_MICRO_SIZE 0 #define PLUGIN_PIPE_ZMQ_SMALL_SIZE 10000 #define PLUGIN_PIPE_ZMQ_MEDIUM_SIZE 100000 #define PLUGIN_PIPE_ZMQ_LARGE_SIZE 1000000 #define PLUGIN_PIPE_ZMQ_XLARGE_SIZE 10000000 #define PM_ZMQ_EVENTS_RETRIES 3 #define PM_ZMQ_DEFAULT_RETRY 1000 /* 1 sec */ #define PM_ZMQ_DEFAULT_FLOW_HWM 100000 /* ~150MB @ 1500 bytes/packet */ /* structures */ struct p_zmq_sock { void *obj; /* XXX: to be removed */ void *obj_tx; void *obj_rx; char str[SHORTBUFLEN]; }; struct p_zmq_zap { struct p_zmq_sock sock; void *thread; char username[SHORTBUFLEN]; char password[SHORTBUFLEN]; }; struct p_zmq_router_worker { void **threads; void (*func)(void *, void *); }; struct p_zmq_host { void *ctx; struct p_zmq_zap zap; char log_id[SHORTBUFLEN]; struct p_zmq_sock sock; struct p_zmq_sock sock_inproc; struct p_zmq_router_worker router_worker; u_int8_t topic; int hwm; }; /* prototypes */ extern void p_zmq_set_address(struct p_zmq_host *, char *); extern void p_zmq_set_topic(struct p_zmq_host *, u_int8_t); extern void p_zmq_set_retry_timeout(struct p_zmq_host *, int); extern void p_zmq_set_username(struct p_zmq_host *, char *); extern void p_zmq_set_password(struct p_zmq_host *, char *); extern void p_zmq_set_random_username(struct p_zmq_host *); extern void p_zmq_set_random_password(struct p_zmq_host *); extern void p_zmq_set_hwm(struct p_zmq_host *, int); extern void p_zmq_set_log_id(struct p_zmq_host *, char *); extern char *p_zmq_get_address(struct p_zmq_host *); extern u_int8_t p_zmq_get_topic(struct p_zmq_host *); extern void *p_zmq_get_sock(struct p_zmq_host *); extern int p_zmq_get_fd(struct p_zmq_host *); extern int p_zmq_connect(struct p_zmq_host *); extern int p_zmq_bind(struct p_zmq_host *); extern void p_zmq_init_pub(struct p_zmq_host *, char *, u_int8_t); extern void p_zmq_init_sub(struct p_zmq_host *); extern void p_zmq_init_push(struct p_zmq_host *, char *); extern void p_zmq_init_pull(struct p_zmq_host *); extern int p_zmq_recv_poll(struct p_zmq_sock *, int); extern int p_zmq_topic_recv(struct p_zmq_host *, void *, u_int64_t); extern int p_zmq_topic_send(struct p_zmq_host *, void *, u_int64_t); extern void p_zmq_close(struct p_zmq_host *); extern void p_zmq_plugin_pipe_init_core(struct p_zmq_host *, u_int8_t, char *, char *); extern void p_zmq_plugin_pipe_init_plugin(struct p_zmq_host *); extern int p_zmq_plugin_pipe_set_profile(struct configuration *, char *); extern void p_zmq_ctx_setup(struct p_zmq_host *); extern void p_zmq_pull_setup(struct p_zmq_host *); extern void p_zmq_pull_bind_setup(struct p_zmq_host *); extern void p_zmq_sub_setup(struct p_zmq_host *); extern void p_zmq_push_setup(struct p_zmq_host *); extern void p_zmq_push_connect_setup(struct p_zmq_host *); extern void p_zmq_pub_setup(struct p_zmq_host *); extern void p_zmq_zap_setup(struct p_zmq_host *); extern void p_zmq_recv_setup(struct p_zmq_host *, int, int); extern void p_zmq_send_setup(struct p_zmq_host *, int, int); extern void p_zmq_router_setup(struct p_zmq_host *, char *, int); extern void p_zmq_dealer_inproc_setup(struct p_zmq_host *); extern void p_zmq_proxy_setup(struct p_zmq_host *); extern void p_zmq_router_backend_setup(struct p_zmq_host *, int); extern void p_zmq_router_worker(void *); extern char *p_zmq_recv_str(struct p_zmq_sock *); extern int p_zmq_send_str(struct p_zmq_sock *, char *); extern int p_zmq_sendmore_str(struct p_zmq_sock *, char *); extern int p_zmq_recv_bin(struct p_zmq_sock *, void *, size_t); extern int p_zmq_send_bin(struct p_zmq_sock *, void *, size_t, int); extern int p_zmq_sendmore_bin(struct p_zmq_sock *, void *, size_t, int); extern void p_zmq_zap_handler(void *); /* global vars */ extern struct p_zmq_host nfacctd_zmq_host; extern struct p_zmq_host telemetry_zmq_host; pmacct-1.7.8/src/pmbgpd.c0000644000175000017500000002437714354105275014233 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_hooks.h" #include "bgp/bgp.h" #include "bgp/bgp_lg.h" #include "pmbgpd.h" #include "pretag_handlers.h" #include "pmacct-data.h" #include "pkt_handlers.h" #include "ip_flow.h" #include "net_aggr.h" #include "thread_pool.h" /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", PMBGPD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -L IP address ] [ -l port ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -L \tBind to the specified IP address\n"); printf(" -l \tListen on the specified TCP port\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -D \tDaemonize\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -o \tOutput file to log real-time BGP messages\n"); printf(" -O \tOutput file to dump generated RIBs at regular time intervals\n"); printf(" -i \tInterval, in secs, to write to the dump output file (supplied by -O)\n"); printf(" -g \tEnable the Looking Glass server\n"); printf(" -m \tLoad a BGP xconnects map from the specified file\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { struct plugins_list_entry *list; char config_file[SRVBUFLEN]; int logf; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); log_notifications_init(&log_notifications); config.acct_type = ACCT_PMBGP; config.progname = pmbgpd_globstr; find_id_func = NULL; plugins_list = NULL; errflag = 0; rows = 0; /* needed for pre_tag_map support */ PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_PMBGPD)) != -1)) { cfg_cmdline[rows] = malloc(SRVBUFLEN); switch (cp) { case 'L': strlcpy(cfg_cmdline[rows], "bgp_daemon_ip: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'l': strlcpy(cfg_cmdline[rows], "bgp_daemon_port: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "bgp_daemon_msglog_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "bgp_table_dump_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'i': strlcpy(cfg_cmdline[rows], "bgp_table_dump_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'g': strlcpy(cfg_cmdline[rows], "bgp_daemon_lg: true", SRVBUFLEN); rows++; break; case 'm': strlcpy(cfg_cmdline[rows], "bgp_daemon_xconnect_map: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, PMBGPD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } list = plugins_list; while (list) { list->cfg.acct_type = ACCT_PMBGP; list->cfg.progname = pmbgpd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, PMBGPD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); if (!config.bgp_daemon) config.bgp_daemon = BGP_DAEMON_ONLINE; if (!config.bgp_daemon_port) config.bgp_daemon_port = BGP_TCP_PORT; #if defined WITH_ZMQ if (config.bgp_lg) bgp_lg_wrapper(); #else if (config.bgp_lg) { Log(LOG_ERR, "ERROR ( %s/core/lg ): 'bgp_daemon_lg' requires --enable-zmq. Exiting.\n", config.name); exit_gracefully(1); } #endif #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif bgp_prepare_daemon(); skinny_bgp_daemon(); return 0; } pmacct-1.7.8/src/pkt_handlers.h0000644000175000017500000004665314354105275015446 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PKT_HANDLERS_H #define PKT_HANDLERS_H extern struct channels_list_entry channels_list[MAX_N_PLUGINS]; /* communication channels: core <-> plugins */ extern pkt_handler phandler[N_PRIMITIVES]; extern void warn_unsupported_packet_handler(u_int64_t, u_int64_t); extern void evaluate_packet_handlers(); extern void src_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void cos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void etype_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void mpls_label_top_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void mpls_label_bottom_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void mpls_label_stack_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void ip_tos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void ip_proto_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tcp_flags_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_src_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_dst_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_ip_proto_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_ip_tos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void tunnel_tcp_flags_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void vxlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void counters_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void counters_renormalize_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void time_new_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void time_pcap_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void post_tag_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void post_tag2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void flows_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void in_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void out_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sampling_rate_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sampling_direction_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void timestamp_start_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void timestamp_arrival_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void custom_primitives_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sfprobe_payload_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void nfprobe_extras_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void mpls_vpn_rd_frommap_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_src_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_dst_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_in_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_out_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_cos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_etype_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_src_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_dst_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_src_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_dst_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_peer_src_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_peer_dst_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_peer_src_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_peer_dst_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_ip_tos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_ip_proto_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_tcp_flags_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_fwd_status_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_counters_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_time_msecs_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_time_secs_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_time_new_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_flows_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_class_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_in_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_out_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_sampling_rate_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_sampling_direction_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_post_nat_src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_post_nat_dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_post_nat_src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_post_nat_dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_nat_event_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_fw_event_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_label_stack_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_label_top_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_label_bottom_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_vpn_id_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_vpn_rd_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_mpls_pw_id_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_vxlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_timestamp_start_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_timestamp_end_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_timestamp_arrival_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_timestamp_export_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_sequence_number_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_version_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_sysid_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_custom_primitives_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_counters_renormalize_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_counters_map_renormalize_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_cust_tag_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_cust_tag2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_cust_label_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_tee_payload_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_ext_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void nfprobe_bgp_ext_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sfprobe_bgp_ext_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_peer_src_as_frommap_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_src_local_pref_frommap_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_src_med_frommap_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_src_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_dst_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void bgp_peer_dst_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void igp_src_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void igp_dst_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void igp_peer_dst_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_src_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_dst_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_in_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_out_vlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_cos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_etype_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_src_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_dst_nmask_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_src_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_dst_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_peer_src_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_peer_dst_ip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_ip_tos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_ip_proto_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tcp_flags_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_flows_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_counters_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_counters_renormalize_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_counters_map_renormalize_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tag_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tag2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_in_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_out_iface_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_sampling_rate_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_sampling_direction_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_sampling_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_timestamp_arrival_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_sequence_number_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_version_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_sysid_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_bgp_peer_src_as_fromext_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_bgp_peer_src_as_fromstd_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_as_path_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_peer_src_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_peer_dst_as_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_local_pref_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_std_comms_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_src_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_dst_mac_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_src_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_dst_host_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_ip_proto_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_ip_tos_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_src_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_dst_port_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tunnel_tcp_flags_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_vxlan_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_tee_payload_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_mpls_label_top_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_mpls_label_bottom_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_mpls_label_stack_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_mpls_pw_id_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_custom_primitives_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void pre_tag_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void pre_tag2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void pre_tag_label_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sampling_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void sfprobe_sampling_handler(struct channels_list_entry *, struct packet_ptrs *, char **); #if defined (WITH_GEOIP) extern void pm_geoip_init(); extern void src_host_country_geoip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_country_geoip_handler(struct channels_list_entry *, struct packet_ptrs *, char **); #endif #if defined (WITH_GEOIPV2) extern void pm_geoipv2_init(); extern void pm_geoipv2_close(); extern void src_host_geoipv2_lookup_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_geoipv2_lookup_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void src_host_country_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_country_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void src_host_pocode_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_pocode_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void src_host_coords_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void dst_host_coords_geoipv2_handler(struct channels_list_entry *, struct packet_ptrs *, char **); #endif #if defined (WITH_NDPI) extern void ndpi_class_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void NF_ndpi_class_handler(struct channels_list_entry *, struct packet_ptrs *, char **); extern void SF_ndpi_class_handler(struct channels_list_entry *, struct packet_ptrs *, char **); #endif extern int evaluate_lm_method(struct packet_ptrs *, u_int8_t, u_int32_t, u_int32_t); extern char *lookup_tpl_ext_db(void *, u_int32_t, u_int16_t); #endif //PKT_HANDLERS_H pmacct-1.7.8/src/addr.c0000644000175000017500000006400314354105275013662 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "addr.h" #include "jhash.h" static const char hex[] = "0123456789abcdef"; /* * str_to_addr() converts a string into a supported family address */ unsigned int str_to_addr(const char *str, struct host_addr *a) { if (inet_aton(str, &a->address.ipv4)) { a->family = AF_INET; return a->family; } if (inet_pton(AF_INET6, str, &a->address.ipv6) > 0) { a->family = AF_INET6; return a->family; } return FALSE; } /* * addr_to_str() converts a supported family address into a string * 'str' length is not checked and assumed to be INET6_ADDRSTRLEN */ unsigned int addr_to_str(char *str, const struct host_addr *a) { if (a->family == AF_INET) { inet_ntop(AF_INET, &a->address.ipv4, str, INET6_ADDRSTRLEN); return a->family; } if (a->family == AF_INET6) { inet_ntop(AF_INET6, &a->address.ipv6, str, INET6_ADDRSTRLEN); return a->family; } memset(str, 0, INET6_ADDRSTRLEN); return FALSE; } /* * addr_to_str2() converts a supported family address into a string * conversions among AFs is supported (ie. IPv6 IPv4-mapped to IPv4 * and vice-versa). 'str' length is not checked and assumed to be * INET6_ADDRSTRLEN */ unsigned int addr_to_str2(char *str, const struct host_addr *a, int target_af) { if (target_af != AF_INET && target_af != AF_INET6) { goto exit_lane; } if (a->family == AF_INET && target_af == AF_INET) { inet_ntop(AF_INET, &a->address.ipv4, str, INET6_ADDRSTRLEN); return target_af; } if (a->family == AF_INET6 && target_af == AF_INET6) { inet_ntop(AF_INET6, &a->address.ipv6, str, INET6_ADDRSTRLEN); return target_af; } if (a->family == AF_INET6 && target_af == AF_INET) { if (a->address.ipv6.s6_addr[10] == 0xff && a->address.ipv6.s6_addr[11] == 0xff) { inet_ntop(target_af, &a->address.ipv6.s6_addr[12], str, INET6_ADDRSTRLEN); return target_af; } } if (a->family == AF_INET && target_af == AF_INET6) { struct host_addr local_ha; memset(&local_ha, 0, sizeof(local_ha)); memset((u_int8_t *)&local_ha.address.ipv6.s6_addr[10], 0xff, 2); memcpy(&local_ha.address.ipv6.s6_addr[12], &a->address.ipv4, 4); inet_ntop(AF_INET6, &local_ha.address.ipv6, str, INET6_ADDRSTRLEN); return target_af; } exit_lane: memset(str, 0, INET6_ADDRSTRLEN); return FALSE; } /* * addr_mask_to_str() converts a supported family address into a string */ unsigned int addr_mask_to_str(char *str, int len, const struct host_addr *a, const struct host_mask *m) { char buf[INET6_ADDRSTRLEN]; if (a->family == m->family) { if (a->family == AF_INET) { inet_ntop(AF_INET, &a->address.ipv4, buf, sizeof(buf)); snprintf(str, len, "%s/%u", buf, m->len); return a->family; } else if (a->family == AF_INET6) { inet_ntop(AF_INET6, &a->address.ipv6, buf, sizeof(buf)); snprintf(str, len, "%s/%u", buf, m->len); return a->family; } } memset(str, 0, len); return FALSE; } unsigned int apply_addr_mask(struct host_addr *a, struct host_mask *m) { int j, ret = FALSE; if (a->family != m->family) { return FALSE; } if (a->family == AF_INET) { if (m->len > 32) { return FALSE; } m->mask.m4 = htonl((m->len == 32) ? 0xffffffffUL : ~(0xffffffffUL >> m->len)); a->address.ipv4.s_addr &= m->mask.m4; ret = a->family; } else if (a->family == AF_INET6) { if (m->len > 128) { return FALSE; } for (j = 0; j < 16 && m->len >= 8; j++, m->len -= 8) { m->mask.m6[j] = 0xffU; } if (j < 16 && m->len) { m->mask.m6[j] = htonl(~(0xffU >> m->len)); } for (j = 0; j < 16; j++) a->address.ipv6.s6_addr[j] &= m->mask.m6[j]; ret = a->family; } return ret; } /* * str_to_addr_mask() converts a string into a supported family address */ unsigned int str_to_addr_mask(const char *str, struct host_addr *a, struct host_mask *m) { char *delim = NULL, *mask = NULL; unsigned int family = 0, index = 0, j; if (!str || !a || !m) return family; delim = strchr(str, '/'); if (delim) { *delim = '\0'; mask = delim+1; } family = str_to_addr(str, a); if (delim) *delim = '/'; if (family) { if (mask) { index = atoi(mask); m->len = index; if (family == AF_INET) { if (index > 32) goto error; else { m->mask.m4 = htonl((index == 32) ? 0xffffffffUL : ~(0xffffffffUL >> index)); a->address.ipv4.s_addr &= m->mask.m4; } } else if (family == AF_INET6) { if (index > 128) goto error; for (j = 0; j < 16 && index >= 8; j++, index -= 8) m->mask.m6[j] = 0xffU; if (j < 16 && index) m->mask.m6[j] = htonl(~(0xffU >> index)); for (j = 0; j < 16; j++) a->address.ipv6.s6_addr[j] &= m->mask.m6[j]; } else goto error; } /* if no mask: set ipv4 mask to /32 and ipv6 mask to /128 */ else { if (family == AF_INET) { m->len = 32; m->mask.m4 = 0xffffffffUL; } else if (family == AF_INET6) { m->len = 128; for (j = 0; j < 16; j++) m->mask.m6[j] = 0xffU; } else goto error; } m->family = family; } return family; error: a->family = 0; m->family = 0; return FALSE; } /* * addr_to_sa() converts a supported family address into a sockaddr * structure */ unsigned int addr_to_sa(struct sockaddr *sa, struct host_addr *a, u_int16_t port) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (a->family == AF_INET) { sa->sa_family = AF_INET; sa4->sin_addr.s_addr = a->address.ipv4.s_addr; sa4->sin_port = htons(port); return sizeof(struct sockaddr_in); } if (a->family == AF_INET6) { sa->sa_family = AF_INET6; ip6_addr_cpy(&sa6->sin6_addr, &a->address.ipv6); sa6->sin6_port = htons(port); return sizeof(struct sockaddr_in6); } memset(sa, 0, sizeof(struct sockaddr)); return FALSE; } /* * sa_to_addr() converts a sockaddr structure into a supported family * address */ unsigned int sa_to_addr(struct sockaddr *sa, struct host_addr *a, u_int16_t *port) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (sa->sa_family == AF_INET) { a->family = AF_INET; a->address.ipv4.s_addr = sa4->sin_addr.s_addr; *port = ntohs(sa4->sin_port); return sizeof(struct sockaddr_in); } if (sa->sa_family == AF_INET6) { a->family = AF_INET6; ip6_addr_cpy(&a->address.ipv6, &sa6->sin6_addr); *port = ntohs(sa6->sin6_port); return sizeof(struct sockaddr_in6); } memset(a, 0, sizeof(struct host_addr)); return FALSE; } /* * sa_addr_cmp(): compare two IP addresses: the first encapsulated * into a 'struct sockaddr' and the second into a 'struct host_addr'. * returns 0 if they match, 1 if a1 is found greater than a2; -1 on * the contrary. -1 is also used to flag a generic error (ie. family * not supported). */ int sa_addr_cmp(struct sockaddr *sa, struct host_addr *a) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; struct sockaddr_in6 sa6_local; if (a->family == AF_INET && sa->sa_family == AF_INET) { if (sa4->sin_addr.s_addr == a->address.ipv4.s_addr) return FALSE; else if (sa4->sin_addr.s_addr > a->address.ipv4.s_addr) return TRUE; else return ERR; } if (a->family == AF_INET6 && sa->sa_family == AF_INET6) { return ip6_addr_cmp(&sa6->sin6_addr, &a->address.ipv6); } else if (a->family == AF_INET && sa->sa_family == AF_INET6) { memset(&sa6_local, 0, sizeof(sa6_local)); memset((u_int8_t *)&sa6_local.sin6_addr+10, 0xff, 2); memcpy((u_int8_t *)&sa6_local.sin6_addr+12, &a->address.ipv4.s_addr, 4); return ip6_addr_cmp(&sa6->sin6_addr, &sa6_local.sin6_addr); } else if (a->family == AF_INET6 && sa->sa_family == AF_INET) { memset(&sa6_local, 0, sizeof(sa6_local)); memset((u_int8_t *)&sa6_local.sin6_addr+10, 0xff, 2); memcpy((u_int8_t *)&sa6_local.sin6_addr+12, &sa4->sin_addr, 4); return ip6_addr_cmp(&sa6_local.sin6_addr, &a->address.ipv6); } return ERR; } /* * sa_port_cmp(): compare two TCP/UDP ports: the first encapsulated in a * 'struct sockaddr' and the second as a u_int16_t * returns 0 if they match; 1 if they don't match; -1 to signal a generic * error (e.g. unsupported family). */ int sa_port_cmp(struct sockaddr *sa, u_int16_t port) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (sa->sa_family == AF_INET) { if (ntohs(sa4->sin_port) == port) return FALSE; else return TRUE; } if (sa->sa_family == AF_INET6) { if (ntohs(sa6->sin6_port) == port) return FALSE; else return TRUE; } return ERR; } /* * host_addr_cmp() compares two IP addresses in a host_addr structure * returns 0 if they match, 1 if a1 is found greater than a2; -1 on * the contrary. -1 is also used to flag a generic error (ie. family * not supported). */ int host_addr_cmp(struct host_addr *a1, struct host_addr *a2) { struct host_addr ha_local; if (a1->family == AF_INET && a2->family == AF_INET) { if (a1->address.ipv4.s_addr == a2->address.ipv4.s_addr) return FALSE; else if (a1->address.ipv4.s_addr > a2->address.ipv4.s_addr) return TRUE; else return ERR; } if (a1->family == AF_INET6 && a2->family == AF_INET6) { return ip6_addr_cmp(&a1->address.ipv6, &a2->address.ipv6); } else if (a1->family == AF_INET && a2->family == AF_INET6) { memset(&ha_local, 0, sizeof(ha_local)); memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2); memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a1->address.ipv4.s_addr, 4); return ip6_addr_cmp(&a2->address.ipv6, &ha_local.address.ipv6); } else if (a1->family == AF_INET6 && a2->family == AF_INET) { memset(&ha_local, 0, sizeof(ha_local)); memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2); memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a2->address.ipv4.s_addr, 4); return ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6); } return ERR; } /* * variant of host_addr_cmp(). In addition it returns FALSE if family * is zero in both a1 and a2. */ int host_addr_cmp2(struct host_addr *a1, struct host_addr *a2) { struct host_addr ha_local; if (a1->family == AF_INET && a2->family == AF_INET) { if (a1->address.ipv4.s_addr == a2->address.ipv4.s_addr) return FALSE; else if (a1->address.ipv4.s_addr > a2->address.ipv4.s_addr) return TRUE; else return ERR; } if (a1->family == AF_INET6 && a2->family == AF_INET6) { return ip6_addr_cmp(&a1->address.ipv6, &a2->address.ipv6); } else if (a1->family == AF_INET && a2->family == AF_INET6) { if (a2->address.ipv6.s6_addr[10] == 0xff && a2->address.ipv6.s6_addr[11] == 0xff) { memset(&ha_local, 0, sizeof(ha_local)); memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2); memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a1->address.ipv4.s_addr, 4); return ip6_addr_cmp(&a2->address.ipv6, &ha_local.address.ipv6); } } else if (a1->family == AF_INET6 && a2->family == AF_INET) { if (a1->address.ipv6.s6_addr[10] == 0xff && a1->address.ipv6.s6_addr[11] == 0xff) { memset(&ha_local, 0, sizeof(ha_local)); memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2); memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a2->address.ipv4.s_addr, 4); return ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6); } } if (!a1->family && !a2->family) return FALSE; return ERR; } /* * host_addr_mask_sa_cmp() checks whether s1 falls in a1/m1 * returns 0 if positive; 1 if negative; -1 to signal a generic error * (e.g. unsupported family). */ int host_addr_mask_sa_cmp(struct host_addr *a1, struct host_mask *m1, struct sockaddr *s1) { struct sockaddr_in *sa4 = (struct sockaddr_in *)s1; struct sockaddr_in6 sa6_local; int ret, j; if (!a1 || !m1 || !s1) return ERR; if (a1->family != s1->sa_family || a1->family != m1->family) return ERR; if (a1->family == AF_INET) { if ((sa4->sin_addr.s_addr & m1->mask.m4) == a1->address.ipv4.s_addr) return FALSE; else return TRUE; } else if (a1->family == AF_INET6) { memcpy(&sa6_local, s1, sizeof(struct sockaddr_in6)); for (j = 0; j < 16; j++) sa6_local.sin6_addr.s6_addr[j] &= m1->mask.m6[j]; ret = ip6_addr_cmp(&a1->address.ipv6, &sa6_local.sin6_addr); if (!ret) return FALSE; else return TRUE; } return ERR; } /* * host_addr_mask_cmp() checks whether a2 falls in a1/m1 * returns 0 if positive; 1 if negative; -1 to signal a generic error * (e.g. unsupported family). */ int host_addr_mask_cmp(struct host_addr *a1, struct host_mask *m1, struct host_addr *a2) { struct host_addr ha_local; int ret, j; if (!a1 || !m1 || !a2) return ERR; if (a1->family != a2->family || a1->family != m1->family) return ERR; if (a1->family == AF_INET) { if ((a2->address.ipv4.s_addr & m1->mask.m4) == a1->address.ipv4.s_addr) return FALSE; else return TRUE; } else if (a1->family == AF_INET6) { memcpy(&ha_local, a2, sizeof(struct host_addr)); for (j = 0; j < 16; j++) ha_local.address.ipv6.s6_addr[j] &= m1->mask.m6[j]; ret = ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6); if (!ret) return FALSE; else return TRUE; } return ERR; } /* * raw_to_sa() converts a supported family address into a sockaddr * structure */ unsigned int raw_to_sa(struct sockaddr *sa, u_char *src, u_int16_t port, u_int8_t v4v6) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (v4v6 == AF_INET) { sa->sa_family = AF_INET; memcpy(&sa4->sin_addr.s_addr, src, 4); sa4->sin_port = port; return sizeof(struct sockaddr_in); } if (v4v6 == AF_INET6) { sa->sa_family = AF_INET6; ip6_addr_cpy(&sa6->sin6_addr, src); sa6->sin6_port = port; return sizeof(struct sockaddr_in6); } memset(sa, 0, sizeof(struct sockaddr)); return FALSE; } /* * raw_to_addr() converts a supported family address into a host_addr * structure */ unsigned int raw_to_addr(struct host_addr *ha, u_char *src, u_int8_t v4v6) { if (v4v6 == AF_INET) { ha->family = AF_INET; memcpy(&ha->address.ipv4, src, 4); return ha->family; } if (v4v6 == AF_INET6) { ha->family = AF_INET6; ip6_addr_cpy(&ha->address.ipv6, src); return ha->family; } memset(ha, 0, sizeof(struct host_addr)); return FALSE; } /* * sa_to_str() converts a supported family address into a string */ unsigned int sa_to_str(char *str, int len, const struct sockaddr *sa, int want_port) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; char sep[] = ":"; int off; if (len >= INET6_ADDRSTRLEN) { if (sa->sa_family == AF_INET) { inet_ntop(AF_INET, &sa4->sin_addr.s_addr, str, INET6_ADDRSTRLEN); if (len >= (strlen(str) + PORT_STRLEN + 1) && sa4->sin_port && want_port) { off = strlen(str); snprintf(str + off, len - off, "%s", sep); off = strlen(str); snprintf(str + off, len - off, "%u", ntohs(sa4->sin_port)); } return sa->sa_family; } if (sa->sa_family == AF_INET6) { inet_ntop(AF_INET6, &sa6->sin6_addr, str, INET6_ADDRSTRLEN); if (len >= (strlen(str) + PORT_STRLEN + 1) && sa6->sin6_port && want_port) { off = strlen(str); snprintf(str + off, len - off, "%s", sep); off = strlen(str); snprintf(str + off, len - off, "%u", ntohs(sa6->sin6_port)); } return sa->sa_family; } } memset(str, 0, len); return FALSE; } unsigned int sa_to_port(int *port, const struct sockaddr *sa) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (!port) return FALSE; if (sa->sa_family == AF_INET) { (*port) = ntohs(sa4->sin_port); return sa->sa_family; } if (sa->sa_family == AF_INET6) { (*port) = ntohs(sa6->sin6_port); return sa->sa_family; } (*port) = 0; return FALSE; } /* * pm_htonl6(): same as htonl() for IPv6 addresses; no checks are done * on the length of the buffer. */ void *pm_htonl6(void *addr) { register u_int32_t *ptr = addr; static u_int32_t buf[4]; u_int8_t chunk; for (chunk = 0; chunk < 4; chunk++) buf[chunk] = htonl(ptr[chunk]); return buf; } /* * pm_ntohl6(): same as ntohl() for IPv6 addresses; no checks are done * on the length of the buffer. */ void *pm_ntohl6(void *addr) { register u_int32_t *ptr = addr; static u_int32_t buf[4]; u_int8_t chunk; for (chunk = 0; chunk < 4; chunk++) buf[chunk] = ntohl(ptr[chunk]); return buf; } /* * ip6_addr_cmp(): compare two IPv6 addresses; returns 0 if they match, * 1 if the first not matching chunk of addr1 is found to be greater than * addr2; -1 on the contrary. */ int ip6_addr_cmp(void *addr1, void *addr2) { register u_int32_t *ptr1 = addr1, *ptr2 = addr2; int chunk; for (chunk = 0; chunk < 4; chunk++) { if (ptr1[chunk] == ptr2[chunk]) continue; else { if (ptr1[chunk] > ptr2[chunk]) return TRUE; else return ERR; } } return FALSE; } /* * ip6_addr_cpy(): copy of a *src IPv6 address into a *dst buffer. */ void ip6_addr_cpy(void *dst, void *src) { register u_int32_t *ptrs = src, *ptrd = dst; int chunk; for (chunk = 0; chunk < 4; chunk++) ptrd[chunk] = ptrs[chunk]; } /* * ip6_addr_32bit_cpy(): copy of arbitrary 32bit IPv6 address chunks */ void ip6_addr_32bit_cpy(void *dst, void *src, int dstart, int sstart, int send) { register u_int32_t *ptrs = src, *ptrd = dst; int schunk, dchunk; for (schunk = sstart, dchunk = dstart; schunk <= send; schunk++, dchunk++) ptrd[dchunk] = ptrs[schunk]; } void etheraddr_string(const u_char *ep, char *buf) { u_int i, j; char *cp; cp = buf; if ((j = *ep >> 4) != 0) *cp++ = hex[j]; else *cp++ = '0'; *cp++ = hex[*ep++ & 0xf]; for (i = 5; (int)--i >= 0;) { *cp++ = ':'; if ((j = *ep >> 4) != 0) *cp++ = hex[j]; else *cp++ = '0'; *cp++ = hex[*ep++ & 0xf]; } *cp = '\0'; } /* * string_etheraddr() writes the content of *asc in *addr (which has * to be ETH_ADDR_LEN long). TRUE is returned if any failure occurs; * TRUE if the routine completes the job successfully */ int string_etheraddr(const char *asc, u_char *addr) { int cnt; for (cnt = 0; cnt < 6; ++cnt) { unsigned int number; char ch; ch = tolower (*asc++); if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return TRUE; number = isdigit (ch) ? (ch - '0') : (ch - 'a' + 10); ch = tolower(*asc); if ((cnt < 5 && ch != ':') || (cnt == 5 && ch != '\0' && !isspace (ch))) { ++asc; if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return TRUE; number <<= 4; number += isdigit (ch) ? (ch - '0') : (ch - 'a' + 10); ch = *asc; if (cnt < 5 && ch != ':') return TRUE; } /* Store result. */ addr[cnt] = (unsigned char) number; /* Skip ':'. */ ++asc; } return FALSE; } /* * pm_htonll(): similar to htonl() for 64 bits integers; no checks are done * on the length of the buffer. */ u_int64_t pm_htonll(u_int64_t addr) { #if defined IM_LITTLE_ENDIAN u_int64_t buf = 0; u_int32_t *x = (u_int32_t *)(void *) &addr; u_int32_t *y = (u_int32_t *)(void *) &buf; y[0] = htonl(x[1]); y[1] = htonl(x[0]); return buf; #else return addr; #endif } /* * pm_ntohll(): similar to ntohl() for 64 bits integers; no checks are done * on the length of the buffer. */ u_int64_t pm_ntohll(u_int64_t addr) { #if defined IM_LITTLE_ENDIAN static u_int64_t buf; buf = ((u_int64_t) ntohl(addr & 0xFFFFFFFFLLU)) << 32; buf |= ntohl((addr & 0xFFFFFFFF00000000LLU) >> 32); return buf; #else return addr; #endif } /* * is_multicast(): determines whether the supplied IPv4/IPv6 address is a * multicast address or not. */ int is_multicast(struct host_addr *a) { if (!a) return FALSE; if (a->family == AF_INET) { if (IS_IPV4_MULTICAST(a->address.ipv4.s_addr)) return a->family; else return FALSE; } if (a->family == AF_INET6) { if (IS_IPV6_MULTICAST(&a->address.ipv6)) return a->family; else return FALSE; } return FALSE; } /* * is_any(): determines whether the supplied IPv4/IPv6 address is a * 0.0.0.0 IPv4 or :: IPv6 address or not. */ int is_any(struct host_addr *a) { struct host_addr empty_host_addr; if (!a) return FALSE; memset(&empty_host_addr, 0, sizeof(empty_host_addr)); if (a->family == AF_INET) { if (!memcmp(&empty_host_addr.address.ipv4, &a->address.ipv4, 4)) return a->family; else return FALSE; } if (a->family == AF_INET6) { if (!memcmp(&empty_host_addr.address.ipv6, &a->address.ipv6, 16)) return a->family; else return FALSE; } return FALSE; } /* * clean_sin_addr(): cleans the IP address from the pointed sockaddr structure */ void clean_sin_addr(struct sockaddr *sa) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (sa->sa_family == AF_INET) sa4->sin_addr.s_addr = 0; if (sa->sa_family == AF_INET6) memset(&sa6->sin6_addr, 0, 16); } /* * ipv4_mapped_to_ipv4() converts a label into a supported family address */ void ipv4_mapped_to_ipv4(struct sockaddr_storage *sas) { struct sockaddr_storage sas_local; struct sockaddr *sa = (struct sockaddr *) sas; struct sockaddr_in *sa4 = (struct sockaddr_in *) sas; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sas; if (sa->sa_family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) return; memcpy(&sas_local, sas, sizeof(struct sockaddr_storage)); memset(sas, 0, sizeof(struct sockaddr_storage)); sa6 = (struct sockaddr_in6 *) &sas_local; sa->sa_family = AF_INET; memcpy(&sa4->sin_addr, (u_int8_t *) &sa6->sin6_addr+12, 4); sa4->sin_port = sa6->sin6_port; } void ipv4_to_ipv4_mapped(struct sockaddr_storage *sas) { struct sockaddr_storage sas_local; struct sockaddr *sa = (struct sockaddr *) sas; struct sockaddr_in *sa4 = (struct sockaddr_in *) sas; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sas; static u_int16_t ffff = 0xFFFF; if (sa->sa_family != AF_INET) return; memcpy(&sas_local, sas, sizeof(struct sockaddr_storage)); memset(sas, 0, sizeof(struct sockaddr_storage)); sa4 = (struct sockaddr_in *) &sas_local; sa->sa_family = AF_INET6; memcpy((u_int8_t *) &sa6->sin6_addr+10, &ffff, 2); memcpy((u_int8_t *) &sa6->sin6_addr+12, &sa4->sin_addr, 4); sa6->sin6_port = sa4->sin_port; } u_int8_t etype_to_af(u_int16_t etype) { if (etype == ETHERTYPE_IP) return AF_INET; else if (etype == ETHERTYPE_IPV6) return AF_INET6; return FALSE; } u_int16_t af_to_etype(u_int8_t af) { if (af == AF_INET) return ETHERTYPE_IP; else if (af == AF_INET6) return ETHERTYPE_IPV6; return FALSE; } const char *af_to_version_str(u_int8_t af) { if (af == AF_INET) return ip_version_string[0]; else if (af == AF_INET6) return ip_version_string[1]; return NULL; } u_int8_t af_to_version(u_int8_t af) { if (af == AF_INET) return ip_version_num[0]; else if (af == AF_INET6) return ip_version_num[1]; return 0; } const char *etype_to_version_str(u_int16_t etype) { if (etype == ETHERTYPE_IP) return ip_version_string[0]; else if (etype == ETHERTYPE_IPV6) return ip_version_string[1]; return NULL; } u_int8_t etype_to_version(u_int16_t etype) { if (etype == ETHERTYPE_IP) return ip_version_num[0]; else if (etype == ETHERTYPE_IPV6) return ip_version_num[1]; return 0; } u_int32_t addr_hash(struct host_addr *ha, u_int32_t modulo) { u_int32_t val = 0; if (ha->family == AF_INET) { val = jhash_1word(ha->address.ipv4.s_addr, 0); } else if (ha->family == AF_INET6) { u_int32_t a, b, c; memcpy(&a, &ha->address.ipv6.s6_addr[4], 4); memcpy(&b, &ha->address.ipv6.s6_addr[8], 4); memcpy(&c, &ha->address.ipv6.s6_addr[12], 4); val = jhash_3words(a, b, c, 0); } return (val % modulo); } u_int32_t sa_hash(struct sockaddr *sa, u_int32_t modulo) { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; u_int32_t val = 0; if (sa->sa_family == AF_INET) { val = jhash_1word(sa4->sin_addr.s_addr, 0); } else if (sa->sa_family == AF_INET6) { u_int32_t a, b, c; memcpy(&a, &sa6->sin6_addr.s6_addr[4], 4); memcpy(&b, &sa6->sin6_addr.s6_addr[8], 4); memcpy(&c, &sa6->sin6_addr.s6_addr[12], 4); val = jhash_3words(a, b, c, 0); } return (val % modulo); } // XXX: basic implementation, to be improved u_int32_t addr_port_hash(struct host_addr *ha, u_int16_t port, u_int32_t modulo) { u_int32_t val = 0; if (ha->family == AF_INET) { val = jhash_2words(ha->address.ipv4.s_addr, port, 0); } else if (ha->family == AF_INET6) { u_int32_t a, b; memcpy(&a, &ha->address.ipv6.s6_addr[8], 4); memcpy(&b, &ha->address.ipv6.s6_addr[12], 4); val = jhash_3words(port, a, b, 0); } return (val % modulo); } u_int16_t sa_has_family(struct sockaddr *sa) { return sa->sa_family; } socklen_t sa_len(struct sockaddr_storage *ss) { struct sockaddr *sa = (struct sockaddr *) ss; if (sa) { if (sa->sa_family == AF_INET) { return sizeof(struct sockaddr_in); } else if (sa->sa_family == AF_INET6) { return sizeof(struct sockaddr_in6); } else { return sizeof(struct sockaddr_storage); } } return 0; } pmacct-1.7.8/src/mysql_plugin.c0000644000175000017500000007270014354105275015476 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "sql_common.h" #include "sql_common_m.h" #include "mysql_plugin.h" #include "preprocess.h" /* variables */ char mysql_user[] = "pmacct"; char mysql_pwd[] = "arealsmartpwd"; unsigned int mysql_prt = 3306; char mysql_db[] = "pmacct"; char mysql_table[] = "acct"; char mysql_table_v2[] = "acct_v2"; char mysql_table_v3[] = "acct_v3"; char mysql_table_v4[] = "acct_v4"; char mysql_table_v5[] = "acct_v5"; char mysql_table_v6[] = "acct_v6"; char mysql_table_v7[] = "acct_v7"; char mysql_table_v8[] = "acct_v8"; char mysql_table_bgp[] = "acct_bgp"; /* Functions */ void mysql_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; struct pollfd pfd; struct insert_data idata; time_t refresh_deadline; int refresh_timeout; int ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *dataptr; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "MySQL Plugin", config.name); memset(&idata, 0, sizeof(idata)); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } sql_set_signals(); sql_init_default_values(&extras); MY_init_default_values(&idata); MY_set_callbacks(&sqlfunc_cbr); sql_set_insert_func(); /* some LOCAL initialization AFTER setting some default values */ reload_map = FALSE; idata.now = time(NULL); refresh_deadline = idata.now; idata.cfg = &config; sql_init_maps(&extras, &prim_ptrs, &nt, &nc, &pt, &prt, &tost); sql_init_global_buffers(); sql_init_historical_acct(idata.now, &idata); sql_init_triggers(idata.now, &idata); sql_init_refresh_deadline(&refresh_deadline); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; /* building up static SQL clauses */ idata.num_primitives = MY_compose_static_queries(); glob_num_primitives = idata.num_primitives; /* setting up environment variables */ SQL_SetENV(); sql_link_backend_descriptors(&bed, &p, &b); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: sql_update_time_reference(&idata); /* lazy sql refresh handling */ if (idata.now > refresh_deadline) { if (sql_qq_ptr) sql_cache_flush(sql_queries_queue, sql_qq_ptr, &idata, FALSE); sql_cache_handle_flush_event(&idata, &refresh_deadline, &pt, &prt, &tost); } else { if (config.sql_trigger_exec) { while (idata.now > idata.triggertime && idata.t_timeslot > 0) { sql_trigger_exec(config.sql_trigger_exec); idata.triggertime += idata.t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata.t_timeslot = calc_monthly_timeslot(idata.triggertime, config.sql_trigger_time_howmany, ADD); } } } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; idata.now = time(NULL); } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*sql_insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } int MY_cache_dbop(struct DBdesc *db, struct db_cache *cache_elem, struct insert_data *idata) { char *ptr_values, *ptr_where, *ptr_mv, *ptr_set; int num=0, num_set=0, ret=0, have_flows=0, len=0; if (idata->mv.last_queue_elem) { ret = mysql_query(db->desc, multi_values_buffer); Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d VALUES statements sent to the MySQL server.\n", config.name, config.type, idata->mv.buffer_elem_num); if (ret) goto signal_error; idata->iqn++; idata->mv.buffer_elem_num = FALSE; idata->mv.buffer_offset = 0; return FALSE; } if (config.what_to_count & COUNT_FLOWS) have_flows = TRUE; /* constructing sql query */ ptr_where = where_clause; ptr_values = values_clause; ptr_set = set_clause; memset(where_clause, 0, sizeof(where_clause)); memset(values_clause, 0, sizeof(values_clause)); memset(set_clause, 0, sizeof(set_clause)); memset(insert_full_clause, 0, sizeof(insert_full_clause)); for (num = 0; num < idata->num_primitives; num++) (*where[num].handler)(cache_elem, idata, num, &ptr_values, &ptr_where); if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { for (num_set = 0; set_event[num_set].type; num_set++) (*set_event[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } else { for (num_set = 0; set[num_set].type; num_set++) (*set[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } /* sending UPDATE query a) if not switched off and b) if we actually have something to update */ if (!config.sql_dont_try_update && num_set) { strncpy(sql_data, update_clause, SPACELEFT(sql_data)); strncat(sql_data, set_clause, SPACELEFT(sql_data)); strncat(sql_data, where_clause, SPACELEFT(sql_data)); ret = mysql_query(db->desc, sql_data); if (ret) goto signal_error; } if (config.sql_dont_try_update || !num_set || (mysql_affected_rows(db->desc) == 0)) { /* UPDATE failed, trying with an INSERT query */ if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_nocounters_clause, SPACELEFT(insert_full_clause)); strncat(ptr_values, ")", SPACELEFT(values_clause)); } else { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_counters_clause, SPACELEFT(insert_full_clause)); if (have_flows) snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter, cache_elem->flows_counter); else snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter); } if (config.sql_multi_values) { multi_values_handling: len = config.sql_multi_values-idata->mv.buffer_offset; if (!idata->mv.buffer_elem_num) { if (strlen(insert_full_clause) < len) { strncpy(multi_values_buffer, insert_full_clause, config.sql_multi_values); strcat(multi_values_buffer, " VALUES"); idata->mv.buffer_offset += strlen(multi_values_buffer); idata->mv.head_buffer_elem = idata->current_queue_elem; } else { Log(LOG_ERR, "ERROR ( %s/%s ): 'sql_multi_values' is too small (%d). Try with a larger value.\n", config.name, config.type, config.sql_multi_values); exit_gracefully(1); } } len = config.sql_multi_values-idata->mv.buffer_offset; if (strlen(values_clause) < len) { if (idata->mv.buffer_elem_num) { strcpy(multi_values_buffer+idata->mv.buffer_offset, ","); idata->mv.buffer_offset++; } ptr_mv = multi_values_buffer+idata->mv.buffer_offset; strcpy(multi_values_buffer+idata->mv.buffer_offset, values_clause+7); /* cut the initial 'VALUES' */ idata->mv.buffer_offset += strlen(ptr_mv); idata->mv.buffer_elem_num++; } else { if (idata->mv.buffer_elem_num) { ret = mysql_query(db->desc, multi_values_buffer); Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d VALUES statements sent to the MySQL server.\n", config.name, config.type, idata->mv.buffer_elem_num); if (ret) goto signal_error; idata->iqn++; idata->mv.buffer_elem_num = FALSE; idata->mv.head_buffer_elem = FALSE; idata->mv.buffer_offset = 0; goto multi_values_handling; } else { Log(LOG_ERR, "ERROR ( %s/%s ): 'sql_multi_values' is too small (%d). Try with a larger value.\n", config.name, config.type, config.sql_multi_values); exit_gracefully(1); } } } else { strncpy(sql_data, insert_full_clause, sizeof(sql_data)); strncat(sql_data, values_clause, SPACELEFT(sql_data)); ret = mysql_query(db->desc, sql_data); if (ret) goto signal_error; Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, sql_data); idata->iqn++; } } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, sql_data); idata->uqn++; } idata->een++; // cache_elem->valid = FALSE; /* committed */ return ret; signal_error: if (!idata->mv.buffer_elem_num) Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, sql_data); else { if (!idata->recover || db->type != BE_TYPE_PRIMARY) { /* DB failure: we will rewind the multi-values buffer */ idata->current_queue_elem = idata->mv.head_buffer_elem; idata->mv.buffer_elem_num = 0; } } MY_get_errmsg(db); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): %s\n\n", config.name, config.type, db->errmsg); if (mysql_errno(db->desc) == 1062) return FALSE; /* not signalling duplicate entry problems */ else return ret; } void MY_cache_purge(struct db_cache *queue[], int index, struct insert_data *idata) { struct db_cache *LastElemCommitted = NULL; time_t start; int j, stop, go_to_pending, saved_index = index; char orig_insert_clause[LONGSRVBUFLEN], orig_update_clause[LONGSRVBUFLEN], orig_lock_clause[LONGSRVBUFLEN]; char tmpbuf[LONGLONGSRVBUFLEN], tmptable[SRVBUFLEN]; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); if (!index) { Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: 0/0, ET: X) ***\n", config.name, config.type, writer_pid); return; } memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); for (j = 0, stop = 0; (!stop) && sql_preprocess_funcs[j]; j++) stop = sql_preprocess_funcs[j](queue, &index, j); if ((config.what_to_count & COUNT_CLASS) || (config.what_to_count_2 & COUNT_NDPI_CLASS)) sql_invalidate_shadow_entries(queue, &index); idata->ten = index; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); /* re-using pending queries queue stuff from parent and saving clauses */ memcpy(sql_pending_queries_queue, queue, index*sizeof(struct db_cache *)); sql_pqq_ptr = index; strlcpy(orig_insert_clause, insert_clause, LONGSRVBUFLEN); strlcpy(orig_update_clause, update_clause, LONGSRVBUFLEN); strlcpy(orig_lock_clause, lock_clause, LONGSRVBUFLEN); start: memset(&idata->mv, 0, sizeof(struct multi_values)); memcpy(queue, sql_pending_queries_queue, sql_pqq_ptr*sizeof(struct db_cache *)); memset(sql_pending_queries_queue, 0, sql_pqq_ptr*sizeof(struct db_cache *)); index = sql_pqq_ptr; sql_pqq_ptr = 0; /* We check for variable substitution in SQL table */ if (idata->dyn_table) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); stamp = queue[0]->basetime; strlcpy(idata->dyn_table_name, config.sql_table, SRVBUFLEN); strlcpy(insert_clause, orig_insert_clause, LONGSRVBUFLEN); strlcpy(update_clause, orig_update_clause, LONGSRVBUFLEN); strlcpy(lock_clause, orig_lock_clause, LONGSRVBUFLEN); prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[0]); handle_dynname_internal_strings_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(update_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(update_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); } if (config.sql_table_schema) sql_create_table(bed.p, &queue[0]->basetime, &prim_ptrs); if (idata->locks == PM_LOCK_EXCLUSIVE) (*sqlfunc_cbr.lock)(bed.p); for (idata->current_queue_elem = 0; idata->current_queue_elem < index; idata->current_queue_elem++) { go_to_pending = FALSE; if (idata->dyn_table && (!idata->dyn_table_time_only || !config.nfacctd_time_new || (config.sql_refresh_time != idata->timeslot))) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); // XXX: pedantic? stamp = queue[idata->current_queue_elem]->basetime; strlcpy(tmptable, config.sql_table, SRVBUFLEN); prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[idata->current_queue_elem]); handle_dynname_internal_strings_same(tmptable, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(tmptable, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (strncmp(idata->dyn_table_name, tmptable, SRVBUFLEN)) { sql_pending_queries_queue[sql_pqq_ptr] = queue[idata->current_queue_elem]; sql_pqq_ptr++; go_to_pending = TRUE; } } if (!go_to_pending) { if (queue[idata->current_queue_elem]->valid) sql_query(&bed, queue[idata->current_queue_elem], idata); if (queue[idata->current_queue_elem]->valid == SQL_CACHE_COMMITTED) LastElemCommitted = queue[idata->current_queue_elem]; } } /* multi-value INSERT query: wrap-up */ if (idata->mv.buffer_elem_num) { idata->mv.last_queue_elem = TRUE; sql_query(&bed, LastElemCommitted, idata); idata->qn--; /* increased by sql_query() one time too much */ } /* rewinding stuff */ if (idata->locks == PM_LOCK_EXCLUSIVE) (*sqlfunc_cbr.unlock)(&bed); if (b.fail) Log(LOG_ALERT, "ALERT ( %s/%s ): recovery for MySQL daemon failed.\n", config.name, config.type); /* If we have pending queries then start again */ if (sql_pqq_ptr) goto start; idata->elap_time = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, idata->qn, saved_index, idata->elap_time); if (config.sql_trigger_exec) { if (queue && queue[0]) idata->basetime = queue[0]->basetime; idata->elap_time = time(NULL)-start; SQL_SetENV_child(idata); } } int MY_evaluate_history(int primitive) { if (config.sql_history) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, ", ", sizeof(values[primitive].string)); strncat(where[primitive].string, " AND ", sizeof(where[primitive].string)); } if (!config.timestamps_since_epoch) strncat(where[primitive].string, "FROM_UNIXTIME(%u) = ", SPACELEFT(where[primitive].string)); else strncat(where[primitive].string, "%u = ", SPACELEFT(where[primitive].string)); strncat(where[primitive].string, "stamp_inserted", SPACELEFT(where[primitive].string)); strncat(insert_clause, "stamp_updated, stamp_inserted", SPACELEFT(insert_clause)); if (!config.timestamps_since_epoch) strncat(values[primitive].string, "FROM_UNIXTIME(%u), FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); else strncat(values[primitive].string, "%u, %u", SPACELEFT(values[primitive].string)); where[primitive].type = values[primitive].type = TIMESTAMP; values[primitive].handler = where[primitive].handler = count_timestamp_handler; primitive++; } return primitive; } int MY_compose_static_queries() { int primitives=0, set_primitives=0, set_event_primitives=0, have_flows=0; if (config.what_to_count & COUNT_FLOWS || (config.sql_table_version >= 4 && config.sql_table_version < SQL_TABLE_VERSION_BGP && !config.sql_optimize_clauses)) { config.what_to_count |= COUNT_FLOWS; have_flows = TRUE; if ((config.sql_table_version < 4 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !config.sql_optimize_clauses) { Log(LOG_ERR, "ERROR ( %s/%s ): The accounting of flows requires SQL table v4. Exiting.\n", config.name, config.type); exit_gracefully(1); } } /* "INSERT INTO ... VALUES ... " and "... WHERE ..." stuff */ strncpy(where[primitives].string, " WHERE ", sizeof(where[primitives].string)); snprintf(insert_clause, sizeof(insert_clause), "INSERT INTO `%s` (", config.sql_table); strncpy(values[primitives].string, " VALUES (", sizeof(values[primitives].string)); primitives = MY_evaluate_history(primitives); primitives = sql_evaluate_primitives(primitives); strncpy(insert_counters_clause, ", packets, bytes", SPACELEFT(insert_counters_clause)); if (have_flows) strncat(insert_counters_clause, ", flows", SPACELEFT(insert_counters_clause)); strncat(insert_counters_clause, ")", SPACELEFT(insert_counters_clause)); strncpy(insert_nocounters_clause, ")", SPACELEFT(insert_nocounters_clause)); /* "LOCK ..." stuff */ snprintf(lock_clause, sizeof(lock_clause), "LOCK TABLES `%s` WRITE", config.sql_table); strncpy(unlock_clause, "UNLOCK TABLES", sizeof(unlock_clause)); /* "UPDATE ... SET ..." stuff */ snprintf(update_clause, sizeof(update_clause), "UPDATE `%s` ", config.sql_table); set_primitives = sql_compose_static_set(have_flows); set_event_primitives = sql_compose_static_set_event(); if (config.sql_history) { if (!config.timestamps_since_epoch) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "stamp_updated=NOW()", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); strncat(set_event[set_event_primitives].string, "stamp_updated=NOW()", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_event_handler; set_event_primitives++; } else { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "stamp_updated=UNIX_TIMESTAMP(NOW())", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); strncat(set_event[set_event_primitives].string, "stamp_updated=UNIX_TIMESTAMP(NOW())", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_event_handler; set_event_primitives++; } } return primitives; } void MY_Lock(struct DBdesc *db) { if (!db->fail) { if (mysql_query(db->desc, lock_clause)) { MY_get_errmsg(db); sql_db_errmsg(db); sql_db_fail(db); } } } void MY_Unlock(struct BE_descs *bed) { if (bed->p->connected) mysql_query(bed->p->desc, unlock_clause); if (bed->b->connected) mysql_query(bed->b->desc, unlock_clause); } void MY_DB_Connect(struct DBdesc *db, char *host) { bool reconnect = TRUE; void *mysql_ret = NULL; char *usp = NULL; if (!db->fail) { mysql_init(db->desc); mysql_options(db->desc, MYSQL_OPT_RECONNECT, &reconnect); if (config.sql_conn_ca_file) mysql_ssl_set(db->desc, NULL, NULL, config.sql_conn_ca_file, NULL, NULL); if (host) { usp = strstr(host, "unix:"); } if (usp && usp == host) { usp += 5; /* go right past the 'unix:' string */ mysql_ret = mysql_real_connect(db->desc, NULL, config.sql_user, config.sql_passwd, config.sql_db, FALSE, usp, 0); } else { mysql_ret = mysql_real_connect(db->desc, host, config.sql_user, config.sql_passwd, config.sql_db, config.sql_port, NULL, 0); } if (!mysql_ret) { sql_db_fail(db); MY_get_errmsg(db); sql_db_errmsg(db); } else { sql_db_ok(db); } } } void MY_DB_Close(struct BE_descs *bed) { if (bed->p->connected) mysql_close(bed->p->desc); if (bed->b->connected) mysql_close(bed->b->desc); } void MY_create_dyn_table(struct DBdesc *db, char *buf) { if (!db->fail) { if (mysql_query(db->desc, buf)) { if (mysql_errno(db->desc) != 1050 /* ER_TABLE_EXISTS_ERROR */) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, buf); MY_get_errmsg(db); sql_db_errmsg(db); } } } } void MY_create_backend(struct DBdesc *db) { db->desc = malloc(sizeof(MYSQL)); if (!db->desc) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (MY_create_backend). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memset(db->desc, 0, sizeof(MYSQL)); } void MY_get_errmsg(struct DBdesc *db) { db->errmsg = (char *) mysql_error(db->desc); } void MY_set_callbacks(struct sqlfunc_cb_registry *cbr) { memset(cbr, 0, sizeof(struct sqlfunc_cb_registry)); cbr->connect = MY_DB_Connect; cbr->close = MY_DB_Close; cbr->lock = MY_Lock; cbr->unlock = MY_Unlock; cbr->op = MY_cache_dbop; cbr->create_table = MY_create_dyn_table; cbr->purge = MY_cache_purge; cbr->create_backend = MY_create_backend; } void MY_init_default_values(struct insert_data *idata) { /* Linking database parameters */ if (!config.sql_user) config.sql_user = mysql_user; if (!config.sql_db) config.sql_db = mysql_db; if (!config.sql_passwd) config.sql_passwd = mysql_pwd; if (!config.sql_port) config.sql_port = mysql_prt; if (!config.sql_table) { if (config.sql_table_version == (SQL_TABLE_VERSION_BGP+1)) config.sql_table = mysql_table_bgp; else if (config.sql_table_version == 8) config.sql_table = mysql_table_v8; else if (config.sql_table_version == 7) config.sql_table = mysql_table_v7; else if (config.sql_table_version == 6) config.sql_table = mysql_table_v6; else if (config.sql_table_version == 5) config.sql_table = mysql_table_v5; else if (config.sql_table_version == 4) config.sql_table = mysql_table_v4; else if (config.sql_table_version == 3) config.sql_table = mysql_table_v3; else if (config.sql_table_version == 2) config.sql_table = mysql_table_v2; else config.sql_table = mysql_table; } if (strchr(config.sql_table, '%') || strchr(config.sql_table, '$')) { idata->dyn_table = TRUE; if (!strchr(config.sql_table, '$')) idata->dyn_table_time_only = TRUE; } glob_dyn_table = idata->dyn_table; glob_dyn_table_time_only = idata->dyn_table_time_only; if (config.sql_backup_host) idata->recover = TRUE; if (config.sql_multi_values) { multi_values_buffer = malloc(config.sql_multi_values); if (!multi_values_buffer) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to get enough room (%d) for multi value queries.\n", config.name, config.type, config.sql_multi_values); config.sql_multi_values = FALSE; } memset(multi_values_buffer, 0, config.sql_multi_values); } if (config.sql_locking_style) idata->locks = sql_select_locking_style(config.sql_locking_style); } void MY_mysql_get_version() { #ifdef MARIADB_CLIENT_VERSION_STR printf("MariaDB %s\n", MARIADB_CLIENT_VERSION_STR); #else printf("MySQL %s\n", MYSQL_SERVER_VERSION); #endif } pmacct-1.7.8/src/net_aggr.c0000644000175000017500000015670014354105275014544 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "nfacctd.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "net_aggr.h" #include "jhash.h" /* global variables */ net_func net_funcs[NET_FUNCS_N]; struct networks_table nt; struct networks_cache nc; struct networks_table_entry dummy_entry; int default_route_in_networks4_table; struct networks6_table_entry dummy_entry6; int default_route_in_networks6_table; void load_networks(char *filename, struct networks_table *nt, struct networks_cache *nc) { load_networks4(filename, nt, nc); load_networks6(filename, nt, nc); } void load_networks4(char *filename, struct networks_table *nt, struct networks_cache *nc) { FILE *file; struct networks_table tmp, *tmpt = &tmp; struct networks_table bkt; struct networks_table_metadata *mdt = NULL; char buf[SRVBUFLEN], *bufptr, *delim, *peer_as, *as, *net, *mask, *nh; int rows, eff_rows = 0, j, buflen, fields, prev[NETWORKS_CACHE_DEPTH], current, next; unsigned int index, fake_row = 0; struct stat st; /* dummy & broken on purpose */ memset(&dummy_entry, 0, sizeof(struct networks_table_entry)); dummy_entry.masknum = 255; memset(&bkt, 0, sizeof(bkt)); memset(&tmp, 0, sizeof(tmp)); memset(&st, 0, sizeof(st)); default_route_in_networks4_table = FALSE; /* backing up pre-existing table and cache */ if (nt->num) { bkt.table = nt->table; bkt.num = nt->num; bkt.timestamp = nt->timestamp; nt->table = NULL; nt->num = 0; nt->timestamp = 0; } if (filename) { if ((file = fopen(filename,"r")) == NULL) { if (!(config.nfacctd_net & NF_NET_KEEP && config.nfacctd_as & NF_AS_KEEP)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); return; } Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); goto handle_error; } else { rows = 0; /* 1st step: count rows for table allocation */ while (!feof(file)) { if (fgets(buf, SRVBUFLEN, file) && !iscomment(buf)) rows++; } /* 2nd step: loading data into a temporary table */ if (!freopen(filename, "r", file)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] freopen() failed (%s).\n", config.name, config.type, filename, strerror(errno)); goto handle_error; } /* We have no (valid) rows. We build a zeroed single-row table aimed to complete successfully any further lookup */ if (!rows) { fake_row = TRUE; rows++; } nt->table = malloc(rows*sizeof(struct networks_table_entry)); if (!nt->table) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Networks Table.\n", config.name, config.type, filename); goto handle_error; } tmpt->table = malloc(rows*sizeof(struct networks_table_entry)); if (!tmpt->table) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Temporary Networks Table.\n", config.name, config.type, filename); goto handle_error; } memset(nt->table, 0, rows*sizeof(struct networks_table_entry)); memset(tmpt->table, 0, rows*sizeof(struct networks_table_entry)); rows = 1; while (!feof(file)) { bufptr = buf; memset(buf, 0, SRVBUFLEN); if (fgets(buf, SRVBUFLEN, file)) { if (iscomment(buf)) continue; for (fields = 0, delim = strchr(bufptr, ','); delim; fields++) { bufptr = delim+1; delim = strchr(bufptr, ','); } bufptr = buf; if (fields >= 3) { delim = strchr(bufptr, ','); *delim = '\0'; bufptr = delim+1; } if (fields >= 2) { delim = strchr(bufptr, ','); nh = bufptr; *delim = '\0'; bufptr = delim+1; str_to_addr(nh, &tmpt->table[eff_rows].nh); } else memset(&tmpt->table[eff_rows].nh, 0, sizeof(struct host_addr)); if (fields >= 1) { char *endptr, *endptr2; peer_as = as = NULL; delim = strchr(bufptr, ','); if (delim) { as = bufptr; *delim = '\0'; bufptr = delim+1; delim = strchr(as, '_'); if (delim) { *delim = '\0'; peer_as = as; as = delim+1; } } else tmpt->table[eff_rows].peer_as = 0; if (as) tmpt->table[eff_rows].as = strtoul(as, &endptr, 10); else tmpt->table[eff_rows].as = 0; if (peer_as) tmpt->table[eff_rows].peer_as = strtoul(peer_as, &endptr2, 10); else tmpt->table[eff_rows].peer_as = 0; } else { tmpt->table[eff_rows].peer_as = 0; tmpt->table[eff_rows].as = 0; } if (!sanitize_buf_net(filename, bufptr, rows)) { delim = strchr(bufptr, '/'); *delim = '\0'; net = bufptr; mask = delim+1; if (!inet_aton(net, (struct in_addr *) &tmpt->table[eff_rows].net)) { memset(&tmpt->table[eff_rows], 0, sizeof(struct networks_table_entry)); goto cycle_end; } buflen = strlen(mask); for (j = 0; j < buflen; j++) { if (!isdigit(mask[j])) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Invalid network mask '%s'.\n", config.name, config.type, filename, rows, mask); memset(&tmpt->table[eff_rows], 0, sizeof(struct networks_table_entry)); goto cycle_end; } } index = atoi(mask); if (index > 32) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Invalid network mask '%d'.\n", config.name, config.type, filename, rows, index); memset(&tmpt->table[eff_rows], 0, sizeof(struct networks_table_entry)); goto cycle_end; } tmpt->table[eff_rows].net = ntohl(tmpt->table[eff_rows].net); tmpt->table[eff_rows].mask = (index == 32) ? 0xffffffffUL : ~(0xffffffffUL >> index); tmpt->table[eff_rows].masknum = index; tmpt->table[eff_rows].net &= tmpt->table[eff_rows].mask; /* enforcing mask on given network */ eff_rows++; } } cycle_end: rows++; } fclose(file); stat(filename, &st); /* We have no (valid) rows. We build a zeroed single-row table aimed to complete successfully any further lookup; unless we are configured to work as a filter */ if (!eff_rows && !config.networks_file_filter) eff_rows++; /* 3rd step: sorting table and removing dupes */ merge_sort(filename, tmpt->table, 0, eff_rows); tmpt->num = eff_rows; remove_dupes(filename, tmpt, FALSE); /* 4th step: collecting informations in the sorted table; we wish to handle networks-in-networks hierarchically */ /* 4a building hierarchies */ mdt = malloc(tmpt->num*sizeof(struct networks_table_metadata)); if (!mdt) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Metadata Networks Table.\n", config.name, config.type, filename); goto handle_error; } memset(mdt, 0, tmpt->num*sizeof(struct networks_table_metadata)); if (tmpt->num) { for (index = 0; index < (tmpt->num-1); index++) { u_int32_t net; int x; for (x = index+1; x < tmpt->num; x++) { net = tmpt->table[x].net; net &= tmpt->table[index].mask; if (net == tmpt->table[index].net) { mdt[x].level++; mdt[index].childs++; } else break; } } } /* 4b retrieving root entries number */ for (index = 0, eff_rows = 0; index < tmpt->num; index++) { if (mdt[index].level == 0) eff_rows++; } nt->num = eff_rows; /* 4c adjusting child counters: each parent has to know only the number of its directly attached childs and not the whole hierarchy */ for (index = 0; index < tmpt->num; index++) { int x, eff_childs = 0; for (x = index+1; x < tmpt->num; x++) { if (mdt[index].level == mdt[x].level) break; else if (mdt[index].level == (mdt[x].level-1)) eff_childs++; } mdt[index].childs = eff_childs; } /* 5a step: building final networks table */ for (index = 0, current = 0, next = 0; index < tmpt->num; index++) { if (!index) { current = 0; next = eff_rows; memset(&prev, 0, 32); memcpy(&nt->table[current], &tmpt->table[index], sizeof(struct networks_table_entry)); } else { if (mdt[index].level == mdt[index-1].level) current++; /* do nothing: we have only to copy our element */ else if (mdt[index].level > mdt[index-1].level) { /* we encountered a child */ if (mdt[index].level > NETWORKS_CACHE_DEPTH) { Log(LOG_ERR, "ERROR ( %s/%s ): Networks Cache exceeds maximum depth (%d).\n", config.name, config.type, NETWORKS_CACHE_DEPTH); goto handle_error; } nt->table[current].childs_table.table = &nt->table[next]; nt->table[current].childs_table.num = mdt[index-1].childs; prev[mdt[index-1].level] = current; current = next; next += mdt[index-1].childs; } else { /* going back to parent level */ current = prev[mdt[index].level]; current++; } memcpy(&nt->table[current], &tmpt->table[index], sizeof(struct networks_table_entry)); } } /* 5b step: debug and default route detection */ index = 0; while (!fake_row && index < tmpt->num) { if (config.debug) { struct host_addr net_bin; char nh_string[INET6_ADDRSTRLEN]; char net_string[INET6_ADDRSTRLEN]; addr_to_str(nh_string, &nt->table[index].nh); net_bin.family = AF_INET; net_bin.address.ipv4.s_addr = htonl(nt->table[index].net); addr_to_str(net_string, &net_bin); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] v4 nh: %s peer asn: %u asn: %u net: %s mask: %u\n", config.name, config.type, filename, nh_string, nt->table[index].peer_as, nt->table[index].as, net_string, nt->table[index].masknum); } if (!nt->table[index].mask) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] v4 contains a default route\n", config.name, config.type, filename); default_route_in_networks4_table = TRUE; } index++; } /* 6th step: create networks cache BUT only for the first time */ if (!nc->cache) { if (!config.networks_cache_entries) nc->num = NETWORKS_CACHE_ENTRIES; else nc->num = config.networks_cache_entries; nc->cache = (struct networks_cache_entry *) malloc(nc->num*sizeof(struct networks_cache_entry)); if (!nc->cache) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed while building Networks Cache.\n", config.name, config.type); goto handle_error; } else Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] IPv4 Networks Cache successfully created: %u entries.\n", config.name, config.type, filename, nc->num); } /* 7th step: freeing resources */ memset(nc->cache, 0, nc->num*sizeof(struct networks_cache_entry)); free(tmpt->table); free(mdt); if (bkt.table) free(bkt.table); /* 8th step: setting timestamp */ nt->timestamp = st.st_mtime; } } /* filename check to not print nulls as load_networks() may not be secured inside an if statement */ if (filename) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, config.type, filename); } return; /* error handling: if we have a copy of the old table we will rollback it; otherwise we just take the exit lane. XXX: actually we are just able to recover malloc() troubles and missing files; efforts should be pushed in the validation of the new table. */ handle_error: if (tmpt->table) free(tmpt->table); if (mdt) free(mdt); if (bkt.num) { if (!nt->table) { memcpy(nt, &bkt, sizeof(struct networks_table)); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back the old Networks Table.\n", config.name, config.type, filename); /* we update the timestamp to avoid loops */ stat(filename, &st); nt->timestamp = st.st_mtime; } } else exit_gracefully(1); } /* sort the (sub)array v from start to end */ void merge_sort(char *filename, struct networks_table_entry *table, int start, int end) { int middle; /* no elements to sort */ if ((start == end) || (start == end-1)) return; /* find the middle of the array, splitting it into two subarrays */ middle = (start+end)/2; /* sort the subarray from start..middle */ merge_sort(filename, table, start, middle); /* sort the subarray from middle..end */ merge_sort(filename, table, middle, end); /* merge the two sorted halves */ merge(filename, table, start, middle, end); } /* merge the subarray v[start..middle] with v[middle..end], placing the result back into v. */ void merge(char *filename, struct networks_table_entry *table, int start, int middle, int end) { struct networks_table_entry *v1, *v2; int v1_n, v2_n, v1_index, v2_index, i, s = sizeof(struct networks_table_entry); v1_n = middle-start; v2_n = end-middle; v1 = malloc(v1_n*s); v2 = malloc(v2_n*s); if ((!v1) || (!v2)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed in merge().\n", config.name, config.type, filename); exit_gracefully(1); } for (i=0; inum-1; u_int32_t net, addrh = ntohl(a->address.ipv4.s_addr), addr = a->address.ipv4.s_addr; struct networks_table_entry *ret; ret = networks_cache_search(nc, &addr); if (ret) { if (ret->masknum == 255) return NULL; /* dummy entry identification */ else return ret; } while (low <= high) { mid = (low+high)/2; net = addrh; net &= nt->table[mid].mask; if (net < nt->table[mid].net) { high = mid-1; continue; } else if (net > nt->table[mid].net) { low = mid+1; continue; } /* It's assumed we've found our element */ if (nt->table[mid].childs_table.table) { ret = binsearch(&nt->table[mid].childs_table, nc, a); if (!ret) { ret = &nt->table[mid]; networks_cache_insert(nc, &addr, &nt->table[mid]); } } else { ret = &nt->table[mid]; networks_cache_insert(nc, &addr, &nt->table[mid]); } return ret; } networks_cache_insert(nc, &addr, &dummy_entry); return NULL; } void remove_dupes(char *filename, struct networks_table *nt, int want_v6) { int i, j; if (!want_v6) { for (i = 0, j = 0; i < nt->num; i++) { if (i < (nt->num - 1) && nt->table[i].net == nt->table[i + 1].net && nt->table[i].mask == nt->table[i + 1].mask) { continue; } memcpy(&nt->table[j], &nt->table[i], sizeof(struct networks_table_entry)); j++; } nt->num = j; } else { for (i = 0, j = 0; i < nt->num6; i++) { if (i < (nt->num6 - 1) && !memcmp(nt->table6[i].net, nt->table6[i + 1].net, sizeof(nt->table6[i].net)) && !memcmp(nt->table6[i].mask, nt->table6[i + 1].mask, sizeof(nt->table6[i].mask))) { continue; } memcpy(&nt->table6[j], &nt->table6[i], sizeof(struct networks6_table_entry)); j++; } nt->num6 = j; } } void networks_cache_insert(struct networks_cache *nc, u_int32_t *key, struct networks_table_entry *result) { struct networks_cache_entry *ptr; ptr = &nc->cache[*key % nc->num]; ptr->key = *key; ptr->result = result; } struct networks_table_entry *networks_cache_search(struct networks_cache *nc, u_int32_t *key) { struct networks_cache_entry *ptr; ptr = &nc->cache[*key % nc->num]; if (ptr->key == *key) return ptr->result; else return NULL; } void set_net_funcs(struct networks_table *nt) { u_int8_t count = 0; memset(&net_funcs, 0, sizeof(net_funcs)); if ((config.nfacctd_net & NF_NET_STATIC) && config.networks_mask) { int j, index = config.networks_mask; memset(nt->maskbits, 0, sizeof(nt->maskbits)); for (j = 0; j < 4 && index >= 32; j++, index -= 32) nt->maskbits[j] = 0xffffffffU; if (j < 4 && index) nt->maskbits[j] = ~(0xffffffffU >> index); if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { net_funcs[count] = mask_static_src_ipaddr; count++; } if (config.what_to_count & (COUNT_DST_NET|COUNT_SUM_NET)) { net_funcs[count] = mask_static_dst_ipaddr; count++; } if (config.what_to_count & COUNT_SRC_NMASK) { net_funcs[count] = copy_src_mask; count++; } if (config.what_to_count & COUNT_DST_NMASK) { net_funcs[count] = copy_dst_mask; count++; } } if ((!nt->num) && (!nt->num6)) goto exit_lane; net_funcs[count] = init_net_funcs; count++; net_funcs[count] = search_src_ip; count++; if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { net_funcs[count] = search_src_host; count++; } if (config.nfacctd_net & NF_NET_NEW) { net_funcs[count] = search_src_nmask; count++; } if (config.nfacctd_as & NF_AS_NEW) { if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) { net_funcs[count] = search_src_as; count++; } } if (config.nfacctd_as & NF_AS_NEW) { if (config.what_to_count & COUNT_PEER_SRC_AS) { net_funcs[count] = search_peer_src_as; count++; } } if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { net_funcs[count] = mask_src_ipaddr; count++; } else { net_funcs[count] = clear_src_net; count++; } if (!(config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST))) { net_funcs[count] = clear_src_host; count++; } if (!(config.what_to_count & COUNT_SRC_NMASK)) { net_funcs[count] = clear_src_nmask; count++; } net_funcs[count] = search_dst_ip; count++; if (config.what_to_count & (COUNT_DST_HOST|COUNT_SUM_HOST)) { net_funcs[count] = search_dst_host; count++; } if (config.nfacctd_net & NF_NET_NEW) { net_funcs[count] = search_dst_nmask; count++; } if (config.nfacctd_as & NF_AS_NEW) { if (config.what_to_count & (COUNT_DST_AS|COUNT_SUM_AS)) { net_funcs[count] = search_dst_as; count++; } } if (config.nfacctd_as & NF_AS_NEW) { if (config.what_to_count & COUNT_PEER_DST_AS) { net_funcs[count] = search_peer_dst_as; count++; } } if (config.nfacctd_net & NF_NET_NEW) { if (config.what_to_count & COUNT_PEER_DST_IP) { net_funcs[count] = search_peer_dst_ip; count++; } } if (config.what_to_count & (COUNT_DST_NET|COUNT_SUM_NET)) { net_funcs[count] = mask_dst_ipaddr; count++; } else { net_funcs[count] = clear_dst_net; count++; } if (!(config.what_to_count & (COUNT_DST_HOST|COUNT_SUM_HOST))) { net_funcs[count] = clear_dst_host; count++; } if (!(config.what_to_count & COUNT_DST_NMASK)) { net_funcs[count] = clear_dst_nmask; count++; } assert(count < NET_FUNCS_N); return; /* no networks_file loaded: apply masks and clean-up */ exit_lane: if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { net_funcs[count] = mask_src_ipaddr; count++; } else { net_funcs[count] = clear_src_net; count++; } if (!(config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST))) { net_funcs[count] = clear_src_host; count++; } if (config.what_to_count & COUNT_DST_NET) { net_funcs[count] = mask_dst_ipaddr; count++; } else { net_funcs[count] = clear_dst_net; count++; } if (!(config.what_to_count & (COUNT_DST_HOST|COUNT_SUM_HOST))) { net_funcs[count] = clear_dst_host; count++; } if (!(config.what_to_count & COUNT_SRC_NMASK)) { net_funcs[count] = clear_src_nmask; count++; } if (!(config.what_to_count & COUNT_DST_NMASK)) { net_funcs[count] = clear_dst_nmask; count++; } assert(count < NET_FUNCS_N); } void init_net_funcs(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { memset(nfd, 0, sizeof(struct networks_file_data)); } void clear_src_nmask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { p->src_nmask = 0; } void clear_dst_nmask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { p->dst_nmask = 0; } void mask_src_ipaddr(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { u_int32_t maskbits[4], addrh[4]; u_int8_t j, mask; memset(maskbits, 0,sizeof(maskbits)); mask = p->src_nmask; if (config.networks_no_mask_if_zero && !mask) mask = 128; for (j = 0; j < 4 && mask >= 32; j++, mask -= 32) maskbits[j] = 0xffffffffU; if (j < 4 && mask) maskbits[j] = ~(0xffffffffU >> mask); if (p->src_ip.family == AF_INET) { addrh[0] = ntohl(p->src_ip.address.ipv4.s_addr); addrh[0] &= maskbits[0]; p->src_net.address.ipv4.s_addr = htonl(addrh[0]); p->src_net.family = p->src_ip.family; } else if (p->src_ip.family == AF_INET6) { memcpy(&addrh, (void *) pm_ntohl6(&p->src_ip.address.ipv6), IP6AddrSz); for (j = 0; j < 4; j++) addrh[j] &= maskbits[j]; memcpy(&p->src_net.address.ipv6, (void *) pm_htonl6(addrh), IP6AddrSz); p->src_net.family = p->src_ip.family; } } void mask_static_src_ipaddr(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { u_int32_t addrh[4]; u_int8_t j; if (p->src_ip.family == AF_INET) { addrh[0] = ntohl(p->src_ip.address.ipv4.s_addr); addrh[0] &= nt->maskbits[0]; p->src_net.address.ipv4.s_addr = htonl(addrh[0]); p->src_net.family = p->src_ip.family; } else if (p->src_ip.family == AF_INET6) { memcpy(&addrh, (void *) pm_ntohl6(&p->src_ip.address.ipv6), IP6AddrSz); for (j = 0; j < 4; j++) addrh[j] &= nt->maskbits[j]; memcpy(&p->src_net.address.ipv6, (void *) pm_htonl6(addrh), IP6AddrSz); p->src_net.family = p->src_ip.family; } } void mask_dst_ipaddr(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { u_int32_t maskbits[4], addrh[4]; u_int8_t j, mask; memset(maskbits, 0,sizeof(maskbits)); mask = p->dst_nmask; if (config.networks_no_mask_if_zero && !mask) mask = 128; for (j = 0; j < 4 && mask >= 32; j++, mask -= 32) maskbits[j] = 0xffffffffU; if (j < 4 && mask) maskbits[j] = ~(0xffffffffU >> mask); if (p->dst_ip.family == AF_INET) { addrh[0] = ntohl(p->dst_ip.address.ipv4.s_addr); addrh[0] &= maskbits[0]; p->dst_net.address.ipv4.s_addr = htonl(addrh[0]); p->dst_net.family = p->dst_ip.family; } else if (p->dst_ip.family == AF_INET6) { memcpy(&addrh, (void *) pm_ntohl6(&p->dst_ip.address.ipv6), IP6AddrSz); for (j = 0; j < 4; j++) addrh[j] &= maskbits[j]; memcpy(&p->dst_net.address.ipv6, (void *) pm_htonl6(addrh), IP6AddrSz); p->dst_net.family = p->dst_ip.family; } } void mask_static_dst_ipaddr(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { u_int32_t addrh[4]; u_int8_t j; if (p->dst_ip.family == AF_INET) { addrh[0] = ntohl(p->dst_ip.address.ipv4.s_addr); addrh[0] &= nt->maskbits[0]; p->dst_net.address.ipv4.s_addr = htonl(addrh[0]); p->dst_net.family = p->dst_ip.family; } else if (p->dst_ip.family == AF_INET6) { memcpy(&addrh, (void *) pm_ntohl6(&p->dst_ip.address.ipv6), IP6AddrSz); for (j = 0; j < 4; j++) addrh[j] &= nt->maskbits[j]; memcpy(&p->dst_net.address.ipv6, (void *) pm_htonl6(addrh), IP6AddrSz); p->dst_net.family = p->dst_ip.family; } } void copy_src_mask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { p->src_nmask = config.networks_mask; } void copy_dst_mask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { p->dst_nmask = config.networks_mask; } void search_src_ip(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { if (p->src_ip.family == AF_INET) { nfd->family = AF_INET; nfd->entry = (u_char *) binsearch(nt, nc, &p->src_ip); } else if (p->src_ip.family == AF_INET6) { nfd->family = AF_INET6; nfd->entry = (u_char *) binsearch6(nt, nc, &p->src_ip); } else { nfd->family = 0; nfd->entry = NULL; } } void search_dst_ip(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { if (p->dst_ip.family == AF_INET) { nfd->family = AF_INET; nfd->entry = (u_char *) binsearch(nt, nc, &p->dst_ip); } else if (p->dst_ip.family == AF_INET6) { nfd->family = AF_INET6; nfd->entry = (u_char *) binsearch6(nt, nc, &p->dst_ip); } else { nfd->family = 0; nfd->entry = NULL; } } void search_src_host(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (!res) { if (config.networks_file_filter) p->src_ip.address.ipv4.s_addr = 0; } else { if (!res->net && !default_route_in_networks4_table) { if (config.networks_file_filter) p->src_ip.address.ipv4.s_addr = 0; /* it may have been cached */ } } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (!res6) { if (config.networks_file_filter) memset(&p->src_ip.address.ipv6, 0, IP6AddrSz); } else { if (!res6->net[0] && !default_route_in_networks6_table) { if (config.networks_file_filter) memset(&p->src_ip.address.ipv6, 0, IP6AddrSz); /* it may have been cached */ } } } } void search_dst_host(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp,struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (!res) { if (config.networks_file_filter) p->dst_ip.address.ipv4.s_addr = 0; } else { if (!res->net && !default_route_in_networks4_table) { if (config.networks_file_filter) p->dst_ip.address.ipv4.s_addr = 0; /* it may have been cached */ } } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (!res6) { if (config.networks_file_filter) memset(&p->dst_ip.address.ipv6, 0, IP6AddrSz); } else { if (!res6->net[0] && !default_route_in_networks6_table) { if (config.networks_file_filter) memset(&p->dst_ip.address.ipv6, 0, IP6AddrSz); /* it may have been cached */ } } } } void search_src_nmask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; u_int8_t mask = 0, default_route_in_networks_table = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; default_route_in_networks_table = default_route_in_networks4_table; if (!res) mask = 0; else mask = res->masknum; } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; default_route_in_networks_table = default_route_in_networks6_table; if (!res6) mask = 0; else mask = res6->masknum; } if (!(config.nfacctd_net & NF_NET_FALLBACK)) { p->src_nmask = mask; } else { if (config.networks_file_no_lpm) { if (mask) p->src_nmask = mask; } else { if (mask > p->src_nmask) p->src_nmask = mask; } if (config.networks_file_filter && !mask && !default_route_in_networks_table) { p->src_nmask = 0; nfd->zero_src_nmask = TRUE; } } } void search_dst_nmask(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; u_int8_t mask = 0, default_route_in_networks_table = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; default_route_in_networks_table = default_route_in_networks4_table; if (!res) mask = 0; else mask = res->masknum; } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; default_route_in_networks_table = default_route_in_networks6_table; if (!res6) mask = 0; else mask = res6->masknum; } if (!(config.nfacctd_net & NF_NET_FALLBACK)) { p->dst_nmask = mask; } else { if (config.networks_file_no_lpm) { if (mask) p->dst_nmask = mask; } else { if (mask > p->dst_nmask) p->dst_nmask = mask; } if (config.networks_file_filter && !mask && !default_route_in_networks_table) { p->dst_nmask = 0; nfd->zero_dst_nmask = TRUE; } } } void search_src_as(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; as_t as = 0; u_int8_t mask = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (res) { as = res->as; mask = res->masknum; } else { as = 0; mask = 0; } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (res6) { as = res6->as; mask = res6->masknum; } else { as = 0; mask = 0; } } if (!(config.nfacctd_as & NF_AS_FALLBACK)) p->src_as = as; else { if (config.networks_file_no_lpm) { if (mask) p->src_as = as; } else { if (mask >= p->src_nmask) p->src_as = as; } } } void search_dst_as(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; as_t as = 0; u_int8_t mask = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (res) { as = res->as; mask = res->masknum; } else { as = 0; mask = 0; } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (res6) { as = res6->as; mask = res6->masknum; } else { as = 0; mask = 0; } } if (!(config.nfacctd_as & NF_AS_FALLBACK)) p->dst_as = as; else { if (config.networks_file_no_lpm) { if (mask) p->dst_as = as; } else { if (mask >= p->dst_nmask) p->dst_as = as; } } } void search_peer_src_as(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; as_t as = 0; u_int8_t mask = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (res) { as = res->peer_as; mask = res->masknum; } else { as = 0; mask = 0; } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (res6) { as = res6->peer_as; mask = res6->masknum; } else { as = 0; mask = 0; } } if (!(config.nfacctd_as & NF_AS_FALLBACK)) { if (pbgp) pbgp->peer_src_as = as; } else { if (config.networks_file_no_lpm) { if (mask && pbgp) pbgp->peer_src_as = as; } else { if (mask >= p->src_nmask) { if (pbgp) pbgp->peer_src_as = as; } } } } void search_peer_dst_as(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res; struct networks6_table_entry *res6; as_t as = 0; u_int8_t mask = 0; if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (res) { as = res->peer_as; mask = res->masknum; } else { as = 0; mask = 0; } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (res6) { as = res6->peer_as; mask = res6->masknum; } else { as = 0; mask = 0; } } if (!(config.nfacctd_as & NF_AS_FALLBACK)) { if (pbgp) pbgp->peer_dst_as = as; } else { if (config.networks_file_no_lpm) { if (mask && pbgp) pbgp->peer_dst_as = as; } else { if (mask >= p->dst_nmask) { if (pbgp) pbgp->peer_dst_as = as; } } } } void search_peer_dst_ip(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { struct networks_table_entry *res = NULL; struct networks6_table_entry *res6 = NULL; struct host_addr nh; u_int8_t mask = 0; if (pbgp) { if (nfd->family == AF_INET) { res = (struct networks_table_entry *) nfd->entry; if (res) { memcpy(&nh, &res->nh, sizeof(struct host_addr)); mask = res->masknum; } else { memset(&nh, 0, sizeof(struct host_addr)); mask = 0; } } else if (nfd->family == AF_INET6) { res6 = (struct networks6_table_entry *) nfd->entry; if (res6) { memcpy(&nh, &res6->nh, sizeof(struct host_addr)); mask = res6->masknum; } else { memset(&nh, 0, sizeof(struct host_addr)); mask = 0; } } if (!(config.nfacctd_net & NF_NET_FALLBACK)) { memcpy(&pbgp->peer_dst_ip, &nh, sizeof(struct host_addr)); } else { if (config.networks_file_no_lpm) { if (mask && pbgp) memcpy(&pbgp->peer_dst_ip, &nh, sizeof(struct host_addr)); } else { if (mask >= p->dst_nmask) { if (pbgp) memcpy(&pbgp->peer_dst_ip, &nh, sizeof(struct host_addr)); } } } } } void clear_src_host(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { memset(&p->src_ip, 0, HostAddrSz); } void clear_dst_host(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { memset(&p->dst_ip, 0, HostAddrSz); } void clear_src_net(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { memset(&p->src_net, 0, HostAddrSz); } void clear_dst_net(struct networks_table *nt, struct networks_cache *nc, struct pkt_primitives *p, struct pkt_bgp_primitives *pbgp, struct networks_file_data *nfd) { memset(&p->dst_net, 0, HostAddrSz); } as_t search_pretag_src_as(struct networks_table *nt, struct networks_cache *nc, struct packet_ptrs *pptrs) { struct networks_table_entry *res; struct host_addr addr; struct networks6_table_entry *res6; if (pptrs->l3_proto == ETHERTYPE_IP) { addr.family = AF_INET; addr.address.ipv4.s_addr = ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr; res = binsearch(nt, nc, &addr); if (!res) return 0; else return res->as; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { addr.family = AF_INET6; memcpy(&addr.address.ipv6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, IP6AddrSz); res6 = binsearch6(nt, nc, &addr); if (!res6) return 0; else return res6->as; } return 0; } as_t search_pretag_dst_as(struct networks_table *nt, struct networks_cache *nc, struct packet_ptrs *pptrs) { struct networks_table_entry *res; struct host_addr addr; struct networks6_table_entry *res6; if (pptrs->l3_proto == ETHERTYPE_IP) { addr.family = AF_INET; addr.address.ipv4.s_addr = ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr; res = binsearch(nt, nc, &addr); if (!res) return 0; else return res->as; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { addr.family = AF_INET6; memcpy(&addr.address.ipv6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, IP6AddrSz); res6 = binsearch6(nt, nc, &addr); if (!res6) return 0; else return res6->as; } return 0; } void load_networks6(char *filename, struct networks_table *nt, struct networks_cache *nc) { FILE *file; struct networks_table tmp, *tmpt = &tmp; struct networks_table bkt; struct networks_table_metadata *mdt = 0; char buf[SRVBUFLEN], *bufptr, *delim, *peer_as, *as, *net, *mask, *nh; int rows, eff_rows = 0, j, buflen, fields, prev[NETWORKS_CACHE_DEPTH], current, next; unsigned int index, fake_row = 0; u_int32_t tmpmask[4], tmpnet[4]; struct stat st; /* dummy & broken on purpose */ memset(&dummy_entry6, 0, sizeof(struct networks6_table_entry)); dummy_entry6.masknum = 255; memset(&bkt, 0, sizeof(bkt)); memset(&tmp, 0, sizeof(tmp)); memset(&st, 0, sizeof(st)); default_route_in_networks6_table = FALSE; /* backing up pre-existing table and cache */ if (nt->num6) { bkt.table6 = nt->table6; bkt.num6 = nt->num6; bkt.timestamp = nt->timestamp; nt->table6 = 0; nt->num6 = 0; nt->timestamp = 0; } if (filename) { if ((file = fopen(filename,"r")) == NULL) { if (!(config.nfacctd_net & NF_NET_KEEP && config.nfacctd_as & NF_AS_KEEP)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); return; } Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); exit_gracefully(1); } else { rows = 0; /* 1st step: count rows for table allocation */ while (!feof(file)) { if (fgets(buf, SRVBUFLEN, file) && !iscomment(buf)) rows++; } /* 2nd step: loading data into a temporary table */ if (!freopen(filename, "r", file)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] freopen() failed (%s).\n", config.name, config.type, filename, strerror(errno)); goto handle_error; } /* We have no (valid) rows. We build a zeroed single-row table aimed to complete successfully any further lookup */ if (!rows) { fake_row = TRUE; rows++; } nt->table6 = malloc(rows*sizeof(struct networks6_table_entry)); if (!nt->table6) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Networks Table.\n", config.name, config.type, filename); goto handle_error; } tmpt->table6 = malloc(rows*sizeof(struct networks6_table_entry)); if (!tmpt->table6) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Temporary Networks Table.\n", config.name, config.type, filename); goto handle_error; } memset(nt->table6, 0, rows*sizeof(struct networks6_table_entry)); memset(tmpt->table6, 0, rows*sizeof(struct networks6_table_entry)); rows = 1; while (!feof(file)) { bufptr = buf; memset(buf, 0, SRVBUFLEN); if (fgets(buf, SRVBUFLEN, file)) { if (iscomment(buf)) continue; for (fields = 0, delim = strchr(bufptr, ','); delim; fields++) { bufptr = delim+1; delim = strchr(bufptr, ','); } bufptr = buf; if (fields >= 3) { delim = strchr(bufptr, ','); *delim = '\0'; bufptr = delim+1; } if (fields >= 2) { delim = strchr(bufptr, ','); nh = bufptr; *delim = '\0'; bufptr = delim+1; str_to_addr(nh, &tmpt->table6[eff_rows].nh); } else memset(&tmpt->table6[eff_rows].nh, 0, sizeof(struct host_addr)); if (fields >= 1) { char *endptr, *endptr2; peer_as = as = NULL; delim = strchr(bufptr, ','); if (delim) { as = bufptr; *delim = '\0'; bufptr = delim+1; delim = strchr(as, '_'); if (delim) { *delim = '\0'; peer_as = as; as = delim+1; } } else tmpt->table6[eff_rows].peer_as = 0; if (as) tmpt->table6[eff_rows].as = strtoul(as, &endptr, 10); else tmpt->table6[eff_rows].as = 0; if (peer_as) tmpt->table6[eff_rows].peer_as = strtoul(peer_as, &endptr2, 10); else tmpt->table6[eff_rows].peer_as = 0; } else { tmpt->table6[eff_rows].peer_as = 0; tmpt->table6[eff_rows].as = 0; } if (!sanitize_buf_net(filename, bufptr, rows)) { delim = strchr(bufptr, '/'); *delim = '\0'; net = bufptr; mask = delim+1; /* XXX: error signallation */ if (!inet_pton(AF_INET6, net, &tmpnet)) { memset(&tmpt->table6[eff_rows], 0, sizeof(struct networks6_table_entry)); goto cycle_end; } buflen = strlen(mask); for (j = 0; j < buflen; j++) { if (!isdigit(mask[j])) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Invalid network mask '%s'.\n", config.name, config.type, filename, rows, mask); memset(&tmpt->table6[eff_rows], 0, sizeof(struct networks6_table_entry)); goto cycle_end; } } index = atoi(mask); if (index > 128) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Invalid network mask '%d'.\n", config.name, config.type, filename, rows, index); memset(&tmpt->table6[eff_rows], 0, sizeof(struct networks6_table_entry)); goto cycle_end; } memset(&tmpmask, 0, sizeof(tmpmask)); tmpt->table6[eff_rows].masknum = index; for (j = 0; j < 4 && index >= 32; j++, index -= 32) tmpmask[j] = 0xffffffffU; if (j < 4 && index) tmpmask[j] = ~(0xffffffffU >> index); for (j = 0; j < 4; j++) tmpnet[j] = ntohl(tmpnet[j]); for (j = 0; j < 4; j++) tmpnet[j] &= tmpmask[j]; /* enforcing mask on given network */ memcpy(&tmpt->table6[eff_rows].net, tmpnet, IP6AddrSz); memcpy(&tmpt->table6[eff_rows].mask, tmpmask, IP6AddrSz); eff_rows++; } } cycle_end: rows++; } fclose(file); stat(filename, &st); /* We have no (valid) rows. We build a zeroed single-row table aimed to complete successfully any further lookup; unless we are configured to work as a filter */ if (!eff_rows && !config.networks_file_filter) eff_rows++; /* 3rd step: sorting table and removing dupes */ merge_sort6(filename, tmpt->table6, 0, eff_rows); tmpt->num6 = eff_rows; remove_dupes(filename, tmpt, TRUE); /* 4th step: collecting informations in the sorted table; we wish to handle networks-in-networks hierarchically */ /* 4a building hierarchies */ mdt = malloc(tmpt->num6*sizeof(struct networks_table_metadata)); if (!mdt) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Metadata Networks Table.\n", config.name, config.type, filename); goto handle_error; } memset(mdt, 0, tmpt->num6*sizeof(struct networks_table_metadata)); if (tmpt->num6) { for (index = 0; index < (tmpt->num6-1); index++) { u_int32_t net[4]; int x, chunk; for (x = index+1; x < tmpt->num6; x++) { memcpy(&net, &tmpt->table6[x].net, IP6AddrSz); for (chunk = 0; chunk < 4; chunk++) net[chunk] &= tmpt->table6[index].mask[chunk]; for (chunk = 0; chunk < 4; chunk++) { if (net[chunk] == tmpt->table6[index].net[chunk]) { if (chunk == 3) { mdt[x].level++; mdt[index].childs++; } } else break; } } } } /* 4b retrieving root entries number */ for (index = 0, eff_rows = 0; index < tmpt->num6; index++) { if (mdt[index].level == 0) eff_rows++; } nt->num6 = eff_rows; /* 4c adjusting child counters: each parent has to know only the number of its directly attached childs and not the whole hierarchy */ for (index = 0; index < tmpt->num6; index++) { int x, eff_childs = 0; for (x = index+1; x < tmpt->num6; x++) { if (mdt[index].level == mdt[x].level) break; else if (mdt[index].level == (mdt[x].level-1)) eff_childs++; } mdt[index].childs = eff_childs; } /* 5a step: building final networks table */ for (index = 0, current = 0, next = 0; index < tmpt->num6; index++) { if (!index) { current = 0; next = eff_rows; memset(&prev, 0, 32); memcpy(&nt->table6[current], &tmpt->table6[index], sizeof(struct networks6_table_entry)); } else { if (mdt[index].level == mdt[index-1].level) current++; /* do nothing: we have only to copy our element */ else if (mdt[index].level > mdt[index-1].level) { /* we encountered a child */ if (mdt[index].level > NETWORKS_CACHE_DEPTH) { Log(LOG_ERR, "ERROR ( %s/%s ): IPv6 Networks Cache exceeds maximum depth (%d).\n", config.name, config.type, NETWORKS_CACHE_DEPTH); goto handle_error; } nt->table6[current].childs_table.table6 = &nt->table6[next]; nt->table6[current].childs_table.num6 = mdt[index-1].childs; prev[mdt[index-1].level] = current; current = next; next += mdt[index-1].childs; } else { /* going back to parent level */ current = prev[mdt[index].level]; current++; } memcpy(&nt->table6[current], &tmpt->table6[index], sizeof(struct networks6_table_entry)); } } /* 5b step: debug and default route detection */ index = 0; while (!fake_row && index < tmpt->num6) { if (config.debug) { struct host_addr net_bin; char nh_string[INET6_ADDRSTRLEN]; char net_string[INET6_ADDRSTRLEN]; net_bin.family = AF_INET6; memcpy(&net_bin.address.ipv6, (void *) pm_htonl6(&nt->table6[index].net), IP6AddrSz); addr_to_str(net_string, &net_bin); addr_to_str(nh_string, &nt->table6[index].nh); Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] v6 nh: %s peer_asn: %u asn: %u net: %s mask: %u\n", config.name, config.type, filename, nh_string, nt->table6[index].peer_as, nt->table6[index].as, net_string, nt->table6[index].masknum); } if (!nt->table6[index].mask[0] && !nt->table6[index].mask[1] && !nt->table6[index].mask[2] && !nt->table6[index].mask[3]) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] v6 contains a default route\n", config.name, config.type, filename); default_route_in_networks6_table = TRUE; } index++; } /* 6th step: create networks cache BUT only for the first time */ if (!nc->cache6) { if (!config.networks_cache_entries) nc->num6 = NETWORKS6_CACHE_ENTRIES; else nc->num6 = config.networks_cache_entries; nc->cache6 = (struct networks6_cache_entry *) malloc(nc->num6*sizeof(struct networks6_cache_entry)); if (!nc->cache6) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed while building Networks Cache.\n", config.name, config.type, filename); goto handle_error; } else Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] IPv6 Networks Cache successfully created: %u entries.\n", config.name, config.type, filename, nc->num6); } /* 7th step: freeing resources */ memset(nc->cache6, 0, nc->num6*sizeof(struct networks6_cache_entry)); free(tmpt->table6); free(mdt); if (bkt.table6) free(bkt.table6); /* 8th step: setting timestamp */ nt->timestamp = st.st_mtime; } } return; /* error handling: if we have a copy of the old table we will rollback it; otherwise we just take the exit lane. XXX: actually we are just able to recover malloc() troubles; efforts should be pushed in the validation of the new table. */ handle_error: if (tmpt->table6) free(tmpt->table6); if (mdt) free(mdt); if (bkt.num6) { if (!nt->table6) { memcpy(nt, &bkt, sizeof(struct networks_table)); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back the old Networks Table.\n", config.name, config.type, filename); /* we update the timestamp to avoid loops */ stat(filename, &st); nt->timestamp = st.st_mtime; } } else exit_gracefully(1); } /* sort the (sub)array v from start to end */ void merge_sort6(char * filename, struct networks6_table_entry *table, int start, int end) { int middle; /* no elements to sort */ if ((start == end) || (start == end-1)) return; /* find the middle of the array, splitting it into two subarrays */ middle = (start+end)/2; /* sort the subarray from start..middle */ merge_sort6(filename, table, start, middle); /* sort the subarray from middle..end */ merge_sort6(filename, table, middle, end); /* merge the two sorted halves */ merge6(filename, table, start, middle, end); } /* merge the subarray v[start..middle] with v[middle..end], placing the result back into v. */ void merge6(char *filename, struct networks6_table_entry *table, int start, int middle, int end) { struct networks6_table_entry *v1, *v2; int v1_n, v2_n, v1_index, v2_index, i, x, s = sizeof(struct networks6_table_entry); int chunk; v1_n = middle-start; v2_n = end-middle; v1 = malloc(v1_n*s); v2 = malloc(v2_n*s); if ((!v1) || (!v2)) Log(LOG_ERR, "ERROR ( %s/%s ): [%s] memory sold out.\n", config.name, config.type, filename); for (i=0; i v2[v2_index].net[chunk]) { memcpy(&table[start+i], &v2[v2_index++], s); break; } if (v1[v1_index].net[chunk] == v2[v2_index].net[chunk]) { if (chunk != 3) continue; else { /* two network prefixes are identical; let's compare their masks */ for (x = 0; x < 4; x++) { if (v1[v1_index].mask[x] < v2[v2_index].mask[x]) { memcpy(&table[start+i], &v1[v1_index++], s); break; } if (v1[v1_index].mask[x] > v2[v2_index].mask[x]) { memcpy(&table[start+i], &v2[v2_index++], s); break; } if (v1[v1_index].mask[x] == v2[v2_index].mask[x]) { if (x != 3) continue; else memcpy(&table[start+i], &v1[v1_index++], s); } } } } } } /* clean up; either v1 or v2 may have stuff left in it */ for (; v1_index < v1_n; i++) memcpy(&table[start+i], &v1[v1_index++], s); for (; v2_index < v2_n; i++) memcpy(&table[start+i], &v2[v2_index++], s); free(v1); free(v2); } struct networks6_table_entry *binsearch6(struct networks_table *nt, struct networks_cache *nc, struct host_addr *a) { int low = 0, mid, high = nt->num6-1, chunk; u_int32_t net[4], addrh[4], addr[4]; struct networks6_table_entry *ret; memcpy(&addr, &a->address.ipv6, IP6AddrSz); memcpy(&addrh, &a->address.ipv6, IP6AddrSz); memcpy(&addrh, (void *) pm_ntohl6(addrh), IP6AddrSz); ret = networks_cache_search6(nc, addr); if (ret) { if (ret->masknum == 255) return NULL; /* dummy entry identification */ else return ret; } binsearch_loop: while (low <= high) { mid = (low+high)/2; memcpy(&net, &addrh, IP6AddrSz); for (chunk = 0; chunk < 4; chunk++) net[chunk] &= nt->table6[mid].mask[chunk]; for (chunk = 0; chunk < 4; chunk++) { if (net[chunk] < nt->table6[mid].net[chunk]) { high = mid-1; goto binsearch_loop; } else if (net[chunk] > nt->table6[mid].net[chunk]) { low = mid+1; goto binsearch_loop; } } /* It's assumed we've found our element */ if (nt->table6[mid].childs_table.table6) { ret = binsearch6(&nt->table6[mid].childs_table, nc, a); if (!ret) { ret = &nt->table6[mid]; networks_cache_insert6(nc, addr, &nt->table6[mid]); } } else { ret = &nt->table6[mid]; networks_cache_insert6(nc, addr, &nt->table6[mid]); } return ret; } networks_cache_insert6(nc, addr, &dummy_entry6); return NULL; } void networks_cache_insert6(struct networks_cache *nc, void *key, struct networks6_table_entry *result) { struct networks6_cache_entry *ptr; unsigned int hash; u_int32_t *keyptr = key; hash = networks_cache_hash6(key); ptr = &nc->cache6[hash % nc->num6]; memcpy(ptr->key, keyptr, IP6AddrSz); ptr->result = result; } struct networks6_table_entry *networks_cache_search6(struct networks_cache *nc, void *key) { struct networks6_cache_entry *ptr; unsigned int hash; u_int32_t *keyptr = key; int chunk; hash = networks_cache_hash6(key); ptr = &nc->cache6[hash % nc->num6]; for (chunk = 0; chunk < 4; chunk++) { if (ptr->key[chunk] == keyptr[chunk]) continue; else return NULL; } return ptr->result; } unsigned int networks_cache_hash6(void *key) { u_int32_t a, b, c; u_int32_t *keyptr = (u_int32_t *)key; a = keyptr[0]; b = keyptr[1]; c = keyptr[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += 140281; /* trivial hash rnd */ __jhash_mix(a, b, c); return c; } pmacct-1.7.8/src/linklist.h0000644000175000017500000001050014354105275014577 0ustar paolopaolo/* Generic linked list * Copyright (C) 1997, 2000 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _LINKLIST_H_ #define _LINKLIST_H_ /* listnodes must always contain data to be valid. Adding an empty node * to a list is invalid */ struct pm_listnode { struct pm_listnode *next; struct pm_listnode *prev; /* private member, use getdata() to retrieve, do not access directly */ void *data; }; struct pm_list { struct pm_listnode *head; struct pm_listnode *tail; /* invariant: count is the number of listnodes in the list */ unsigned int count; /* * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. * Used as definition of sorted for pm_listnode_add_sort */ int (*cmp) (void *val1, void *val2); /* callback to free user-owned data when listnode is deleted. supplying * this callback is very much encouraged! */ void (*del) (void *val); }; #define pm_listnextnode(X) ((X)->next) #define pm_listhead(X) ((X)->head) #define pm_listtail(X) ((X)->tail) #define pm_listcount(X) ((X)->count) #define pm_list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) #define pm_listgetdata(X) (assert((X)->data != NULL), (X)->data) /* Prototypes. */ extern struct pm_list *pm_list_new(void); /* encouraged: set list.del callback on new lists */ extern void pm_list_free (struct pm_list *); extern void pm_listnode_add (struct pm_list *, void *); extern void pm_listnode_add_sort (struct pm_list *, void *); extern void pm_listnode_add_after (struct pm_list *, struct pm_listnode *, void *); extern void pm_listnode_delete (struct pm_list *, void *); extern struct pm_listnode *pm_listnode_lookup (struct pm_list *, void *); extern void *pm_listnode_head (struct pm_list *); extern void pm_list_delete (struct pm_list *); extern void pm_list_delete_all_node (struct pm_list *); extern void pm_list_delete_node (struct pm_list *, struct pm_listnode *); extern void pm_list_add_node_prev (struct pm_list *, struct pm_listnode *, void *); extern void pm_list_add_node_next (struct pm_list *, struct pm_listnode *, void *); extern void pm_list_add_list (struct pm_list *, struct pm_list *); /* List iteration macro. * Usage: for (ALL_LIST_ELEMENTS (...) { ... } * It is safe to delete the listnode using this macro. */ #define PM_ALL_LIST_ELEMENTS(list,node,nextnode,data) \ (node) = pm_listhead(list); \ (node) != NULL && \ ((data) = pm_listgetdata(node),(nextnode) = pm_listnextnode(node), 1); \ (node) = (nextnode) /* read-only list iteration macro. * Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only * use this macro when it is *immediately obvious* the listnode is not * deleted in the body of the loop. Does not have forward-reference overhead * of previous macro. */ #define PM_ALL_LIST_ELEMENTS_RO(list,node,data) \ (node) = pm_listhead(list); \ (node) != NULL && ((data) = pm_listgetdata(node), 1); \ (node) = pm_listnextnode(node) /* these *do not* cleanup list nodes and referenced data, as the functions * do - these macros simply {de,at}tach a listnode from/to a list. */ /* List node attach macro. */ #define PM_LISTNODE_ATTACH(L,N) \ do { \ (N)->prev = (L)->tail; \ if ((L)->head == NULL) \ (L)->head = (N); \ else \ (L)->tail->next = (N); \ (L)->tail = (N); \ (L)->count++; \ } while (0) /* List node detach macro. */ #define PM_LISTNODE_DETACH(L,N) \ do { \ if ((N)->prev) \ (N)->prev->next = (N)->next; \ else \ (L)->head = (N)->next; \ if ((N)->next) \ (N)->next->prev = (N)->prev; \ else \ (L)->tail = (N)->prev; \ (L)->count--; \ } while (0) #endif /* _LINKLIST_H_ */ pmacct-1.7.8/src/redis_common.h0000644000175000017500000000462314354105275015435 0ustar paolopaolo/* * pmacct (Promiscuous mode IP Accounting package) * * Copyright (c) 2003-2020 Paolo Lucente * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* includes */ #include /* defines */ #define PM_REDIS_DEFAULT_PORT 6379 #define PM_REDIS_DEFAULT_TIMEOUT 60 #define PM_REDIS_DEFAULT_EXP_TIME 60 #define PM_REDIS_DEFAULT_REFRESH_TIME (PM_REDIS_DEFAULT_EXP_TIME / 3) #define PM_REDIS_DEFAULT_CONN_RETRY (PM_REDIS_DEFAULT_EXP_TIME / 5) #define PM_REDIS_DEFAULT_SEP "+" typedef void (*redis_thread_handler)(void *); /* structures */ struct p_redis_host { char log_id[SHORTBUFLEN]; int exp_time; int db; time_t last_conn; redis_thread_handler th_hdlr; redisContext *ctx; redisReply *reply; }; /* prototypes */ extern void p_redis_thread_wrapper(struct p_redis_host *); extern int p_redis_master_produce_thread(void *); extern void p_redis_init(struct p_redis_host *, char *, redis_thread_handler); extern int p_redis_connect(struct p_redis_host *, int); extern void p_redis_process_reply(struct p_redis_host *); extern void p_redis_close(struct p_redis_host *); extern void p_redis_set_log_id(struct p_redis_host *, char *); extern void p_redis_set_db(struct p_redis_host *, int); extern void p_redis_set_exp_time(struct p_redis_host *, int); extern void p_redis_set_thread_handler(struct p_redis_host *, redis_thread_handler); extern void p_redis_set_string(struct p_redis_host *, char *, char *, int); extern void p_redis_set_int(struct p_redis_host *, char *, int, int); extern void p_redis_ping(struct p_redis_host *); extern void p_redis_select_db(struct p_redis_host *); extern void p_redis_thread_produce_common_core_handler(void *); extern void p_redis_thread_produce_common_plugin_handler(void *); pmacct-1.7.8/src/sfv5_module.c0000644000175000017500000000362414354105275015202 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "sflow.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "sfacctd.h" #include "sfv5_module.h" #include "pmacct-data.h" /* Global variables */ struct sfv5_modules_desc sfv5_modules; void sfv5_modules_db_init() { memset(&sfv5_modules, 0, sizeof(sfv5_modules)); } struct sfv5_modules_db_field *sfv5_modules_db_get_ie(u_int32_t type) { u_int16_t idx, modulo = (type%SFV5_MODULES_DB_ENTRIES); struct sfv5_modules_db_field *db_ptr = NULL; for (idx = 0; idx < IES_PER_SFV5_MODULES_DB_ENTRY; idx++) { if (sfv5_modules.db[modulo].ie[idx].type == type) { db_ptr = &sfv5_modules.db[modulo].ie[idx]; break; } } return db_ptr; } struct sfv5_modules_db_field *sfv5_modules_db_get_next_ie(u_int32_t type) { u_int16_t idx, modulo = (type%SFV5_MODULES_DB_ENTRIES); struct sfv5_modules_db_field *db_ptr = NULL; for (idx = 0; idx < IES_PER_SFV5_MODULES_DB_ENTRY; idx++) { if (sfv5_modules.db[modulo].ie[idx].type == 0) { db_ptr = &sfv5_modules.db[modulo].ie[idx]; break; } } return db_ptr; } pmacct-1.7.8/src/uacctd.h0000644000175000017500000000015014354105275014211 0ustar paolopaolo#define DEFAULT_NFLOG_BUFLEN (1024*128) #define DEFAULT_NFLOG_GROUP 0 #define DEFAULT_NFLOG_THRESHOLD 1 pmacct-1.7.8/src/pretag_handlers.h0000644000175000017500000004414014354105275016117 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PRETAG_HANDLERS_H #define PRETAG_HANDLERS_H /* prototypes */ extern int PT_map_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_id2_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_label_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_ip_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_input_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_output_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_nexthop_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_bgp_nexthop_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_engine_type_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_engine_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_filter_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_agent_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_flowset_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_fwd_status_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_sample_type_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_is_bi_flow_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_is_nsel_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_is_nel_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_direction_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_nat_event_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_as_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_dst_as_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_peer_src_as_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_peer_dst_as_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_local_pref_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_local_pref_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_roa_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_dst_roa_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_comms_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_comms_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_mpls_vpn_rd_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_mpls_pw_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_mac_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_dst_mac_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_vlan_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_cvlan_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_src_net_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_dst_net_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_is_multicast_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_set_tos_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_entry_label_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_jeq_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_return_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int PT_map_stack_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern pm_id_t PT_stack_sum(pm_id_t, pm_id_t); extern pm_id_t PT_stack_logical_or(pm_id_t, pm_id_t); extern int PT_map_index_entries_ip_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_input_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_output_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_bgp_nexthop_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_src_as_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_dst_as_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_peer_src_as_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_peer_dst_as_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_mpls_vpn_id_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_mpls_vpn_rd_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_mpls_pw_id_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_mpls_label_bottom_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_src_mac_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_dst_mac_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_vlan_id_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_cvlan_id_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_src_net_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_dst_net_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_is_multicast_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_fwd_status_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_entries_null_handler(struct id_table_index *, int, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_ip_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_input_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_output_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_bgp_nexthop_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_src_as_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_dst_as_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_peer_src_as_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_peer_dst_as_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_mpls_vpn_id_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_mpls_vpn_rd_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_mpls_pw_id_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_mpls_label_bottom_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_src_mac_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_dst_mac_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_vlan_id_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_cvlan_id_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_src_net_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_dst_net_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_is_multicast_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_fwd_status_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); extern int PT_map_index_fdata_null_handler(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); /* BPAS_*: bgp_peer_as_src map specific handlers */ extern int BPAS_map_bgp_nexthop_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int BPAS_map_bgp_peer_dst_as_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); /* BTA_*: bgp_agent_map specific handlers */ extern int BTA_map_lookup_bgp_port_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); /* BITR_*: flow_to_rd_map specific handlers */ extern int BITR_map_mpls_label_bottom_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int BITR_map_mpls_vpn_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); /* custom_primitives_*: aggregate_primitives specific handlers */ extern int custom_primitives_map_name_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int custom_primitives_map_packet_ptr_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int custom_primitives_map_field_type_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int custom_primitives_map_len_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int custom_primitives_map_semantics_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern void custom_primitives_map_initialize(); extern void custom_primitives_map_validate(char *, struct plugin_requests *); extern int pretag_dummy_ip_handler(struct packet_ptrs *, void *, void *); extern int pretag_input_handler(struct packet_ptrs *, void *, void *); extern int pretag_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_id2_handler(struct packet_ptrs *, void *, void *); extern int pretag_label_handler(struct packet_ptrs *, void *, void *); extern int pretag_output_handler(struct packet_ptrs *, void *, void *); extern int pretag_nexthop_handler(struct packet_ptrs *, void *, void *); extern int pretag_bgp_nexthop_handler(struct packet_ptrs *, void *, void *); extern int pretag_bgp_bgp_nexthop_handler(struct packet_ptrs *, void *, void *); extern int pretag_engine_type_handler(struct packet_ptrs *, void *, void *); extern int pretag_engine_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_flowset_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_filter_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_dst_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_bgp_src_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_bgp_dst_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_peer_src_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_peer_dst_as_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_local_pref_handler(struct packet_ptrs *, void *, void *); extern int pretag_local_pref_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_roa_handler(struct packet_ptrs *, void *, void *); extern int pretag_dst_roa_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_comms_handler(struct packet_ptrs *, void *, void *); extern int pretag_comms_handler(struct packet_ptrs *, void *, void *); extern int pretag_sample_type_handler(struct packet_ptrs *, void *, void *); extern int pretag_is_bi_flow_handler(struct packet_ptrs *, void *, void *); extern int pretag_is_nsel_handler(struct packet_ptrs *, void *, void *); extern int pretag_is_nel_handler(struct packet_ptrs *, void *, void *); extern int pretag_direction_handler(struct packet_ptrs *, void *, void *); extern int pretag_nat_event_handler(struct packet_ptrs *, void *, void *); extern int pretag_mpls_vpn_rd_handler(struct packet_ptrs *, void *, void *); extern int pretag_mpls_pw_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_mac_handler(struct packet_ptrs *, void *, void *); extern int pretag_dst_mac_handler(struct packet_ptrs *, void *, void *); extern int pretag_vlan_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_src_net_handler(struct packet_ptrs *, void *, void *); extern int pretag_dst_net_handler(struct packet_ptrs *, void *, void *); extern int pretag_is_multicast_handler(struct packet_ptrs *, void *, void *); extern int pretag_fwd_status_handler(struct packet_ptrs *, void *, void *); extern int pretag_cvlan_id_handler(struct packet_ptrs *, void *, void *); extern int pretag_set_tos_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_input_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_output_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_nexthop_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_bgp_nexthop_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_agent_id_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_src_as_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_dst_as_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_dst_as_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_src_mac_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_dst_mac_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_vlan_id_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_mpls_pw_id_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_src_net_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_dst_net_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_is_multicast_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_sample_type_handler(struct packet_ptrs *, void *, void *); extern int SF_pretag_direction_handler(struct packet_ptrs *, void *, void *); extern int PM_pretag_src_as_handler(struct packet_ptrs *, void *, void *); extern int PM_pretag_dst_as_handler(struct packet_ptrs *, void *, void *); extern int PM_pretag_input_handler(struct packet_ptrs *, void *, void *); extern int PM_pretag_output_handler(struct packet_ptrs *, void *, void *); extern int PM_pretag_direction_handler(struct packet_ptrs *, void *, void *); extern int BPAS_bgp_nexthop_handler(struct packet_ptrs *, void *, void *); extern int BPAS_bgp_peer_dst_as_handler(struct packet_ptrs *, void *, void *); extern int BTA_lookup_bgp_port_handler(struct packet_ptrs *, void *, void *); extern int BITR_mpls_label_bottom_handler(struct packet_ptrs *, void *, void *); extern int BITR_mpls_vpn_id_handler(struct packet_ptrs *, void *, void *); extern void pm_pcap_interfaces_map_validate(char *, struct plugin_requests *); extern int pm_pcap_interfaces_map_ifindex_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int pm_pcap_interfaces_map_ifname_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int pm_pcap_interfaces_map_direction_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern void pm_pcap_interfaces_map_initialize(struct pm_pcap_interfaces *); extern void pm_pcap_interfaces_map_load(struct pm_pcap_interfaces *); extern void pm_pcap_interfaces_map_destroy(struct pm_pcap_interfaces *); extern void pm_pcap_interfaces_map_copy(struct pm_pcap_interfaces *, struct pm_pcap_interfaces *); extern u_int32_t pm_pcap_interfaces_map_lookup_ifname(struct pm_pcap_interfaces *, char *); extern struct pm_pcap_interface *pm_pcap_interfaces_map_getentry_by_ifname(struct pm_pcap_interfaces *, char *); extern struct pm_pcap_interface *pm_pcap_interfaces_map_getentry_by_idx(struct pm_pcap_interfaces *, int); extern char *pm_pcap_interfaces_map_getnext_ifname(struct pm_pcap_interfaces *, int *); extern char *pm_pcap_interfaces_map_get_ifname(struct pm_pcap_interfaces *, int); extern int pm_pcap_interfaces_map_get_direction(struct pm_pcap_interfaces *, int); #endif //PRETAG_HANDLERS_H pmacct-1.7.8/src/uacctd.c0000644000175000017500000011350114354105275014211 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "uacctd.h" #include "pmacct-data.h" #include "pretag_handlers.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_frag.h" #include "ip_flow.h" #include "net_aggr.h" #include "thread_pool.h" #include "bgp/bgp.h" #include "isis/isis.h" #include "bmp/bmp.h" #include #include #include #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif /* Functions */ static int nflog_incoming(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *nfa, void *p) { static u_char *jumbo_container; static ssize_t jumbo_container_sz = 0; struct pcap_pkthdr hdr; char *pkt = NULL; ssize_t pkt_len = nflog_get_payload(nfa, &pkt); ssize_t mac_len = 0; struct pm_pcap_callback_data *cb_data = p; if (nflog_get_hwtype(nfa) == DLT_EN10MB) mac_len = nflog_get_msg_packet_hwhdrlen(nfa); /* Check we can handle this packet */ switch (nfmsg->nfgen_family) { case AF_INET: break; case AF_INET6: break; default: return 0; } if (pkt_len == ERR) return ERR; if (nflog_get_timestamp(nfa, &hdr.ts) < 0) { gettimeofday(&hdr.ts, NULL); } hdr.caplen = MIN(pkt_len, config.snaplen); hdr.len = pkt_len; cb_data->ifindex_in = nflog_get_physindev(nfa); if (cb_data->ifindex_in == 0) cb_data->ifindex_in = nflog_get_indev(nfa); cb_data->ifindex_out = nflog_get_physoutdev(nfa); if (cb_data->ifindex_out == 0) cb_data->ifindex_out = nflog_get_outdev(nfa); #if defined (HAVE_L2) ssize_t req_len = hdr.caplen + (mac_len ? mac_len : ETHER_HDRLEN); if (req_len > jumbo_container_sz) { if (jumbo_container) free(jumbo_container); jumbo_container = malloc(req_len); if (jumbo_container == NULL) { jumbo_container_sz = 0; Log(LOG_ERR, "ERROR ( %s/core ): jumbo_container buffer malloc() failed, packet ignored.\n", config.name); return ERR; } jumbo_container_sz = req_len; } if (mac_len) { memcpy(jumbo_container, nflog_get_msg_packet_hwhdr(nfa), mac_len); memcpy(jumbo_container + mac_len, pkt, hdr.caplen); hdr.caplen += mac_len; hdr.len += mac_len; } else { memset(jumbo_container, 0, ETHER_HDRLEN); memcpy(jumbo_container+ETHER_HDRLEN, pkt, hdr.caplen); hdr.caplen += ETHER_HDRLEN; hdr.len += ETHER_HDRLEN; switch (nfmsg->nfgen_family) { case AF_INET: ((struct eth_header *)jumbo_container)->ether_type = ntohs(ETHERTYPE_IP); break; case AF_INET6: ((struct eth_header *)jumbo_container)->ether_type = ntohs(ETHERTYPE_IPV6); break; } } pm_pcap_cb((u_char *) cb_data, &hdr, jumbo_container); #else pm_pcap_cb((u_char *) cb_data, &hdr, pkt); #endif return 0; } void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", UACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -g NFLOG group ] [ -c primitive [ , ... ] ] [ -P plugin [ , ... ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -a \tPrint list of supported aggregation primitives\n"); printf(" -c \tAggregation method, see full list of primitives with -a (DEFAULT: src_host)\n"); printf(" -D \tDaemonize\n"); printf(" -n \tPath to a file containing networks and/or ASNs definitions\n"); printf(" -t \tPath to a file containing ports definitions\n"); printf(" -P \t[ memory | print | mysql | pgsql | sqlite3 | amqp | kafka | nfprobe | sfprobe ] \n\tActivate plugin\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -R \tRenormalize sampled data\n"); printf(" -g \tNetlink NFLOG group\n"); printf(" -L \tSnapshot length\n"); printf(" -u \tLeave IP protocols in numerical format\n"); printf("\nMemory plugin (-P memory) options:\n"); printf(" -p \tSocket for client-server communication (DEFAULT: /tmp/collect.pipe)\n"); printf(" -b \tNumber of buckets\n"); printf(" -m \tNumber of memory pools\n"); printf(" -s \tMemory pool size\n"); printf("\nPrint plugin (-P print) plugin options:\n"); printf(" -r \tRefresh time (in seconds)\n"); printf(" -O \t[ formatted | csv | json | avro ] \n\tOutput format\n"); printf(" -o \tPath to output file\n"); printf(" -M \tPrint event init/close marker messages\n"); printf(" -A \tAppend output (applies to -o)\n"); printf(" -E \tCSV format separator (applies to -O csv, DEFAULT: ',')\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { int index, logf; struct plugins_list_entry *list; struct plugin_requests req; char config_file[SRVBUFLEN]; struct id_table bpas_table; struct id_table blp_table; struct id_table bmed_table; struct id_table biss_table; struct id_table bta_table; struct pm_pcap_callback_data cb_data; sigset_t signal_set; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; /* NFLOG stuff */ struct nflog_handle *nfh = NULL; struct nflog_g_handle *nfgh = NULL; int one = 1; ssize_t len = 0; char *nflog_buffer; struct sockaddr_storage client; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); compute_once(); /* a bunch of default definitions */ reload_map = FALSE; print_stats = FALSE; reload_geoipv2_file = FALSE; bpas_map_allocated = FALSE; blp_map_allocated = FALSE; bmed_map_allocated = FALSE; biss_map_allocated = FALSE; bta_map_caching = FALSE; sampling_map_caching = FALSE; custom_primitives_allocated = FALSE; find_id_func = PM_find_id; plugins_list = NULL; errflag = 0; memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&config, 0, sizeof(struct configuration)); memset(&device, 0, sizeof(struct pm_pcap_device)); memset(&config_file, 0, sizeof(config_file)); memset(&failed_plugins, 0, sizeof(failed_plugins)); memset(&req, 0, sizeof(req)); memset(dummy_tlhdr, 0, sizeof(dummy_tlhdr)); memset(sll_mac, 0, sizeof(sll_mac)); memset(&bpas_table, 0, sizeof(bpas_table)); memset(&blp_table, 0, sizeof(blp_table)); memset(&bmed_table, 0, sizeof(bmed_table)); memset(&biss_table, 0, sizeof(biss_table)); memset(&bta_table, 0, sizeof(bta_table)); memset(&client, 0, sizeof(client)); memset(&cb_data, 0, sizeof(cb_data)); memset(&tunnel_registry, 0, sizeof(tunnel_registry)); memset(&reload_map_tstamp, 0, sizeof(reload_map_tstamp)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); log_notifications_init(&log_notifications); config.acct_type = ACCT_PM; config.progname = uacctd_globstr; rows = 0; memset(&device, 0, sizeof(device)); /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_UACCTD)) != -1)) { if (!cfg_cmdline[rows]) cfg_cmdline[rows] = malloc(SRVBUFLEN); memset(cfg_cmdline[rows], 0, SRVBUFLEN); switch (cp) { case 'P': strlcpy(cfg_cmdline[rows], "plugins: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'n': strlcpy(cfg_cmdline[rows], "networks_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 't': strlcpy(cfg_cmdline[rows], "ports_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "print_output: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "print_output_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'M': strlcpy(cfg_cmdline[rows], "print_markers: true", SRVBUFLEN); rows++; break; case 'A': strlcpy(cfg_cmdline[rows], "print_output_file_append: true", SRVBUFLEN); rows++; break; case 'E': strlcpy(cfg_cmdline[rows], "print_output_separator: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'u': strlcpy(cfg_cmdline[rows], "print_num_protos: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); free(cfg_cmdline[rows]); cfg_cmdline[rows] = NULL; break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'c': strlcpy(cfg_cmdline[rows], "aggregate: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'b': strlcpy(cfg_cmdline[rows], "imt_buckets: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'm': strlcpy(cfg_cmdline[rows], "imt_mem_pools_number: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'p': strlcpy(cfg_cmdline[rows], "imt_path: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'r': strlcpy(cfg_cmdline[rows], "sql_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 's': strlcpy(cfg_cmdline[rows], "imt_mem_pools_size: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'g': strlcpy(cfg_cmdline[rows], "uacctd_group: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'L': strlcpy(cfg_cmdline[rows], "snaplen: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'R': strlcpy(cfg_cmdline[rows], "sfacctd_renormalize: true", SRVBUFLEN); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, UACCTD_USAGE_HEADER); exit(0); break; case 'a': print_primitives(config.acct_type, UACCTD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } /* XXX: glue; i'm conscious it's a dirty solution from an engineering viewpoint; someday later i'll fix this */ list = plugins_list; while (list) { list->cfg.acct_type = ACCT_PM; list->cfg.progname = uacctd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); if (!config.snaplen) config.snaplen = DEFAULT_SNAPLEN; if (!config.uacctd_nl_size) config.uacctd_nl_size = DEFAULT_NFLOG_BUFLEN; if (!config.uacctd_threshold) config.uacctd_threshold = DEFAULT_NFLOG_THRESHOLD; /* Let's check whether we need superuser privileges */ if (getuid() != 0) { printf("%s %s (%s)\n\n", UACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("ERROR ( %s/core ): You need superuser privileges to run this command.\nExiting ...\n\n", config.name); exit(1); } if (!config.uacctd_group) { config.uacctd_group = DEFAULT_NFLOG_GROUP; list = plugins_list; while (list) { list->cfg.uacctd_group = DEFAULT_NFLOG_GROUP; list = list->next; } } initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); list = plugins_list; while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { list = plugins_list; while (list) { if (!strcmp(list->type.string, "print") && !list->cfg.print_output_file) printf("INFO ( %s/%s ): Daemonizing. Bye bye screen.\n", list->name, list->type.string); list = list->next; } if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s (%s)\n", config.name, UACCTD_USAGE_HEADER, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); /* Enforcing policies over aggregation methods */ list = plugins_list; while (list) { if (list->type.id != PLUGIN_ID_CORE) { /* applies to all plugins */ plugin_pipe_check(&list->cfg); if (list->cfg.sampling_rate && config.ext_sampling_rate) { Log(LOG_ERR, "ERROR ( %s/core ): Internal packet sampling and external packet sampling are mutual exclusive.\n", config.name); exit_gracefully(1); } /* applies to specific plugins */ if (list->type.id == PLUGIN_ID_TEE) { Log(LOG_ERR, "ERROR ( %s/core ): 'tee' plugin not supported in 'uacctd'.\n", config.name); exit_gracefully(1); } else if (list->type.id == PLUGIN_ID_NFPROBE) { /* If we already renormalizing an external sampling rate, we cancel the sampling information from the probe plugin */ if (config.sfacctd_renormalize && (list->cfg.ext_sampling_rate || list->cfg.sampling_rate)) { list->cfg.ext_sampling_rate = 0; list->cfg.sampling_rate = 0; } config.handle_fragments = TRUE; list->cfg.nfprobe_what_to_count = list->cfg.what_to_count; list->cfg.nfprobe_what_to_count_2 = list->cfg.what_to_count_2; list->cfg.what_to_count = 0; list->cfg.what_to_count_2 = 0; #if defined (HAVE_L2) if (list->cfg.nfprobe_version == 9 || list->cfg.nfprobe_version == 10) { list->cfg.what_to_count |= COUNT_SRC_MAC; list->cfg.what_to_count |= COUNT_DST_MAC; list->cfg.what_to_count |= COUNT_VLAN; } #endif list->cfg.what_to_count |= COUNT_SRC_HOST; list->cfg.what_to_count |= COUNT_DST_HOST; if (list->cfg.networks_file || list->cfg.networks_mask || list->cfg.nfacctd_net) { list->cfg.what_to_count |= COUNT_SRC_NMASK; list->cfg.what_to_count |= COUNT_DST_NMASK; } list->cfg.what_to_count |= COUNT_SRC_PORT; list->cfg.what_to_count |= COUNT_DST_PORT; list->cfg.what_to_count |= COUNT_IP_TOS; list->cfg.what_to_count |= COUNT_IP_PROTO; if (list->cfg.networks_file || ((list->cfg.bgp_daemon || list->cfg.bmp_daemon) && list->cfg.nfacctd_as == NF_AS_BGP)) { list->cfg.what_to_count |= COUNT_SRC_AS; list->cfg.what_to_count |= COUNT_DST_AS; list->cfg.what_to_count |= COUNT_PEER_DST_IP; } if (list->cfg.nfprobe_version == 9 || list->cfg.nfprobe_version == 10) { if (list->cfg.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS) list->cfg.what_to_count_2 |= COUNT_NDPI_CLASS; if (list->cfg.nfprobe_what_to_count_2 & COUNT_MPLS_LABEL_TOP) list->cfg.what_to_count_2 |= COUNT_MPLS_LABEL_TOP; } if (list->cfg.pre_tag_map) { list->cfg.what_to_count |= COUNT_TAG; list->cfg.what_to_count |= COUNT_TAG2; list->cfg.what_to_count_2 |= COUNT_LABEL; } list->cfg.what_to_count |= COUNT_IN_IFACE; list->cfg.what_to_count |= COUNT_OUT_IFACE; if ((list->cfg.what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_LOCAL_PREF|COUNT_MED|COUNT_AS_PATH| COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS|COUNT_PEER_SRC_IP|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF| COUNT_MPLS_VPN_RD)) || (list->cfg.what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM|COUNT_SRC_ROA|COUNT_DST_ROA))) { Log(LOG_ERR, "ERROR ( %s/core ): 'src_as', 'dst_as' and 'peer_dst_ip' are currently the only BGP-related primitives supported within the 'nfprobe' plugin.\n", config.name); exit_gracefully(1); } list->cfg.what_to_count |= COUNT_COUNTERS; if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; list->cfg.data_type = PIPE_TYPE_METADATA; list->cfg.data_type |= PIPE_TYPE_EXTRAS; if (list->cfg.what_to_count & (COUNT_PEER_DST_IP)) list->cfg.data_type |= PIPE_TYPE_BGP; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_LABEL)) list->cfg.data_type |= PIPE_TYPE_VLEN; } else if (list->type.id == PLUGIN_ID_SFPROBE) { /* If we already renormalizing an external sampling rate, we cancel the sampling information from the probe plugin */ if (config.sfacctd_renormalize && (list->cfg.ext_sampling_rate || list->cfg.sampling_rate)) { list->cfg.ext_sampling_rate = 0; list->cfg.sampling_rate = 0; } if (config.snaplen < 128) config.snaplen = 128; /* SFL_DEFAULT_HEADER_SIZE */ list->cfg.what_to_count = COUNT_PAYLOAD; list->cfg.what_to_count_2 = 0; #if defined (WITH_NDPI) if (list->cfg.ndpi_num_roots) list->cfg.what_to_count_2 |= COUNT_NDPI_CLASS; #endif if (list->cfg.networks_file || ((list->cfg.bgp_daemon || list->cfg.bmp_daemon) && list->cfg.nfacctd_as == NF_AS_BGP)) { list->cfg.what_to_count |= COUNT_SRC_AS; list->cfg.what_to_count |= COUNT_DST_AS; list->cfg.what_to_count |= COUNT_PEER_DST_IP; } if (list->cfg.networks_file || list->cfg.networks_mask || list->cfg.nfacctd_net) { list->cfg.what_to_count |= COUNT_SRC_NMASK; list->cfg.what_to_count |= COUNT_DST_NMASK; } if (list->cfg.pre_tag_map) { list->cfg.what_to_count |= COUNT_TAG; list->cfg.what_to_count |= COUNT_TAG2; } if ((list->cfg.what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_LOCAL_PREF|COUNT_MED|COUNT_AS_PATH| COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS|COUNT_PEER_SRC_IP|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF| COUNT_MPLS_VPN_RD)) || (list->cfg.what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM|COUNT_SRC_ROA|COUNT_DST_ROA))) { Log(LOG_ERR, "ERROR ( %s/core ): 'src_as', 'dst_as' and 'peer_dst_ip' are currently the only BGP-related primitives supported within the 'sfprobe' plugin.\n", config.name); exit_gracefully(1); } #if defined (HAVE_L2) list->cfg.what_to_count |= COUNT_VLAN; list->cfg.what_to_count |= COUNT_COS; #endif if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; list->cfg.data_type = PIPE_TYPE_PAYLOAD; } else { if (list->cfg.what_to_count_2 & (COUNT_POST_NAT_SRC_HOST|COUNT_POST_NAT_DST_HOST| COUNT_POST_NAT_SRC_PORT|COUNT_POST_NAT_DST_PORT|COUNT_NAT_EVENT| COUNT_TIMESTAMP_START|COUNT_TIMESTAMP_END|COUNT_TIMESTAMP_ARRIVAL| COUNT_EXPORT_PROTO_TIME|COUNT_FWD_STATUS|COUNT_FW_EVENT)) list->cfg.data_type |= PIPE_TYPE_NAT; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP|COUNT_MPLS_LABEL_BOTTOM)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_TUNNEL_SRC_MAC|COUNT_TUNNEL_DST_MAC| COUNT_TUNNEL_SRC_HOST|COUNT_TUNNEL_DST_HOST|COUNT_TUNNEL_IP_PROTO| COUNT_TUNNEL_IP_TOS|COUNT_TUNNEL_SRC_PORT|COUNT_TUNNEL_DST_PORT| COUNT_VXLAN)) { list->cfg.data_type |= PIPE_TYPE_TUN; cb_data.has_tun_prims = TRUE; } if (list->cfg.what_to_count_2 & (COUNT_LABEL|COUNT_MPLS_LABEL_STACK)) list->cfg.data_type |= PIPE_TYPE_VLEN; evaluate_sums(&list->cfg.what_to_count, &list->cfg.what_to_count_2, list->name, list->type.string); if (list->cfg.what_to_count & (COUNT_SRC_PORT|COUNT_DST_PORT|COUNT_SUM_PORT|COUNT_TCPFLAGS)) config.handle_fragments = TRUE; if (list->cfg.what_to_count & COUNT_FLOWS) { config.handle_fragments = TRUE; config.handle_flows = TRUE; } if (!list->cfg.what_to_count && !list->cfg.what_to_count_2 && !list->cfg.cpptrs.num) { Log(LOG_WARNING, "WARN ( %s/%s ): defaulting to SRC HOST aggregation.\n", list->name, list->type.string); list->cfg.what_to_count |= COUNT_SRC_HOST; } if (list->cfg.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) { if (!list->cfg.networks_file && list->cfg.nfacctd_as != NF_AS_BGP) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation selected but NO 'networks_file' or 'uacctd_as' are specified. Exiting...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; } if (list->cfg.what_to_count & (COUNT_SRC_NET|COUNT_DST_NET|COUNT_SUM_NET|COUNT_SRC_NMASK|COUNT_DST_NMASK|COUNT_PEER_DST_IP)) { if (!list->cfg.nfacctd_net) { if (list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; if (list->cfg.networks_mask) list->cfg.nfacctd_net |= NF_NET_STATIC; if (!list->cfg.nfacctd_net) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'uacctd_net', 'networks_file', 'networks_mask' is specified. Exiting ...\n\n", list->name, list->type.string); exit_gracefully(1); } } else { if ((list->cfg.nfacctd_net == NF_NET_NEW && !list->cfg.networks_file) || (list->cfg.nfacctd_net == NF_NET_STATIC && !list->cfg.networks_mask) || (list->cfg.nfacctd_net == NF_NET_BGP && !list->cfg.bgp_daemon && !list->cfg.bmp_daemon) || (list->cfg.nfacctd_net == NF_NET_IGP && !list->cfg.nfacctd_isis) || (list->cfg.nfacctd_net == NF_NET_KEEP)) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'bgp_daemon', 'bmp_daemon', 'isis_daemon', 'networks_file', 'networks_mask' is specified. Exiting ...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; } } list->cfg.type_id = list->type.id; bgp_config_checks(&list->cfg); list->cfg.what_to_count |= COUNT_COUNTERS; list->cfg.data_type |= PIPE_TYPE_METADATA; } /* applies to all plugins */ if ((list->cfg.what_to_count_2 & COUNT_NDPI_CLASS) || (list->cfg.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS)) { config.handle_fragments = TRUE; config.classifier_ndpi = TRUE; } } list = list->next; } /* plugins glue: creation (since 094) */ #if defined (WITH_NDPI) if (config.classifier_ndpi) { config.handle_fragments = TRUE; pm_ndpi_wfl = pm_ndpi_workflow_init(); pm_ndpi_export_proto_to_class(pm_ndpi_wfl); } else pm_ndpi_wfl = NULL; #endif if (config.aggregate_primitives) { req.key_value_table = (void *) &custom_primitives_registry; load_id_file(MAP_CUSTOM_PRIMITIVES, config.aggregate_primitives, NULL, &req, &custom_primitives_allocated); } else memset(&custom_primitives_registry, 0, sizeof(custom_primitives_registry)); /* fixing per plugin custom primitives pointers, offsets and lengths */ list = plugins_list; while(list) { custom_primitives_reconcile(&list->cfg.cpptrs, &custom_primitives_registry); if (custom_primitives_vlen(&list->cfg.cpptrs)) list->cfg.data_type |= PIPE_TYPE_VLEN; list = list->next; } load_plugins(&req); if (config.handle_fragments) init_ip_fragment_handler(); if (config.handle_flows) init_ip_flow_handler(); load_networks(config.networks_file, &nt, &nc); #if defined (HAVE_L2) device.link_type = DLT_EN10MB; #else device.link_type = DLT_RAW; #endif for (index = 0; _devices[index].link_type != -1; index++) { if (device.link_type == _devices[index].link_type) device.data = &_devices[index]; } load_plugin_filters(device.link_type); cb_data.device = &device; /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ sighandler_action.sa_handler = startup_handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = push_stats; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); nfh = nflog_open(); if (nfh == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to create Netlink NFLOG socket\n", config.name); nflog_close(nfh); exit_gracefully(1); } Log(LOG_INFO, "INFO ( %s/core ): Successfully connected Netlink NFLOG socket\n", config.name); /* Bind to IPv4 (and IPv6) */ if (nflog_unbind_pf(nfh, AF_INET) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to unbind Netlink NFLOG socket from IPv4\n", config.name); nflog_close(nfh); exit_gracefully(1); } if (nflog_bind_pf(nfh, AF_INET) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to bind Netlink NFLOG socket from IPv4\n", config.name); nflog_close(nfh); exit_gracefully(1); } if (nflog_unbind_pf(nfh, AF_INET6) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to unbind Netlink NFLOG socket from IPv6\n", config.name); nflog_close(nfh); exit_gracefully(1); } if (nflog_bind_pf(nfh, AF_INET6) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to bind Netlink NFLOG socket from IPv6\n", config.name); nflog_close(nfh); exit_gracefully(1); } /* Bind to group */ if ((nfgh = nflog_bind_group(nfh, config.uacctd_group)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to join NFLOG group %d\n", config.name, config.uacctd_group); nflog_close(nfh); exit_gracefully(1); } /* Set snaplen */ if (nflog_set_mode(nfgh, NFULNL_COPY_PACKET, config.snaplen) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to set snaplen to %d\n", config.name, config.snaplen); nflog_unbind_group(nfgh); nflog_close(nfh); exit_gracefully(1); } /* Set threshold */ if (nflog_set_qthresh(nfgh, config.uacctd_threshold) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to set threshold to %d\n", config.name, config.uacctd_threshold); nflog_unbind_group(nfgh); nflog_close(nfh); exit_gracefully(1); } /* Set buffer size */ if (nflog_set_nlbufsiz(nfgh, config.uacctd_nl_size) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): Failed to set receive buffer size to %d\n", config.name, config.uacctd_nl_size); nflog_unbind_group(nfgh); nflog_close(nfh); exit_gracefully(1); } /* Turn off netlink errors from overrun. */ if (setsockopt(nflog_fd(nfh), SOL_NETLINK, NETLINK_NO_ENOBUFS, &one, (socklen_t) sizeof(one))) Log(LOG_ERR, "ERROR ( %s/core ): Failed to turn off netlink ENOBUFS\n", config.name); nflog_callback_register(nfgh, &nflog_incoming, &cb_data); nflog_buffer = malloc(config.uacctd_nl_size); if (nflog_buffer == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): NFLOG buffer malloc() failed\n", config.name); nflog_unbind_group(nfgh); nflog_close(nfh); exit_gracefully(1); } if (config.bgp_daemon && config.bmp_daemon) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_daemon and bmp_daemon are currently mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } /* starting the ISIS threa */ if (config.nfacctd_isis) { req.bpf_filter = TRUE; nfacctd_isis_wrapper(); /* Let's give the ISIS thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } /* starting the BGP thread */ if (config.bgp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_stdcomm_pattern_to_asn && config.bgp_daemon_lrgcomm_pattern_to_asn) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_stdcomm_pattern_to_asn and bgp_lrgcomm_pattern_to_asn are mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } load_comm_patterns(&config.bgp_daemon_stdcomm_pattern, &config.bgp_daemon_extcomm_pattern, &config.bgp_daemon_lrgcomm_pattern, &config.bgp_daemon_stdcomm_pattern_to_asn, &config.bgp_daemon_lrgcomm_pattern_to_asn); if (config.bgp_daemon_peer_as_src_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_peer_as_src_map) { load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); cb_data.bpas_table = (u_char *) &bpas_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_peer_as_src_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.bpas_table = NULL; if (config.bgp_daemon_src_local_pref_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_local_pref_map) { load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); cb_data.blp_table = (u_char *) &blp_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_local_pref_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.bpas_table = NULL; if (config.bgp_daemon_src_med_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_med_map) { load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); cb_data.bmed_table = (u_char *) &bmed_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_med_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else cb_data.bmed_table = NULL; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); cb_data.bta_table = (u_char *) &bta_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): 'bgp_daemon' configured but no 'bgp_agent_map' has been specified. Exiting.\n", config.name); exit_gracefully(1); } /* Limiting BGP peers to only two: one would suffice in pmacctd but in case maps are reloadable (ie. bta), it could be handy to keep a backup feed in memory */ config.bgp_daemon_max_peers = 2; cb_data.f_agent = (u_char *) &client; bgp_daemon_wrapper(); /* Let's give the BGP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } /* starting the BMP thread */ if (config.bmp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); cb_data.bta_table = (u_char *) &bta_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): 'bmp_daemon' configured but no 'bgp_agent_map' has been specified. Exiting.\n", config.name); exit_gracefully(1); } /* Limiting BGP peers to only two: one would suffice in pmacctd but in case maps are reloadable (ie. bta), it could be handy to keep a backup feed in memory */ config.bgp_daemon_max_peers = 2; bmp_daemon_wrapper(); /* Let's give the BMP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } #if defined WITH_GEOIP if (config.geoip_ipv4_file || config.geoip_ipv6_file) { req.bpf_filter = TRUE; } #endif #if defined WITH_GEOIPV2 if (config.geoipv2_file) { req.bpf_filter = TRUE; } #endif if (config.nfacctd_flow_to_rd_map) { Log(LOG_ERR, "ERROR ( %s/core ): 'flow_to_rd_map' is not supported by this daemon. Exiting.\n", config.name); exit_gracefully(1); } /* plugins glue: creation (until 093) */ evaluate_packet_handlers(); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); /* signals to be handled only by the core process; we set proper handlers after plugin creation */ sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); kill(getpid(), SIGCHLD); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } cb_data.sig.is_set = FALSE; /* Main loop: if pcap_loop() exits maybe an error occurred; we will try closing and reopening again our listening device */ for (;;) { sigprocmask(SIG_BLOCK, &signal_set, NULL); if (len == ERR) { if (errno != EAGAIN) { /* We can't deal with permanent errors. * Just sleep a bit. */ Log(LOG_ERR, "ERROR ( %s/core ): Syscall returned %d: %s. Sleeping for 1 sec.\n", config.name, errno, strerror(errno)); sleep(1); } } len = recv(nflog_fd(nfh), nflog_buffer, config.uacctd_nl_size, 0); if (len < 0) continue; if (nflog_handle_packet(nfh, nflog_buffer, len) != 0) continue; sigprocmask(SIG_UNBLOCK, &signal_set, NULL); } } pmacct-1.7.8/src/preprocess.c0000644000175000017500000006062414354105275015142 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_common.h" #include "sql_common.h" #include "preprocess.h" #include "preprocess-data.h" #include "preprocess-internal.h" //Global variables sql_preprocess_func sql_preprocess_funcs[2*N_FUNCS]; /* 20 */ P_preprocess_func P_preprocess_funcs[2*N_FUNCS]; /* 20 */ struct preprocess prep; struct _fsrc_queue fsrc_queue; void set_preprocess_funcs(char *string, struct preprocess *prep, int dictionary) { char *token, *sep, *key, *value; int dindex, err = 0, sql_idx = 0, p_idx = 0; memset(sql_preprocess_funcs, 0, sizeof(sql_preprocess_funcs)); memset(P_preprocess_funcs, 0, sizeof(P_preprocess_funcs)); memset(prep, 0, sizeof(struct preprocess)); if (!string) return; trim_all_spaces(string); while ((token = extract_token(&string, ','))) { sep = strchr(token, '='); if (!sep) { Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: malformed input string. Ignored.\n", config.name, config.type); return; } else { key = token; *sep = '\0'; value = sep+1; lower_string(key); } /* validation against dictionaries */ if (dictionary == PREP_DICT_SQL) { for (dindex = 0; strcmp(sql_prep_dict[dindex].key, ""); dindex++) { if (!strcmp(sql_prep_dict[dindex].key, key)) { err = FALSE; break; } else err = E_NOTFOUND; /* key not found */ } } else if (dictionary == PREP_DICT_PRINT) { for (dindex = 0; strcmp(print_prep_dict[dindex].key, ""); dindex++) { if (!strcmp(print_prep_dict[dindex].key, key)) { err = FALSE; break; } else err = E_NOTFOUND; /* key not found */ } } if (err == E_NOTFOUND) { Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: unknown keyword %s. Ignored.\n", config.name, config.type, key); continue; } if (!strcmp(key, "qnum")) { prep->qnum = atoi(value); if (!prep->qnum) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'qnum' value.\n", config.name, config.type); } else if (!strcmp(key, "minp")) { prep->minp = atoi(value); if (!prep->minp) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'minp' value.\n", config.name, config.type); } else if (!strcmp(key, "minf")) { prep->minf = atoi(value); if (!prep->minf) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'minf' value.\n", config.name, config.type); } else if (!strcmp(key, "minb")) { prep->minb = atoi(value); if (!prep->minb) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'minb' value.\n", config.name, config.type); } else if (!strcmp(key, "maxp")) { prep->maxp = atoi(value); if (!prep->maxp) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'maxp' value.\n", config.name, config.type); } else if (!strcmp(key, "maxf")) { prep->maxf = atoi(value); if (!prep->maxf) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'maxf' value.\n", config.name, config.type); } else if (!strcmp(key, "maxb")) { prep->maxb = atoi(value); if (!prep->maxb) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'maxb' value.\n", config.name, config.type); } else if (!strcmp(key, "maxbpp")) { prep->maxbpp = atoi(value); if (!prep->maxbpp) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'maxbpp' value.\n", config.name, config.type); } else if (!strcmp(key, "maxppf")) { prep->maxppf = atoi(value); if (!prep->maxppf) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'maxppf' value.\n", config.name, config.type); } else if (!strcmp(key, "minbpp")) { prep->minbpp = atoi(value); if (!prep->minbpp) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'minbpp' value.\n", config.name, config.type); } else if (!strcmp(key, "minppf")) { prep->minppf = atoi(value); if (!prep->minppf) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'minppf' value.\n", config.name, config.type); } else if (!strcmp(key, "fss")) { prep->fss = atoi(value); if (!prep->fss) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'fss' value.\n", config.name, config.type); } else if (!strcmp(key, "fsrc")) { prep->fsrc = atoi(value); if (!prep->fsrc) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'fsrc' value.\n", config.name, config.type); else { fsrc_queue.num = 0; memset(&fsrc_queue.head, 0, sizeof(struct fsrc_queue_elem)); } } else if (!strcmp(key, "usrf")) { prep->usrf = atoi(value); if (!prep->usrf) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'usrf' value.\n", config.name, config.type); } else if (!strcmp(key, "adjb")) { prep->adjb = atoi(value); if (!prep->adjb) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'adjb' value.\n", config.name, config.type); } else if (!strcmp(key, "recover")) { prep->recover = atoi(value); if (!prep->recover) Log(LOG_WARNING, "WARN ( %s/%s ): preprocess: invalid 'recover' value.\n", config.name, config.type); } else Log(LOG_ERR, "ERROR ( %s/%s ): preprocess: invalid key: '%s'. Ignored.\n", config.name, config.type, key); } /* Post checks: almost one check should have been specified */ if ((!prep->minp) && (!prep->minb) && (!prep->minf) && (!prep->maxp) && (!prep->maxb) && (!prep->maxf) && (!prep->maxbpp) && (!prep->maxppf) && (!prep->minbpp) && (!prep->minppf) && (!prep->fss) && (!prep->fsrc) && (!prep->usrf) && (!prep->adjb)) { Log(LOG_ERR, "ERROR ( %s/%s ): preprocess: does not contain any checks. Ignored.\n", config.name, config.type); return; } /* 1st step: insert conditionals */ if (prep->qnum) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = cond_qnum; sql_idx++; } } /* 2nd step: invalidation of committed cache entries - if at least one check was specified; each check will selectively re-validate entries that pass tests successfully */ if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = mandatory_invalidate; sql_idx++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_mandatory_invalidate; p_idx++; } /* 3rd step: insert checks */ if (prep->minp) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_minp; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_minp; prep->num++; p_idx++; prep->checkno++; } } if (prep->minf) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_minf; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_minf; prep->num++; p_idx++; prep->checkno++; } } if (prep->minb) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_minb; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_minb; prep->num++; p_idx++; prep->checkno++; } } if (prep->maxp) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_maxp; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_maxp; prep->num++; p_idx++; prep->checkno++; } } if (prep->maxf) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_maxf; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_maxf; prep->num++; p_idx++; prep->checkno++; } } if (prep->maxb) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_maxb; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_maxb; prep->num++; p_idx++; prep->checkno++; } } if (prep->maxbpp) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_maxbpp; prep->num++; sql_idx++; prep->checkno++; } } if (prep->maxppf) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_maxppf; prep->num++; sql_idx++; prep->checkno++; } } if (prep->minbpp) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_minbpp; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_minbpp; prep->num++; p_idx++; prep->checkno++; } } if (prep->minppf) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_minppf; prep->num++; sql_idx++; prep->checkno++; } else if (dictionary == PREP_DICT_PRINT) { P_preprocess_funcs[p_idx] = P_check_minppf; prep->num++; p_idx++; prep->checkno++; } } if (prep->fss) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_fss; prep->num++; sql_idx++; prep->checkno++; } } if (prep->fsrc) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = check_fsrc; prep->num++; sql_idx++; prep->checkno++; } } if (prep->usrf) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = action_usrf; prep->num++; sql_idx++; prep->actionno++; } } if (prep->adjb) { if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = action_adjb; prep->num++; sql_idx++; prep->actionno++; } } /* 4th and final step: check points: - if in 'any' mode, any entry with 'points >= 1' is valid - if in 'all' mode, any entry with 'points == number of conditions' is valid */ if (dictionary == PREP_DICT_SQL) { sql_preprocess_funcs[sql_idx] = mandatory_validate; sql_idx++; } } void check_validity(struct db_cache *entry, int seq) { if (config.sql_preprocess_type == 0) { if (entry->prep_valid > 0 && entry->valid == SQL_CACHE_INVALID) entry->valid = SQL_CACHE_COMMITTED; } else { if (entry->prep_valid == seq) entry->valid = SQL_CACHE_COMMITTED; else entry->valid = SQL_CACHE_FREE; } } int cond_qnum(struct db_cache *queue[], int *num, int seq) { if (*num > prep.qnum) return FALSE; else return TRUE; } int check_minp(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->packet_counter >= prep.minp) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_minb(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->bytes_counter >= prep.minb) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_minf(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->flows_counter >= prep.minf) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_maxp(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->packet_counter < prep.maxp) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_maxb(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->bytes_counter < prep.maxb) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_maxf(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->flows_counter < prep.maxf) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_maxbpp(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->bytes_counter/queue[x]->packet_counter < prep.maxbpp) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_maxppf(struct db_cache *queue[], int *num, int seq) { int x; if (!queue[0]->flows_counter) return FALSE; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->packet_counter/queue[x]->flows_counter < prep.maxppf) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_minbpp(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->bytes_counter/queue[x]->packet_counter >= prep.minbpp) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_minppf(struct db_cache *queue[], int *num, int seq) { int x; if (!queue[0]->flows_counter) return FALSE; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { if (queue[x]->packet_counter/queue[x]->flows_counter >= prep.minppf) queue[x]->prep_valid++; check_validity(queue[x], seq); } } return FALSE; } int check_fss(struct db_cache *queue[], int *num, int seq) { u_int32_t t = prep.fss; /* threshold */ float p = 0 /* probability */, res; u_int16_t bpratio; int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { res = (float) queue[x]->bytes_counter/t; if (res < 1) p += res; if (p >= 1 || res >= 1) { queue[x]->prep_valid++; if (queue[x]->bytes_counter < t) { bpratio = queue[x]->bytes_counter/queue[x]->packet_counter; queue[x]->bytes_counter = t; queue[x]->packet_counter = queue[x]->bytes_counter/bpratio; /* hmmm */ } if (p >= 1) p -= 1; } check_validity(queue[x], seq); } } return FALSE; } /* This is an initial implementation and any advice is welcome: - seed: microseconds value returned by the gettimeofday() call - random value: high-order bits returned by the random() call */ int check_fsrc(struct db_cache *queue[], int *num, int seq) { struct fsrc_queue_elem *ptr, *last_seen = NULL, *new; struct timeval tv; float w /* random variable */, z; u_int32_t max = prep.fsrc+1; /* maximum number of allowed flows */ int x, queueElemSz = sizeof(struct fsrc_queue_elem); u_int16_t bpratio; u_int32_t total = 0, subtotal = 0; /* no need to sample */ if (*num <= prep.fsrc) { for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { queue[x]->prep_valid++; check_validity(queue[x], seq); } } goto end; } /* 1st stage: computing the m+1==max flows with highest z */ for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID || queue[x]->valid == SQL_CACHE_COMMITTED) { gettimeofday(&tv, NULL); srandom((unsigned int)tv.tv_usec); w = (float) (random()/(RAND_MAX+1.0)); z = (float) queue[x]->bytes_counter/w; ptr = &fsrc_queue.head; while (z > ptr->z) { last_seen = ptr; if (ptr->next) ptr = ptr->next; else break; } if (fsrc_queue.num < max) { new = malloc(queueElemSz); if (!new) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (check_fsrc). Exiting ..\n", config.name, config.type); exit_gracefully(1); } fsrc_queue.num++; new->next = last_seen->next; last_seen->next = new; } else { if (last_seen == &fsrc_queue.head) continue; new = fsrc_queue.head.next; if (last_seen != fsrc_queue.head.next) { fsrc_queue.head.next = new->next; new->next = last_seen->next; last_seen->next = new; } } new->cache_ptr = queue[x]; new->z = z; total += queue[x]->bytes_counter; } } /* 2nd stage + 3rd stage: - validating the highest m flows - renormalizing the highest m flows: Xi(bytes_counter) = { max[ Xi(bytes_counter), Xm+1(z) ]: i = 1,...,m } */ for (ptr = fsrc_queue.head.next->next; ptr; ptr = ptr->next) { ptr->cache_ptr->prep_valid++; if (ptr->cache_ptr->bytes_counter < fsrc_queue.head.next->z) { bpratio = ptr->cache_ptr->bytes_counter/ptr->cache_ptr->packet_counter; ptr->cache_ptr->bytes_counter = fsrc_queue.head.next->z; ptr->cache_ptr->packet_counter = ptr->cache_ptr->bytes_counter/bpratio; /* hmmm */ } subtotal += ptr->cache_ptr->bytes_counter; check_validity(ptr->cache_ptr, seq); } if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): TOT/%u/%u SUBTOT/%u/%u\n", config.name, config.type, *num, total, fsrc_queue.num-1, subtotal); end: return FALSE; } int action_usrf(struct db_cache *queue[], int *num, int seq) { u_int32_t r = prep.usrf; /* renormalization factor */ u_int16_t bpratio; int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_COMMITTED) { bpratio = queue[x]->bytes_counter/queue[x]->packet_counter; queue[x]->bytes_counter = queue[x]->bytes_counter*r; queue[x]->packet_counter = queue[x]->bytes_counter/bpratio; /* hmmm */ } } return FALSE; } int action_adjb(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_COMMITTED) { queue[x]->bytes_counter += (queue[x]->packet_counter * prep.adjb); } } return FALSE; } int mandatory_invalidate(struct db_cache *queue[], int *num, int seq) { int x; /* Two validation mechanisms are used: if ALL checks have to be successful, prep_valid is a) initializated to a base value, b) incremented at every test concluding positively and c) checked for prep_valid == seq; if instead ANY check has to be successful, a) prep_valid is initializeted to zero, b) is brought to a positive value by the first positive test and c) finally checked for a non-zero value */ for (x = 0; x < *num; x++) { if (config.sql_preprocess_type == 0) queue[x]->prep_valid = 0; else queue[x]->prep_valid = seq; if (prep.checkno && queue[x]->valid == SQL_CACHE_COMMITTED) queue[x]->valid = SQL_CACHE_INVALID; } return FALSE; } /* - 'sql_preprocess_type == 0' means match 'any' of the checks - 'sql_preprocess_type == 1' means match 'all' checks - queue[x]->valid floor value is 2 (SQL_CACHE_COMMITTED) */ int mandatory_validate(struct db_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == SQL_CACHE_INVALID && prep.recover) queue[x]->valid = SQL_CACHE_ERROR; } return FALSE; } int P_mandatory_invalidate(struct chained_cache *queue[], int *num, int seq) { int x; /* Two validation mechanisms are used: if ALL checks have to be successful, prep_valid is a) initializated to a base value, b) incremented at every test concluding positively and c) checked for prep_valid == seq; if instead ANY check has to be successful, a) prep_valid is initializeted to zero, b) is brought to a positive value by the first positive test and c) finally checked for a non-zero value */ for (x = 0; x < *num; x++) { if (config.sql_preprocess_type == 0) queue[x]->prep_valid = 0; else queue[x]->prep_valid = seq; if (prep.checkno && queue[x]->valid == PRINT_CACHE_COMMITTED) queue[x]->valid = PRINT_CACHE_INVALID; } return FALSE; } int P_check_minp(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->packet_counter >= prep.minp) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_minb(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->bytes_counter >= prep.minb) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_minf(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->flow_counter >= prep.minf) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_maxp(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->packet_counter < prep.maxp) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_maxb(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->bytes_counter < prep.maxb) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_maxf(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->flow_counter < prep.maxf) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_minbpp(struct chained_cache *queue[], int *num, int seq) { int x; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->bytes_counter/queue[x]->packet_counter >= prep.minbpp) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } int P_check_minppf(struct chained_cache *queue[], int *num, int seq) { int x; if (!queue[0]->flow_counter) return FALSE; for (x = 0; x < *num; x++) { if (queue[x]->valid == PRINT_CACHE_INVALID || queue[x]->valid == PRINT_CACHE_COMMITTED) { if (queue[x]->packet_counter/queue[x]->flow_counter >= prep.minppf) queue[x]->prep_valid++; P_check_validity(queue[x], seq); } } return FALSE; } void P_check_validity(struct chained_cache *entry, int seq) { if (config.sql_preprocess_type == 0) { if (entry->prep_valid > 0 && entry->valid == PRINT_CACHE_INVALID) entry->valid = PRINT_CACHE_COMMITTED; } else { if (entry->prep_valid == seq) entry->valid = PRINT_CACHE_COMMITTED; else entry->valid = PRINT_CACHE_FREE; } } pmacct-1.7.8/src/plugin_cmn_custom.h0000644000175000017500000000336014354105275016501 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLUGIN_CMN_CUSTOM_H #define PLUGIN_CMN_CUSTOM_H /* defines */ struct pm_custom_output { void *lib_handle; int (*plugin_init)(const char *); int (*plugin_destroy)(); int (*output_init)(const char *, int); int (*print)(u_int64_t, u_int64_t, u_int8_t, struct pkt_primitives *, struct pkt_bgp_primitives *, struct pkt_nat_primitives *, struct pkt_mpls_primitives *, struct pkt_tunnel_primitives *, u_char *, struct pkt_vlen_hdr_primitives *, pm_counter_t, pm_counter_t, pm_counter_t, u_int8_t, u_int8_t, struct timeval *, struct pkt_stitching *); int (*output_flush)(); int (*output_close)(); char* (*get_error_text)(); }; /* prototypes */ /* prototypes */ extern void custom_output_setup(char *, char *, struct pm_custom_output *); /* global variables */ extern struct pm_custom_output custom_print_plugin; #endif //PLUGIN_CMN_CUSTOM_H pmacct-1.7.8/src/thread_pool.h0000644000175000017500000000363014354105275015254 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Original thread pool implementation for pmacct is: Copyright (C) 2006 Francois Deppierraz */ #ifndef _THREAD_POOL_H_ #define _THREAD_POOL_H_ #include #include /* for assert() */ #include /* for EBUSY */ #define DEFAULT_TH_NUM 10 #define MIN_TH_STACK_SIZE 8192000 typedef struct thread_pool_item { int id; pthread_mutex_t *mutex; pthread_cond_t *cond; pthread_t *thread; int (*function)(struct packet_ptrs *data); struct packet_ptrs *data; int usage; int go; int quit; struct thread_pool_item *next; struct thread_pool *owner; } thread_pool_item_t; typedef struct thread_pool { int count; thread_pool_item_t **list; thread_pool_item_t *free_list; pthread_cond_t *cond; pthread_mutex_t *mutex; } thread_pool_t; extern thread_pool_t *allocate_thread_pool(int); extern void deallocate_thread_pool(thread_pool_t **); extern void send_to_pool(thread_pool_t *, void *, void *); extern void *thread_runner(void *); #endif /* _THREAD_POOL_H_ */ pmacct-1.7.8/src/conntrack.c0000644000175000017500000004315014354105275014732 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "ip_flow.h" #include "classifier.h" #include "jhash.h" /* Global variables */ struct conntrack_ipv4 *conntrack_ipv4_table; struct conntrack_ipv6 *conntrack_ipv6_table; u_int32_t conntrack_total_nodes_v4; u_int32_t conntrack_total_nodes_v6; struct conntrack_helper_entry __attribute__((unused)) conntrack_helper_list[4] = { { "ftp", conntrack_ftp_helper }, { "sip", conntrack_sip_helper }, // { "irc", conntrack_irc_helper }, { "rtsp", conntrack_rtsp_helper }, { "", NULL }, }; void init_conntrack_table() { if (config.conntrack_bufsz) conntrack_total_nodes_v4 = config.conntrack_bufsz / sizeof(struct conntrack_ipv4); else conntrack_total_nodes_v4 = DEFAULT_CONNTRACK_BUFFER_SIZE / sizeof(struct conntrack_ipv4); conntrack_ipv4_table = NULL; if (config.conntrack_bufsz) conntrack_total_nodes_v6 = config.conntrack_bufsz / sizeof(struct conntrack_ipv6); else conntrack_total_nodes_v6 = DEFAULT_CONNTRACK_BUFFER_SIZE / sizeof(struct conntrack_ipv6); conntrack_ipv6_table = NULL; } void conntrack_ftp_helper(time_t now, struct packet_ptrs *pptrs) { char *start = NULL, *end = NULL, *ptr; u_int16_t port[2]; int len; if (!pptrs->payload_ptr) return; len = strlen((char *)pptrs->payload_ptr); /* truncated payload */ if (len < 4) return; /* XXX: is it correct to assume that the commands are in the first 4 bytes of the payload ? */ /* PORT/LPRT command, active FTP */ if ((pptrs->payload_ptr[0] == 'P' && pptrs->payload_ptr[1] == 'O' && pptrs->payload_ptr[2] == 'R' && pptrs->payload_ptr[3] == 'T') || (pptrs->payload_ptr[0] == 'L' && pptrs->payload_ptr[1] == 'P' && pptrs->payload_ptr[2] == 'R' && pptrs->payload_ptr[3] == 'T')) { start = strchr((char *)pptrs->payload_ptr, ' '); end = strchr((char *)pptrs->payload_ptr, '\r'); if (start && end) { /* getting the port number */ ptr = end; *end = '\0'; while (*ptr != ',' && ptr > start) ptr--; port[1] = atoi(ptr+1); *end = '\r'; end = ptr; *end = '\0'; while (*ptr != ',' && ptr > start) ptr--; port[0] = atoi(ptr+1); *end = ','; if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, port[0]*256+port[1], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, port[0]*256+port[1], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } /* 227/228 reply, passive (PASV/LPASV) FTP */ else if ((pptrs->payload_ptr[0] == '2' && pptrs->payload_ptr[1] == '2' && pptrs->payload_ptr[2] == '7' && pptrs->payload_ptr[3] == ' ') || (pptrs->payload_ptr[0] == '2' && pptrs->payload_ptr[1] == '2' && pptrs->payload_ptr[2] == '8' && pptrs->payload_ptr[3] == ' ')) { start = strchr((char *)pptrs->payload_ptr, '('); end = strchr((char *)pptrs->payload_ptr, ')'); if (start && end) { /* getting the port number */ ptr = end; *end = '\0'; while (*ptr != ',' && ptr > start) ptr--; port[1] = atoi(ptr+1); *end = ')'; end = ptr; *end = '\0'; while (*ptr != ',' && ptr > start) ptr--; port[0] = atoi(ptr+1); *end = ','; if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, port[0]*256+port[1], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, port[0]*256+port[1], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } /* EPRT command, Extended data port */ else if (pptrs->payload_ptr[0] == 'E' && pptrs->payload_ptr[1] == 'P' && pptrs->payload_ptr[2] == 'R' && pptrs->payload_ptr[3] == 'T') { start = strchr((char *)pptrs->payload_ptr, ' '); end = strchr((char *)pptrs->payload_ptr, '\r'); if (start && end) { /* getting the port number */ while (*end != '|' && end >= start) end--; if (*end != '|') return; ptr = end; *end = '\0'; while (*ptr != '|' && ptr >= start) ptr--; if (*ptr != '|') return; port[0] = atoi(ptr+1); *end = '|'; if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, port[0], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, port[0], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } /* 229 reply, extended passive (EPASV) FTP */ else if (pptrs->payload_ptr[0] == '2' && pptrs->payload_ptr[1] == '2' && pptrs->payload_ptr[2] == '9' && pptrs->payload_ptr[3] == ' ') { start = strchr((char *)pptrs->payload_ptr, '('); end = strchr((char *)pptrs->payload_ptr, ')'); if (start && end) { /* getting the port number */ while (*end != '|' && end >= start) end--; if (*end != '|') return; ptr = end; *end = '\0'; while (*ptr != '|' && ptr >= start) ptr--; if (*ptr != '|') return; port[0] = atoi(ptr+1); *end = '|'; if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, port[0], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, port[0], 0, IPPROTO_TCP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } } void conntrack_rtsp_helper(time_t now, struct packet_ptrs *pptrs) { char *start = NULL, *end = NULL, *ptr; u_int16_t port[2]; int x = 0, len; port[0] = 0; port[1] = 0; if (!pptrs->payload_ptr) return; len = strlen((char *)pptrs->payload_ptr); /* truncated payload */ if (len < 6) return; /* We need to look into RTSP SETUP messages */ if ( !strncmp((char *)pptrs->payload_ptr, "SETUP ", 6) ) { start = strchr((char *)pptrs->payload_ptr, '\n'); end = (char *)(pptrs->payload_ptr + len); while (start && start < end) { start++; /* Then, we need to look into the Transport: line */ if ( !strncmp(start, "Transport:", 10) ) { if ((ptr = strchr(start, '\r'))) end = ptr; ptr = strchr(start, ':'); ptr++; while (ptr && ptr < end) { ptr++; /* Then, we need to search for the client_port= key */ if ( !strncmp(ptr, "client_port=", 12) ) { char *ss_start, *ss_sep, *ss_end; ss_end = strchr(ptr, ';'); /* If we are unable to find the trailing separator, lets return */ if (!ss_end) return; ss_start = strchr(ptr, '='); ss_start++; *ss_end = '\0'; /* We have reached the client_port info; let's handle it meaningfully: we expect either a single port or a range of ports (lo-hi) */ if ((ss_sep = strchr(ss_start, '-'))) { *ss_sep = '\0'; port[0] = atoi(ss_start); *ss_sep = '-'; port[1] = atoi(ss_sep+1); } else { port[0] = atoi(ss_start); port[1] = port[0]; } *ss_end = ';'; for (x = port[0]; x <= port[1]; x++) { if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, x, 0, IPPROTO_UDP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, x, 0, IPPROTO_UDP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } else ptr = strchr(ptr, ';'); } } else start = strchr(start, '\n'); } } } void conntrack_sip_helper(time_t now, struct packet_ptrs *pptrs) { char *start = NULL, *end = NULL, *ptr; u_int16_t port; int len; if (!pptrs->payload_ptr) return; len = strlen((char *)pptrs->payload_ptr); /* truncated payload */ if (len < 11) return; /* We need to look into SIP INVITE messages */ if ( !strncmp((char *)pptrs->payload_ptr, "INVITE ", 7) || !strncmp((char *)pptrs->payload_ptr, "SIP/2.0 200", 11) ) { /* We are searching for the m= line */ for ( start = (char *)pptrs->payload_ptr, end = (char *)(pptrs->payload_ptr + len); start && start < end; start = strchr(start, '\n') ) { start++; if ( !strncmp(start, "m=", 2) ) { end = strchr(start, '\r'); break; } } if (!start || !end) return; ptr = start; while (*ptr != ' ' && ptr < end) ptr++; if (*ptr != ' ') return; while (*ptr == ' ' && ptr < end) ptr++; if (ptr == end) return; start = ptr; while (*ptr != ' ' && ptr < end) ptr++; if (ptr == end) return; *ptr = '\0'; port = atoi(start); *ptr = ' '; if (pptrs->l3_proto == ETHERTYPE_IP) insert_conntrack_ipv4(now, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr, ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr, port, 0, IPPROTO_UDP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); else if (pptrs->l3_proto == ETHERTYPE_IPV6) insert_conntrack_ipv6(now, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_src, &((struct ip6_hdr *) pptrs->iph_ptr)->ip6_dst, port, 0, IPPROTO_UDP, pptrs->class, NULL, CONNTRACK_GENERIC_LIFETIME); } } void conntrack_irc_helper(time_t now, struct packet_ptrs *pptrs) { /* while (isprint(pptrs->payload_ptr[x]) || isspace(pptrs->payload_ptr[x])) { printf("%c", pptrs->payload_ptr[x]); x++; } printf("\n\n"); */ } void insert_conntrack_ipv4(time_t now, u_int32_t ip_src, u_int32_t ip_dst, u_int16_t port_src, u_int16_t port_dst, u_int8_t proto, pm_class_t class, conntrack_helper helper, time_t exp) { int size = sizeof(struct conntrack_ipv4); struct conntrack_ipv4 *ct_elem; if (conntrack_ipv4_table) { ct_elem = conntrack_ipv4_table; while (ct_elem->next && now < ct_elem->stamp+ct_elem->expiration) ct_elem = ct_elem->next; /* no entry expired and we reached the tail: let's allocate a new one */ if (now < ct_elem->stamp+ct_elem->expiration && !ct_elem->next) { if (conntrack_total_nodes_v4) { ct_elem->next = malloc(size); ct_elem->next->next = NULL; ct_elem = ct_elem->next; conntrack_total_nodes_v4--; } else { Log(LOG_INFO, "INFO ( %s/core ): Conntrack/4 buffer full. Skipping packet.\n", config.name); return; } } } /* let's allocate our first element */ else { conntrack_ipv4_table = malloc(size); ct_elem = conntrack_ipv4_table; ct_elem->next = NULL; } ct_elem->ip_src = ip_src; ct_elem->ip_dst = ip_dst; ct_elem->port_src = port_src; ct_elem->port_dst = port_dst; ct_elem->proto = proto; ct_elem->class = class; ct_elem->stamp = now; ct_elem->helper = helper; ct_elem->expiration = exp; } void search_conntrack(struct ip_flow_common *fp, struct packet_ptrs *pptrs, unsigned int idx) { if (pptrs->l3_proto == ETHERTYPE_IP) search_conntrack_ipv4(fp, pptrs, idx); else if (pptrs->l3_proto == ETHERTYPE_IPV6) search_conntrack_ipv6(fp, pptrs, idx); } void search_conntrack_ipv4(struct ip_flow_common *fp, struct packet_ptrs *pptrs, unsigned int idx) { struct conntrack_ipv4 *ct_elem = conntrack_ipv4_table, *aux = NULL; struct pm_iphdr *iphp = (struct pm_iphdr *)pptrs->iph_ptr; struct pm_tlhdr *tlhp = (struct pm_tlhdr *)pptrs->tlh_ptr; if (!conntrack_ipv4_table) return; while (ct_elem) { /* if (fp->last[idx] < ct_elem->stamp+CONNTRACK_GENERIC_LIFETIME) { printf("IP SRC: %x %x\n", iphp->ip_src.s_addr, ct_elem->ip_src); printf("IP DST: %x %x\n", iphp->ip_dst.s_addr, ct_elem->ip_dst); printf("SRC PORT: %u %u\n", ntohs(tlhp->src_port), ct_elem->port_src); printf("DST PORT: %u %u\n", ntohs(tlhp->dst_port), ct_elem->port_dst); printf("IP PROTO: %u %u\n", pptrs->l4_proto, ct_elem->proto); } */ /* conntrack entries usually have incomplete informations about the upcoming data channels; missing primitives are to be considered always true; then, we assure a) full match on the remaining primitives and b) our conntrack entry has not been aged out. */ if (fp->last[idx].tv_sec < ct_elem->stamp+ct_elem->expiration && (ct_elem->ip_src ? iphp->ip_src.s_addr == ct_elem->ip_src : 1) && (ct_elem->ip_dst ? iphp->ip_dst.s_addr == ct_elem->ip_dst : 1) && (ct_elem->proto ? pptrs->l4_proto == ct_elem->proto : 1) && (ct_elem->port_src ? ntohs(tlhp->src_port) == ct_elem->port_src : 1) && (ct_elem->port_dst ? ntohs(tlhp->dst_port) == ct_elem->port_dst : 1)) { fp->class[0] = ct_elem->class; fp->class[1] = ct_elem->class; fp->conntrack_helper = ct_elem->helper; ct_elem->stamp = 0; /* no aux means we are facing the first element in the chain */ if (aux) aux->next = ct_elem->next; else conntrack_ipv4_table = ct_elem->next; free(ct_elem); return; } aux = ct_elem; ct_elem = ct_elem->next; } } void insert_conntrack_ipv6(time_t now, struct in6_addr *ip_src, struct in6_addr *ip_dst, u_int16_t port_src, u_int16_t port_dst, u_int8_t proto, pm_class_t class, conntrack_helper helper, time_t exp) { int size = sizeof(struct conntrack_ipv4); struct conntrack_ipv6 *ct_elem; if (conntrack_ipv6_table) { ct_elem = conntrack_ipv6_table; while (ct_elem->next && now < ct_elem->stamp+ct_elem->expiration) ct_elem = ct_elem->next; /* no entry expired and we reached the tail: let's allocate a new one */ if (now < ct_elem->stamp+ct_elem->expiration && !ct_elem->next) { if (conntrack_total_nodes_v6) { ct_elem->next = malloc(size); ct_elem->next->next = NULL; ct_elem = ct_elem->next; conntrack_total_nodes_v6--; } else { Log(LOG_INFO, "INFO ( %s/core ): Conntrack/6 buffer full. Skipping packet.\n", config.name); return; } } } /* let's allocate our first element */ else { conntrack_ipv6_table = malloc(size); ct_elem = conntrack_ipv6_table; ct_elem->next = NULL; } memcpy(&ct_elem->ip_src, ip_src, IP6AddrSz); memcpy(&ct_elem->ip_dst, ip_dst, IP6AddrSz); ct_elem->port_src = port_src; ct_elem->port_dst = port_dst; ct_elem->proto = proto; ct_elem->class = class; ct_elem->stamp = now; ct_elem->helper = helper; ct_elem->expiration = exp; } void search_conntrack_ipv6(struct ip_flow_common *fp, struct packet_ptrs *pptrs, unsigned int idx) { struct conntrack_ipv6 *ct_elem = conntrack_ipv6_table, *aux = NULL; struct ip6_hdr *iphp = (struct ip6_hdr *)pptrs->iph_ptr; struct pm_tlhdr *tlhp = (struct pm_tlhdr *)pptrs->tlh_ptr; if (!conntrack_ipv6_table) return; while (ct_elem) { /* conntrack entries usually have incomplete informations about the upcoming data channels; missing primitives are to be considered always true; then, we assure a) full match on the remaining primitives and b) our conntrack entry has not been aged out. */ if (fp->last[idx].tv_sec < ct_elem->stamp+ct_elem->expiration && (ct_elem->ip_src[0] ? !ip6_addr_cmp(&iphp->ip6_src, &ct_elem->ip_src) : 1) && (ct_elem->ip_dst[0] ? !ip6_addr_cmp(&iphp->ip6_dst, &ct_elem->ip_dst) : 1) && (ct_elem->proto ? pptrs->l4_proto == ct_elem->proto : 1) && (ct_elem->port_src ? ntohs(tlhp->src_port) == ct_elem->port_src : 1) && (ct_elem->port_dst ? ntohs(tlhp->dst_port) == ct_elem->port_dst : 1)) { fp->class[0] = ct_elem->class; fp->class[1] = ct_elem->class; fp->conntrack_helper = ct_elem->helper; ct_elem->stamp = 0; /* no aux means we are facing the first element in the chain */ if (aux) aux->next = ct_elem->next; else conntrack_ipv6_table = ct_elem->next; free(ct_elem); return; } aux = ct_elem; ct_elem = ct_elem->next; } } pmacct-1.7.8/src/classifier.c0000644000175000017500000001022714354105275015073 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "ip_flow.h" #include "classifier.h" #include "jhash.h" /* Global variables */ struct pkt_classifier *class; u_int32_t class_trivial_hash_rnd = 140281; void init_classifiers() { int max = pmct_get_num_entries(); class = map_shared(0, sizeof(struct pkt_classifier) * max, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); memset(class, 0, sizeof(struct pkt_classifier) * max); } /* pmct library function set follows: PMacct Classifier Table. Unique assumption is the global "class" Classifier Table */ pm_class_t pmct_register(struct pkt_classifier *css) { int max = pmct_get_num_entries(); if (!css || !css->id) return 0; /* let's check that a) a valid class ID has been supplied, b) the class ID is still available. If this is the case, let's proceed with this entry, otherwise we will switch to a default behaviour. */ if (!strcmp(css->protocol, "")) return 0; if (css->id && css->id <= max && !class[css->id-1].id) { memcpy(&class[css->id-1], css, sizeof(struct pkt_classifier)); return css->id; } else return 0; } /* same as pmct_register but without the index decrement */ pm_class_t pmct_ndpi_register(struct pkt_classifier *css) { int max = pmct_get_num_entries(); if (!css || !css->id) return 0; /* let's check that a) a valid class ID has been supplied, b) the class ID is still available. If this is the case, let's proceed with this entry, otherwise we will switch to a default behaviour. */ if (!strcmp(css->protocol, "")) return 0; if (css->id <= max && !class[css->id-1].id) { memcpy(&class[css->id-1], css, sizeof(struct pkt_classifier)); return css->id; } else return 0; } void pmct_unregister(pm_class_t id) { int max = pmct_get_num_entries(); if (id && id <= max && class[id-1].id) memset(&class[id-1], 0, sizeof(struct pkt_classifier)); } pm_class_t pmct_find_first_free() { int ret, idx = 0, num = pmct_get_num_entries(); while (idx < num) { ret = pmct_isfree(idx+1); if (ret > 0) return idx+1; else if (ret < 0) return 0; idx++; } if (num && idx == num) { if (!log_notification_isset(&log_notifications.max_classifiers, FALSE)) { Log(LOG_WARNING, "WARN ( %s/%s ): Finished elements in class table (%u). Raise via classifier_table_num.\n", config.name, config.type, num); log_notification_set(&log_notifications.max_classifiers, FALSE, FALSE); } } return 0; } pm_class_t pmct_find_last_free() { int ret, idx = pmct_get_num_entries(); idx--; while (idx) { ret = pmct_isfree(idx+1); if (ret > 0) return idx+1; else if (ret < 0) return 0; idx--; } return 0; } int pmct_isfree(pm_class_t id) { int max = pmct_get_num_entries(); if (!class) return -1; if (id && id <= max) { if (!class[id-1].id) return 1; else return 0; } else return -1; } int pmct_get(pm_class_t id, struct pkt_classifier *css) { int max = pmct_get_num_entries(); if (!css) return 0; if (id && id <= max && class[id-1].id) { memcpy(css, &class[id-1], sizeof(struct pkt_classifier)); return 1; } else { memset(css, 0, sizeof(struct pkt_classifier)); return 1; } } int pmct_get_num_entries() { if (config.classifier_table_num) return config.classifier_table_num; else return MAX_CLASSIFIERS; } pmacct-1.7.8/src/network.h0000644000175000017500000005523014354105275014450 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PMACCT_NETWORK_H #define PMACCT_NETWORK_H #include "../include/extract.h" #include "../include/llc.h" #include "../include/sll.h" #include "../include/ieee802_11.h" #include "../include/ip6.h" #include "../include/ah.h" #ifndef IN6_IS_ADDR_V4MAPPED #define IN6_IS_ADDR_V4MAPPED(a) \ ((((__const uint32_t *) (a))[0] == 0) \ && (((__const uint32_t *) (a))[1] == 0) \ && (((__const uint32_t *) (a))[2] == htonl (0xffff))) #endif #define ETH_ADDR_LEN 6 /* Octets in one ethernet addr */ #define ETHER_HDRLEN 14 #define ETHERMTU 1500 #define ETHER_JUMBO_MTU 9000 #define IEEE8021Q_TAGLEN 4 #define CFP_TAGLEN 16 #define CVNT_TAGLEN 6 #define IEEE8021AH_LEN 10 #define PPP_TAGLEN 2 #define MAX_MCAST_GROUPS 20 #define PRIMPTRS_FUNCS_N 16 /* Ethernet header */ struct eth_header { u_int8_t ether_dhost[ETH_ADDR_LEN]; /* destination eth addr */ u_int8_t ether_shost[ETH_ADDR_LEN]; /* source ether addr */ u_int16_t ether_type; /* packet type ID field */ }; /* 802.1Q header */ struct vlan_header { u_int16_t tci; /* priority and VLAN ID */ u_int16_t proto; /* packet type ID or len */ } __attribute__ ((packed)); #define CHDLC_MCAST_ADDR 0x8F #define CHDLC_FIXED_CONTROL 0x00 /* CHDLC header */ struct chdlc_header { u_int8_t address; u_int8_t control; u_int16_t protocol; }; /* Ethernet protocol ID's */ #define ETHERTYPE_IP 0x0800 /* IP */ #define ETHERTYPE_IPV6 0x86dd /* IPv6 */ #define ETHERTYPE_PPPOE 0x8864 /* pppoe (session stage) */ #define ETHERTYPE_8021Q 0x8100 /* 802.1Q */ #define ETHERTYPE_MPLS 0x8847 /* MPLS */ #define ETHERTYPE_MPLS_MULTI 0x8848 /* MPLS */ #define ETHERTYPE_8021AD 0x88A8 /* 802.1AD */ #define ETHERTYPE_ISO 0xFEFE /* OSI */ #define ETHERTYPE_GRE_ISO 0x00FE /* OSI over GRE */ #define ETHERTYPE_CFP 0x8903 /* Cisco FabricPath */ #define ETHERTYPE_CVNT 0x8926 /* Cisco Virtual Network TAG */ /* PPP protocol definitions */ #define PPP_HDRLEN 4 /* octets for standard ppp header */ #define PPPOE_HDRLEN 6 /* octets for standard pppoe header */ #define PPP_IP 0x0021 /* Internet Protocol */ #define PPP_IPV6 0x0057 /* IPv6 */ #define PPP_MPLS_UCAST 0x0281 /* rfc 3032 */ #define PPP_MPLS_MCAST 0x0283 /* rfc 3022 */ #define PPP_ADDRESS 0xff /* The address byte value */ #define PPP_CONTROL 0x03 /* The control byte value */ /* CHDLC protocol definitions */ #define CHDLC_HDRLEN 4 /* additional protocol definitions */ #ifndef IPPROTO_HOPOPTS #define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ #endif #ifndef IPPROTO_IPV6 #define IPPROTO_IPV6 41 #endif #ifndef IPPROTO_ROUTING #define IPPROTO_ROUTING 43 /* IPv6 routing header */ #endif #ifndef IPPROTO_FRAGMENT #define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ #endif #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 /* SIPP Encap Sec. Payload */ #endif #ifndef IPPROTO_AH #define IPPROTO_AH 51 /* SIPP Auth Header */ #endif #ifndef IPPROTO_NONE #define IPPROTO_NONE 59 /* IPv6 no next header */ #endif #ifndef IPPROTO_DSTOPTS #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ #endif #ifndef IPPROTO_IPCOMP #define IPPROTO_IPCOMP 108 #endif #ifndef IPPROTO_MOBILITY #define IPPROTO_MOBILITY 135 #endif struct pm_iphdr { u_int8_t ip_vhl; /* header length, version */ #define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4) #define IP_HL(ip) ((ip)->ip_vhl & 0x0f) u_int8_t ip_tos; /* type of service */ u_int16_t ip_len; /* total length */ u_int16_t ip_id; /* identification */ u_int16_t ip_off; /* fragment offset field */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ u_int8_t ip_ttl; /* time to live */ u_int8_t ip_p; /* protocol */ u_int16_t ip_sum; /* checksum */ struct in_addr ip_src; /* source and destination addresses */ struct in_addr ip_dst; }; typedef u_int32_t tcp_seq; struct pm_tcphdr { u_int16_t th_sport; /* source port */ u_int16_t th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #if defined IM_LITTLE_ENDIAN u_int8_t th_x2:4; /* (unused) */ u_int8_t th_off:4; /* data offset */ #endif #if defined IM_BIG_ENDIAN u_int8_t th_off:4; /* data offset */ u_int8_t th_x2:4; /* (unused) */ #endif u_int8_t th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 u_int16_t th_win; /* window */ u_int16_t th_sum; /* checksum */ u_int16_t th_urp; /* urgent pointer */ }; /* For TCP_MD5SIG socket option. */ #ifndef TCP_MD5SIG_MAXKEYLEN #define TCP_MD5SIG_MAXKEYLEN 80 #endif #ifndef TCP_MD5SIG #define TCP_MD5SIG 14 #endif struct pm_tcp_md5sig { struct sockaddr_storage tcpm_addr; /* Address associated. */ u_int16_t __tcpm_pad1; /* Zero. */ u_int16_t tcpm_keylen; /* Key length. */ u_int32_t __tcpm_pad2; /* Zero. */ u_int8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary). */ }; #define UDP_PORT_VXLAN 4789 struct pm_udphdr { u_int16_t uh_sport; /* source port */ u_int16_t uh_dport; /* destination port */ u_int16_t uh_ulen; /* udp length */ u_int16_t uh_sum; /* udp checksum */ }; struct pm_icmphdr { u_int8_t type; /* message type */ u_int8_t code; /* type sub-code */ u_int16_t checksum; }; struct pm_tlhdr { u_int16_t src_port; /* source and destination ports */ u_int16_t dst_port; }; #define VXLAN_FLAG_I 0x8 /* according to rfc7348 */ struct vxlan_hdr { u_int8_t flags; u_char reserved1[3]; u_char vni[3]; u_int8_t reserved2; } __attribute__ ((packed)); #define MAX_GTP_TRIALS 8 struct pm_gtphdr_v0 { u_int8_t flags; u_int8_t message; u_int16_t length; }; struct pm_gtphdr_v1 { u_int8_t flags; u_int8_t message; u_int16_t length; u_int32_t teid; }; /* typedefs */ typedef u_int32_t as_t; typedef u_int16_t as16_t; typedef u_int16_t afi_t; typedef u_int8_t safi_t; /* RD: standard */ #define RD_LEN 8 #define RD_TYPE_AS 0 #define RD_TYPE_IP 1 #define RD_TYPE_AS4 2 /* RD: squat squat */ #define RD_TYPE_VRFID 0x1000 #define RD_TYPE_MASK 0x1FFF #define RD_ORIGIN_UNKNOWN 0x0000 #define RD_ORIGIN_FLOW 0x2000 #define RD_ORIGIN_BGP 0x4000 #define RD_ORIGIN_BMP 0x8000 #define RD_ORIGIN_MASK 0xE000 #define RD_ORIGIN_FUNC_TYPE_MAX 2 struct rd_as { u_int16_t type; u_int16_t as; u_int32_t val; } __attribute__ ((packed)); struct rd_ip { u_int16_t type; struct in_addr ip; u_int16_t val; } __attribute__ ((packed)); struct rd_as4 { u_int16_t type; as_t as; u_int16_t val; } __attribute__ ((packed)); /* Picking one of the three structures as rd_t for simplicity */ typedef struct rd_as rd_t; typedef u_int32_t path_id_t; struct flow_chars { u_int8_t traffic_type; u_int8_t is_bi; }; struct packet_ptrs { struct pcap_pkthdr *pkthdr; /* ptr to header structure passed by libpcap */ u_char *f_agent; /* ptr to flow export agent */ u_char *f_header; /* ptr to NetFlow packet header */ u_char *f_data; /* ptr to NetFlow data */ u_char *f_tpl; /* ptr to NetFlow V9 template */ u_char *f_status; /* ptr to status table entry */ u_char *f_status_g; /* ptr to status table entry. global per f_agent */ u_char *tag_table; /* ptr to a tag table map */ u_char *bpas_table; /* ptr to bgp_peer_as_src table map */ u_char *blp_table; /* ptr to bgp_src_local_pref table map */ u_char *bmed_table; /* ptr to bgp_src_med table map */ u_char *bta_table; /* ptr to bgp_to_agent table map */ u_char *bitr_table; /* ptr to flow_to_rd table map */ u_char *sampling_table; /* ptr to sampling_map table map */ u_char *packet_ptr; /* ptr to the whole packet */ u_char *mac_ptr; /* ptr to mac addresses */ u_int16_t l3_proto; /* layer-3 protocol: IPv4, IPv6 */ int (*l3_handler)(register struct packet_ptrs *); /* layer-3 protocol handler */ u_int16_t l4_proto; /* layer-4 protocol */ struct flow_chars flow_type; /* Flow, NAT event, etc. */ pm_id_t tag; /* pre tag id */ u_int8_t have_tag; /* have tag? */ pm_id_t tag2; /* pre tag id2 */ u_int8_t have_tag2; /* have tag2? */ pt_label_t label; /* pre tag label */ u_int8_t have_label; /* have label? */ pm_id_t bpas; /* bgp_peer_as_src */ pm_id_t blp; /* bgp_src_local_pref */ pm_id_t bmed; /* bgp_src_med */ u_int16_t bta_af; /* bgp_to_agent address family */ pm_id_t bta; /* bgp_to_agent */ pm_id_t bta2; /* bgp_to_agent (cont.d: 64bits more for IPv6 addresses) */ pm_id_t bitr; /* flow_to_rd */ pm_id_t st; /* sampling_map */ s_uint8_t set_tos; /* pretag map: set_tos feature */ s_uint16_t lookup_bgp_port; /* bgp_agent_map: lookup BGP port feature */ char *bgp_src; /* pointer to bgp_node structure for source prefix, if any */ char *bgp_dst; /* pointer to bgp_node structure for destination prefix, if any */ char *bgp_src_info; /* pointer to bgp_info structure for source prefix, if any */ char *bgp_dst_info; /* pointer to bgp_info structure for destination prefix, if any */ char *bgp_peer; /* record BGP peer's Router-ID */ char *bgp_nexthop_info; /* record bgp_info of BGP next-hop in case of follow-up */ u_int8_t src_roa; /* record ROA status for source prefix */ u_int8_t dst_roa; /* record ROA status for destination prefix */ char *igp_src; /* pointer to IGP node structure for source prefix, if any */ char *igp_dst; /* pointer to IGP node structure for destination prefix, if any */ char *igp_src_info; /* pointer to IGP node info structure for source prefix, if any */ char *igp_dst_info; /* pointer to IGP node info structure for destination prefix, if any */ u_int8_t lm_mask_src; /* Longest match for source prefix (network mask bits) */ u_int8_t lm_mask_dst; /* Longest match for destination prefix (network mask bits) */ u_int8_t lm_method_src; /* Longest match for source prefix (method: BGP, IGP, etc.) */ u_int8_t lm_method_dst; /* Longest match for destination prefix (method: BGP, IGP, etc.) */ u_int16_t pf; /* pending fragments or packets */ u_int8_t new_flow; /* pmacctd flows: part of a new flow ? */ u_int8_t tcp_flags; /* pmacctd flows: TCP packet flags; URG, PUSH filtered out */ u_int8_t icmp_type; /* pmacctd/uacctd -> nfprobe: ICMP / ICMPv6 type */ u_int8_t icmp_code; /* pmacctd/uacctd -> nfprobe: ICMP / ICMPv6 code */ u_int8_t frag_first_found; /* entry found in fragments table */ u_int16_t frag_sum_bytes; /* accumulated bytes by fragment entry, ie. due to out of order */ u_int16_t frag_sum_pkts; /* accumulated packets by fragment entry, ie. due to out of order */ u_char *vlan_ptr; /* ptr to (outer) vlan id */ u_char *cvlan_ptr; /* ptr to inner vlan id */ u_char *mpls_ptr; /* ptr to base MPLS label */ u_char *iph_ptr; /* ptr to ip header */ u_char *tlh_ptr; /* ptr to transport level protocol header */ u_char *vxlan_ptr; /* ptr to VXLAN VNI */ u_char *payload_ptr; /* classifiers: ptr to packet payload */ pm_class_t class; /* classifiers: class id */ u_int8_t shadow; /* 0=the packet is being distributed for the 1st time 1=the packet is being distributed for the 2nd+ time */ u_int32_t ifindex_in; /* input ifindex; used by pmacctd/uacctd */ u_int32_t ifindex_out; /* output ifindex; used by pmacctd/uacctd */ u_int8_t direction; /* packet sampling direction; used by pmacctd/uacctd */ u_char *tun_pptrs; /* tunnel packet pointers */ u_int8_t tun_stack; /* tunnell stack */ u_int8_t tun_layer; /* tunnell layer count */ u_int32_t sample_type; /* sFlow sample type */ u_int32_t seqno; /* sFlow/NetFlow sequence number */ u_int16_t f_len; /* sFlow/NetFlow payload length */ char *tee_dissect; /* pointer to flow tee dissection structure */ int tee_dissect_bcast; /* is the tee dissected element to be broadcasted? */ u_int8_t renormalized; /* Is it renormalized yet ? */ u_char *pkt_data_ptrs[CUSTOM_PRIMITIVE_MAX_PPTRS_IDX]; /* indexed packet pointers */ u_int16_t pkt_proto[CUSTOM_PRIMITIVE_MAX_PPTRS_IDX]; /* indexed packet protocols */ #if defined (WITH_GEOIPV2) MMDB_lookup_result_s geoipv2_src; MMDB_lookup_result_s geoipv2_dst; #endif #if defined (WITH_NDPI) pm_class2_t ndpi_class; #endif }; struct pkt_primitives { #if defined (HAVE_L2) u_int8_t eth_dhost[ETH_ADDR_LEN]; u_int8_t eth_shost[ETH_ADDR_LEN]; u_int16_t vlan_id; u_int16_t out_vlan_id; u_int8_t cos; u_int16_t etype; #endif struct host_addr src_ip; struct host_addr dst_ip; struct host_addr src_net; struct host_addr dst_net; u_int8_t src_nmask; u_int8_t dst_nmask; as_t src_as; as_t dst_as; u_int16_t src_port; u_int16_t dst_port; u_int8_t tos; u_int8_t proto; u_int32_t ifindex_in; u_int32_t ifindex_out; #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) pm_country_t src_ip_country; pm_country_t dst_ip_country; pm_pocode_t src_ip_pocode; pm_pocode_t dst_ip_pocode; double src_ip_lat; double src_ip_lon; double dst_ip_lat; double dst_ip_lon; #endif #if defined (WITH_NDPI) pm_class2_t ndpi_class; #endif pm_id_t tag; pm_id_t tag2; pm_class_t class; u_int32_t sampling_rate; u_int8_t sampling_direction; u_int32_t export_proto_seqno; u_int8_t export_proto_version; u_int32_t export_proto_sysid; }; struct pkt_data { struct pkt_primitives primitives; pm_counter_t pkt_len; pm_counter_t pkt_num; pm_counter_t flo_num; u_int8_t flow_type; u_int8_t tcp_flags; u_int8_t tunnel_tcp_flags; struct timeval time_start; struct timeval time_end; }; struct pkt_payload { u_int16_t cap_len; pm_counter_t sample_pool; pm_counter_t pkt_len; pm_counter_t pkt_num; u_int32_t time_start; pm_class_t class; #if defined (WITH_NDPI) pm_class2_t ndpi_class; #endif pm_id_t tag; pm_id_t tag2; struct host_addr src_ip; struct host_addr dst_ip; as_t src_as; as_t dst_as; u_int32_t ifindex_in; u_int32_t ifindex_out; u_int8_t src_nmask; u_int8_t dst_nmask; u_int16_t vlan; u_int8_t priority; struct host_addr bgp_next_hop; }; struct pkt_vlen_hdr_primitives { u_int16_t tot_len; u_int16_t num; } __attribute__ ((packed)); struct pkt_extras { u_int8_t tcp_flags; u_int8_t icmp_type; u_int8_t icmp_code; }; #define PKT_MSG_SIZE 10000 struct pkt_msg { struct sockaddr_storage agent; u_int32_t seqno; u_int16_t len; u_char *payload; pm_id_t tag; pm_id_t tag2; u_int8_t bcast; u_int16_t pad; }; struct pkt_stitching { struct timeval timestamp_min; struct timeval timestamp_max; }; /* START: BGP section */ #define MAX_BGP_STD_COMMS 96 #define MAX_BGP_EXT_COMMS 96 #define MAX_BGP_LRG_COMMS 96 #define MAX_BGP_ASPATH 128 /* MPLS */ #define MAX_MPLS_LABELS 10 #define MAX_MPLS_LABEL_LEN 16 struct extra_primitives { u_int16_t off_pkt_bgp_primitives; u_int16_t off_pkt_lbgp_primitives; u_int16_t off_pkt_nat_primitives; u_int16_t off_pkt_mpls_primitives; u_int16_t off_pkt_tun_primitives; u_int16_t off_custom_primitives; u_int16_t off_pkt_extras; /* nfprobe only */ u_int16_t off_pkt_vlen_hdr_primitives; }; struct primitives_ptrs { struct pkt_data *data; struct pkt_bgp_primitives *pbgp; struct pkt_legacy_bgp_primitives *plbgp; struct pkt_nat_primitives *pnat; struct pkt_mpls_primitives *pmpls; struct pkt_tunnel_primitives *ptun; u_char *pcust; struct pkt_extras *pextras; struct pkt_vlen_hdr_primitives *pvlen; u_int16_t vlen_next_off; }; typedef void (*primptrs_func) (u_char *, struct extra_primitives *, struct primitives_ptrs *); struct pkt_bgp_primitives { as_t peer_src_as; as_t peer_dst_as; struct host_addr peer_src_ip; struct host_addr peer_dst_ip; u_int32_t local_pref; u_int32_t med; u_int32_t src_local_pref; u_int32_t src_med; rd_t mpls_vpn_rd; u_int32_t mpls_pw_id; u_int8_t src_roa; u_int8_t dst_roa; }; struct pkt_legacy_bgp_primitives { char std_comms[MAX_BGP_STD_COMMS]; char ext_comms[MAX_BGP_EXT_COMMS]; char lrg_comms[MAX_BGP_LRG_COMMS]; char as_path[MAX_BGP_ASPATH]; char src_std_comms[MAX_BGP_STD_COMMS]; char src_ext_comms[MAX_BGP_EXT_COMMS]; char src_lrg_comms[MAX_BGP_LRG_COMMS]; char src_as_path[MAX_BGP_ASPATH]; }; struct pkt_nat_primitives { struct host_addr post_nat_src_ip; struct host_addr post_nat_dst_ip; u_int16_t post_nat_src_port; u_int16_t post_nat_dst_port; u_int8_t nat_event; u_int8_t fw_event; u_int8_t fwd_status; struct timeval timestamp_start; /* XXX: clean-up: to be moved in a separate structure */ struct timeval timestamp_end; /* XXX: clean-up: to be moved in a separate structure */ struct timeval timestamp_arrival; /* XXX: clean-up: to be moved in a separate structure */ struct timeval timestamp_export; /* XXX: clean-up: to be moved in a separate structure */ }; struct pkt_mpls_primitives { u_int32_t mpls_label_top; u_int32_t mpls_label_bottom; }; struct pkt_tunnel_primitives { u_int8_t tunnel_eth_dhost[ETH_ADDR_LEN]; u_int8_t tunnel_eth_shost[ETH_ADDR_LEN]; struct host_addr tunnel_src_ip; struct host_addr tunnel_dst_ip; u_int8_t tunnel_tos; u_int8_t tunnel_proto; u_int16_t tunnel_src_port; u_int16_t tunnel_dst_port; u_int8_t tunnel_tcp_flags; u_int32_t tunnel_id; /* ie. VXLAN VNI */ }; /* same as pkt_legacy_bgp_primitives but pointers in place of strings */ struct cache_legacy_bgp_primitives { char *std_comms; char *ext_comms; char *lrg_comms; char *as_path; char *src_std_comms; char *src_ext_comms; char *src_lrg_comms; char *src_as_path; }; /* END: BGP section */ struct packet_ptrs_vector { struct packet_ptrs v4; struct packet_ptrs vlan4; struct packet_ptrs mpls4; struct packet_ptrs vlanmpls4; struct packet_ptrs v6; struct packet_ptrs vlan6; struct packet_ptrs mpls6; struct packet_ptrs vlanmpls6; }; struct hosts_table_entry { struct host_addr addr; struct host_mask mask; }; struct hosts_table { int num; time_t timestamp; struct hosts_table_entry table[MAX_MAP_ENTRIES]; }; struct bgp_md5_table_entry { struct host_addr addr; char key[TCP_MD5SIG_MAXKEYLEN]; }; struct bgp_md5_table { int num; struct bgp_md5_table_entry table[BGP_MD5_MAP_ENTRIES]; }; #define TUNNEL_PROTO_STRING 16 #define TUNNEL_REGISTRY_STACKS 9 /* MAX + 1 */ #define TUNNEL_REGISTRY_ENTRIES 4 typedef int (*tunnel_func)(register struct packet_ptrs *); struct tunnel_handler { tunnel_func tf; u_int8_t proto; u_int16_t port; }; typedef int (*tunnel_configurator)(struct tunnel_handler *, char *); struct tunnel_entry { char type[TUNNEL_PROTO_STRING]; tunnel_func tf; tunnel_configurator tc; }; /* global variables */ extern struct tunnel_handler tunnel_registry[TUNNEL_REGISTRY_STACKS][TUNNEL_REGISTRY_ENTRIES]; /* http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt */ typedef struct { union { struct { char line[108]; } v1; struct { uint8_t sig[12]; uint8_t ver_cmd; uint8_t fam; uint16_t len; union { struct { /* for TCP/UDP over IPv4, len = 12 */ uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port; } ip4; struct { /* for TCP/UDP over IPv6, len = 36 */ uint8_t src_addr[16]; uint8_t dst_addr[16]; uint16_t src_port; uint16_t dst_port; } ip6; struct { /* for AF_UNIX sockets, len = 216 */ uint8_t src_addr[108]; uint8_t dst_addr[108]; } unx; } addr; } v2; }; } proxy_protocol_header; #ifdef WITH_GNUTLS #define PM_DTLS_TIMEOUT_RETRANS (1 * 1000) #define PM_DTLS_TIMEOUT_TOTAL (60 * 1000) #define PM_DTLS_TIMEOUT_HS (5 * 1000) #define PM_DTLS_MTU 1500 typedef struct { gnutls_certificate_credentials_t x509_cred; gnutls_datum_t cookie_key; gnutls_priority_t priority_cache; } pm_dtls_glob_t; typedef struct { int fd; int stage; int do_reconnect; struct sockaddr_storage peer; socklen_t peer_len; unsigned char seq[8]; void *async_rx; void *async_tx; } pm_dtls_conn_t; typedef struct { gnutls_session_t session; gnutls_dtls_prestate_st prestate; pm_dtls_conn_t conn; } pm_dtls_peer_t; #define PM_DTLS_STAGE_DOWN 0 #define PM_DTLS_STAGE_HELLO 1 #define PM_DTLS_STAGE_HANDSHAKE 2 #define PM_DTLS_STAGE_UP 3 #endif /* prototypes */ extern int parse_proxy_header(int, struct host_addr *, u_int16_t *); extern u_int16_t pm_checksum(u_int16_t *, int, u_int32_t *, int); extern u_int16_t pm_udp6_checksum(struct ip6_hdr *, struct pm_udphdr *, u_char *, int); #ifdef WITH_GNUTLS extern void pm_dtls_init(pm_dtls_glob_t *, char *); extern ssize_t pm_dtls_server_recv(gnutls_transport_ptr_t, void *, size_t); extern ssize_t pm_dtls_server_send(gnutls_transport_ptr_t, const void *, size_t); extern int pm_dtls_server_select(gnutls_transport_ptr_t, unsigned int); extern void pm_dtls_server_log(int, const char *); extern void pm_dtls_server_bye(pm_dtls_peer_t *); extern int pm_dtls_server_process(int, struct sockaddr_storage *, socklen_t, u_char *, int, void *); extern void pm_dtls_client_init(pm_dtls_peer_t *, int, struct sockaddr_storage *, socklen_t, char *); extern int pm_dtls_client_recv_async(pm_dtls_peer_t *); extern ssize_t pm_dtls_client_send(pm_dtls_peer_t *, const void *, size_t); extern void pm_dtls_client_bye(pm_dtls_peer_t *); #endif #endif //PMACCT_NETWORK_H pmacct-1.7.8/src/redis_common.c0000644000175000017500000002126414354105275015430 0ustar paolopaolo/* * pmacct (Promiscuous mode IP Accounting package) * * Copyright (c) 2003-2022 Paolo Lucente * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "thread_pool.h" /* Global variables */ thread_pool_t *redis_pool; /* Functions */ void p_redis_thread_wrapper(struct p_redis_host *redis_host) { /* initialize threads pool */ redis_pool = allocate_thread_pool(1); assert(redis_pool); assert(redis_host); Log(LOG_DEBUG, "DEBUG ( %s ): %d thread(s) initialized\n", redis_host->log_id, 1); /* giving a kick to the Redis thread */ send_to_pool(redis_pool, p_redis_master_produce_thread, redis_host); } int p_redis_master_produce_thread(void *rh) { struct p_redis_host *redis_host = rh; unsigned int ret = 0, period = 0; p_redis_connect(redis_host, TRUE); for (;;) { if (!ret) { (*redis_host->th_hdlr)(redis_host); period = PM_REDIS_DEFAULT_REFRESH_TIME; } else { period = ret; } ret = sleep(period); } return SUCCESS; } void p_redis_init(struct p_redis_host *redis_host, char *log_id, redis_thread_handler th_hdlr) { if (!redis_host || !log_id || !th_hdlr) return; memset(redis_host, 0, sizeof(struct p_redis_host)); if (config.redis_host) { p_redis_set_log_id(redis_host, log_id); p_redis_set_db(redis_host, config.redis_db); p_redis_set_exp_time(redis_host, PM_REDIS_DEFAULT_EXP_TIME); p_redis_set_thread_handler(redis_host, th_hdlr); if (!config.cluster_name) { Log(LOG_ERR, "ERROR ( %s ): redis_host requires cluster_name to be specified. Exiting...\n\n", redis_host->log_id); exit_gracefully(1); } p_redis_thread_wrapper(redis_host); } } int p_redis_connect(struct p_redis_host *redis_host, int fatal) { struct sockaddr_storage dest; socklen_t dest_len = sizeof(dest); char dest_str[INET6_ADDRSTRLEN]; int dest_port; time_t now = time(NULL); assert(redis_host); if (config.redis_host) { if (now >= (redis_host->last_conn + PM_REDIS_DEFAULT_CONN_RETRY)) { redis_host->last_conn = now; /* round of parsing and validation */ parse_hostport(config.redis_host, (struct sockaddr *)&dest, &dest_len); sa_to_str(dest_str, sizeof(dest_str), (struct sockaddr *)&dest, FALSE); sa_to_port(&dest_port, (struct sockaddr *)&dest); if (!dest_port) { dest_port = PM_REDIS_DEFAULT_PORT; } redis_host->ctx = redisConnect(dest_str, dest_port); if (redis_host->ctx == NULL || redis_host->ctx->err) { if (redis_host->ctx) { if (fatal) { Log(LOG_ERR, "ERROR ( %s ): Connection error: %s\n", redis_host->log_id, redis_host->ctx->errstr); exit_gracefully(1); } else { return ERR; } } else { Log(LOG_ERR, "ERROR ( %s ): Connection error: can't allocate redis context\n", redis_host->log_id); exit_gracefully(1); } } else { Log(LOG_DEBUG, "DEBUG ( %s ): Connection successful\n", redis_host->log_id); } } } return SUCCESS; } void p_redis_close(struct p_redis_host *redis_host) { redisFree(redis_host->ctx); } void p_redis_set_string(struct p_redis_host *redis_host, char *resource, char *value, int expire) { if (expire > 0) { redis_host->reply = redisCommand(redis_host->ctx, "SETEX %s%s%d%s%s %d %s", config.cluster_name, PM_REDIS_DEFAULT_SEP, config.cluster_id, PM_REDIS_DEFAULT_SEP, resource, redis_host->exp_time, value); } else { redis_host->reply = redisCommand(redis_host->ctx, "SET %s%s%d%s%s %s", config.cluster_name, PM_REDIS_DEFAULT_SEP, config.cluster_id, PM_REDIS_DEFAULT_SEP, resource, value); } p_redis_process_reply(redis_host); } void p_redis_set_int(struct p_redis_host *redis_host, char *resource, int value, int expire) { if (expire > 0) { redis_host->reply = redisCommand(redis_host->ctx, "SETEX %s%s%d%s%s %d %d", config.cluster_name, PM_REDIS_DEFAULT_SEP, config.cluster_id, PM_REDIS_DEFAULT_SEP, resource, redis_host->exp_time, value); } else { redis_host->reply = redisCommand(redis_host->ctx, "SET %s%s%d%s%s %d", config.cluster_name, PM_REDIS_DEFAULT_SEP, config.cluster_id, PM_REDIS_DEFAULT_SEP, resource, value); } p_redis_process_reply(redis_host); } void p_redis_ping(struct p_redis_host *redis_host) { redis_host->reply = redisCommand(redis_host->ctx, "PING"); p_redis_process_reply(redis_host); } void p_redis_select_db(struct p_redis_host *redis_host) { char select_cmd[VERYSHORTBUFLEN]; if (redis_host->db) { snprintf(select_cmd, sizeof(select_cmd), "SELECT %d", redis_host->db); redis_host->reply = redisCommand(redis_host->ctx, select_cmd); p_redis_process_reply(redis_host); } } void p_redis_process_reply(struct p_redis_host *redis_host) { if (redis_host->reply) { if (redis_host->reply->type == REDIS_REPLY_ERROR) { Log(LOG_WARNING, "WARN ( %s ): reply='%s'\n", redis_host->log_id, redis_host->reply->str); } freeReplyObject(redis_host->reply); } else { p_redis_connect(redis_host, FALSE); } } void p_redis_set_log_id(struct p_redis_host *redis_host, char *log_id) { if (redis_host) { strlcpy(redis_host->log_id, log_id, sizeof(redis_host->log_id)); strncat(redis_host->log_id, "/redis", (sizeof(redis_host->log_id) - strlen(redis_host->log_id))); } } void p_redis_set_db(struct p_redis_host *redis_host, int db) { if (redis_host) redis_host->db = db; } void p_redis_set_exp_time(struct p_redis_host *redis_host, int exp_time) { if (redis_host) redis_host->exp_time = exp_time; } void p_redis_set_thread_handler(struct p_redis_host *redis_host, redis_thread_handler th_hdlr) { if (redis_host) redis_host->th_hdlr = th_hdlr; } void p_redis_thread_produce_common_core_handler(void *rh) { struct p_redis_host *redis_host = rh; char buf[SRVBUFLEN], name_and_type[SHORTBUFLEN], daemon_type[VERYSHORTBUFLEN]; switch (config.acct_type) { case ACCT_NF: snprintf(daemon_type, sizeof(daemon_type), "%s", "nfacctd"); break; case ACCT_SF: snprintf(daemon_type, sizeof(daemon_type), "%s", "sfacctd"); break; case ACCT_PM: if (config.uacctd_group) { snprintf(daemon_type, sizeof(daemon_type), "%s", "uacctd"); } else { snprintf(daemon_type, sizeof(daemon_type), "%s", "pmacctd"); } break; case ACCT_PMBGP: snprintf(daemon_type, sizeof(daemon_type), "%s", "pmbgpd"); break; case ACCT_PMBMP: snprintf(daemon_type, sizeof(daemon_type), "%s", "pmbmpd"); break; case ACCT_PMTELE: snprintf(daemon_type, sizeof(daemon_type), "%s", "pmtelemetryd"); break; default: break; } p_redis_set_string(redis_host, "daemon_type", daemon_type, PM_REDIS_DEFAULT_EXP_TIME); snprintf(name_and_type, sizeof(name_and_type), "process%s%s%s%s", PM_REDIS_DEFAULT_SEP, config.name, PM_REDIS_DEFAULT_SEP, config.type); p_redis_set_int(redis_host, name_and_type, TRUE, PM_REDIS_DEFAULT_EXP_TIME); if (config.acct_type < ACCT_FWDPLANE_MAX) { if (config.nfacctd_isis) { snprintf(buf, sizeof(buf), "%s%sisis", name_and_type, PM_REDIS_DEFAULT_SEP); p_redis_set_int(redis_host, buf, TRUE, PM_REDIS_DEFAULT_EXP_TIME); } if (config.bgp_daemon) { snprintf(buf, sizeof(buf), "%s%sbgp", name_and_type, PM_REDIS_DEFAULT_SEP); p_redis_set_int(redis_host, buf, TRUE, PM_REDIS_DEFAULT_EXP_TIME); } if (config.bmp_daemon) { snprintf(buf, sizeof(buf), "%s%sbmp", name_and_type, PM_REDIS_DEFAULT_SEP); p_redis_set_int(redis_host, buf, TRUE, PM_REDIS_DEFAULT_EXP_TIME); } if (config.telemetry_daemon) { snprintf(buf, sizeof(buf), "%s%stelemetry", name_and_type, PM_REDIS_DEFAULT_SEP); p_redis_set_int(redis_host, buf, TRUE, PM_REDIS_DEFAULT_EXP_TIME); } } } void p_redis_thread_produce_common_plugin_handler(void *rh) { struct p_redis_host *redis_host = rh; char name_and_type[SRVBUFLEN]; snprintf(name_and_type, sizeof(name_and_type), "process%s%s%s%s", PM_REDIS_DEFAULT_SEP, config.name, PM_REDIS_DEFAULT_SEP, config.type); p_redis_set_int(redis_host, name_and_type, TRUE, PM_REDIS_DEFAULT_EXP_TIME); } pmacct-1.7.8/src/mongodb_plugin.h0000644000175000017500000000320114354105275015751 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MONGODB_PLUGIN_H #define MONGODB_PLUGIN_H /* includes */ #include #include #include /* defines */ #if (!defined MONGO_HAVE_STDINT) #define MONGO_HAVE_STDINT 1 #endif #include #define DEFAULT_MONGO_INSERT_BATCH 10000 /* structures */ /* prototypes */ extern void mongodb_plugin(int, struct configuration *, void *); extern void mongodb_legacy_warning(int, struct configuration *, void *); extern void MongoDB_cache_purge(struct chained_cache *[], int, int); extern void MongoDB_create_indexes(mongo *, const char *); extern int MongoDB_get_database(char *, int, char *); extern void MongoDB_append_string(bson *, char *, struct pkt_vlen_hdr_primitives *, pm_cfgreg_t); extern int MongoDB_oid_fuzz(); /* global vars */ extern mongo db_conn; #endif //MONGODB_PLUGIN_H pmacct-1.7.8/src/ll.c0000644000175000017500000002743614354105275013370 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" /* eth_handler() picks a whole packet, reads informtions contained in the link layer protocol header and fills a pointer structure */ void eth_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { u_int16_t e8021Q, ppp, cfp, cvnt; struct eth_header *eth_pk; u_int16_t etype, caplen = h->caplen, nl; u_int8_t cursor = 0; if (caplen < ETHER_HDRLEN) { pptrs->iph_ptr = NULL; return; } eth_pk = (struct eth_header *) pptrs->packet_ptr; etype = ntohs(eth_pk->ether_type); pptrs->mac_ptr = (u_char *) eth_pk->ether_dhost; pptrs->vlan_ptr = NULL; /* avoid stale vlan pointers */ pptrs->mpls_ptr = NULL; /* avoid stale MPLS pointers */ nl = ETHER_HDRLEN; caplen -= ETHER_HDRLEN; recurse: if (etype == ETHERTYPE_IP) { pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; pptrs->iph_ptr = pptrs->packet_ptr + nl; return; } if (etype == ETHERTYPE_IPV6) { pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; pptrs->iph_ptr = pptrs->packet_ptr + nl; return; } /* originally contributed by Rich Gade */ if (etype == ETHERTYPE_8021Q || etype == ETHERTYPE_8021AD) { if (caplen < IEEE8021Q_TAGLEN) { pptrs->iph_ptr = NULL; return; } memcpy(&e8021Q, (pptrs->packet_ptr + nl + 2), 2); if (!cursor) { pptrs->vlan_ptr = (pptrs->packet_ptr + nl); } else { if (pptrs->vlan_ptr) { pptrs->cvlan_ptr = (pptrs->packet_ptr + nl); } } etype = ntohs(e8021Q); nl += IEEE8021Q_TAGLEN; caplen -= IEEE8021Q_TAGLEN; cursor++; goto recurse; } /* Process Cisco Fabric Path Header */ if (etype == ETHERTYPE_CFP) { if (caplen < CFP_TAGLEN) { pptrs->iph_ptr = NULL; return; } memcpy(&cfp, pptrs->packet_ptr+nl+CFP_TAGLEN-2, 2); etype = ntohs(cfp); nl += CFP_TAGLEN; caplen -= CFP_TAGLEN; cursor++; goto recurse; } /* Process Cisco Virtual Network TAG Header */ if (etype == ETHERTYPE_CVNT) { if (caplen < CVNT_TAGLEN) { pptrs->iph_ptr = NULL; return; } memcpy(&cvnt, pptrs->packet_ptr+nl+CVNT_TAGLEN-2, 2); etype = ntohs(cvnt); nl += CVNT_TAGLEN; caplen -= CVNT_TAGLEN; cursor++; goto recurse; } /* originally contributed by Vasiliy Ponomarev */ if (etype == ETHERTYPE_PPPOE) { if (caplen < PPPOE_HDRLEN+PPP_TAGLEN) { pptrs->iph_ptr = NULL; return; } memcpy(&ppp, pptrs->packet_ptr+nl+PPPOE_HDRLEN, 2); etype = ntohs(ppp); if (etype == PPP_IP) etype = ETHERTYPE_IP; if (etype == PPP_IPV6) etype = ETHERTYPE_IPV6; nl += PPPOE_HDRLEN+PPP_TAGLEN; caplen -= PPPOE_HDRLEN+PPP_TAGLEN; cursor = 1; goto recurse; } if (etype == ETHERTYPE_MPLS || etype == ETHERTYPE_MPLS_MULTI) { etype = mpls_handler(pptrs->packet_ptr + nl, &caplen, &nl, pptrs); cursor = 1; goto recurse; } if (config.aggregate_unknown_etype) { pptrs->l3_proto = etype; pptrs->l3_handler = unknown_etype_handler; pptrs->iph_ptr = pptrs->packet_ptr + nl; return; } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } u_int16_t mpls_handler(u_char *bp, u_int16_t *caplen, u_int16_t *nl, register struct packet_ptrs *pptrs) { u_int32_t *p = (u_int32_t *) bp; u_char *next = bp; u_int32_t label=0; pptrs->mpls_ptr = bp; if (*caplen < 4) { pptrs->iph_ptr = NULL; return 0; } do { label = ntohl(*p); p += 4; *nl += 4; next += 4; *caplen -= 4; } while (!MPLS_STACK(label) && *caplen >= 4); switch (MPLS_LABEL(label)) { case 0: /* IPv4 explicit NULL label */ case 3: /* IPv4 implicit NULL label */ return ETHERTYPE_IP; case 2: /* IPv6 explicit NULL label */ return ETHERTYPE_IPV6; default: /* support for what is sometimes referred as null-encapsulation: by looking at the first payload byte (but only if the Bottom of Stack bit is set) we try to determine the network layer protocol: 0x45-0x4f is IPv4 0x60-0x6f is IPv6 */ if (MPLS_STACK(label)) { switch (*next) { case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: return ETHERTYPE_IP; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: return ETHERTYPE_IPV6; default: break; } } break; } return FALSE; } void ppp_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { u_char *p = pptrs->packet_ptr; u_int16_t caplen = h->caplen, nl = 0; unsigned int proto = 0; if (caplen < PPP_HDRLEN) { pptrs->iph_ptr = NULL; return; } if (*p == PPP_ADDRESS && *(p + 1) == PPP_CONTROL) { p += 2; caplen -= 2; if (caplen < 2) { pptrs->iph_ptr = NULL; return; } } if (*p % 2) { proto = *p; p++; } else { proto = EXTRACT_16BITS(p); p += 2; } recurse: if ((proto == PPP_IP) || (proto == ETHERTYPE_IP)) { pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; pptrs->iph_ptr = p; return; } if ((proto == PPP_IPV6) || (proto == ETHERTYPE_IPV6)) { pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; pptrs->iph_ptr = p; return; } if (proto == PPP_MPLS_UCAST || proto == PPP_MPLS_MCAST) { proto = mpls_handler(p, &caplen, &nl, pptrs); goto recurse; } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } /* support for 802.11 Wireless LAN protocol. I'm writing it during a sad morning spent at Fiumicino's Airport because of Alitalia strikes. It's currently working well for me at FCO WiFi zone. Let me know. 28-11-2003, Paolo. */ void ieee_802_11_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { u_int16_t fc; u_int caplen = h->caplen; short int hdrlen; u_char *p; if (caplen < IEEE802_11_FC_LEN) { pptrs->iph_ptr = NULL; return; } p = pptrs->packet_ptr; fc = EXTRACT_LE_16BITS(p); if (FC_TYPE(fc) == T_DATA) { if (FC_TO_DS(fc) && FC_FROM_DS(fc)) hdrlen = 30; else hdrlen = 24; if (caplen < hdrlen) { pptrs->iph_ptr = NULL; return; } caplen -= hdrlen; p += hdrlen; if (!FC_WEP(fc)) { if ((p = llc_handler(h, caplen, p, pptrs)) != NULL) { pptrs->iph_ptr = p; return; } } } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } void raw_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { register u_int16_t caplen = h->caplen; struct pm_iphdr *hdr; if (caplen < 4) { pptrs->iph_ptr = NULL; return; } hdr = (struct pm_iphdr *) pptrs->packet_ptr; switch (IP_V(hdr)) { case 4: pptrs->iph_ptr = pptrs->packet_ptr; pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; return; case 6: pptrs->iph_ptr = pptrs->packet_ptr; pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; return; default: pptrs->iph_ptr = NULL; pptrs->l3_proto = 0; pptrs->l3_handler = NULL; return; } } void null_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { register u_int32_t *family; u_int caplen = h->caplen; if (caplen < 4) { pptrs->iph_ptr = NULL; return; } family = (u_int32_t *) pptrs->packet_ptr; if (*family == AF_INET || ntohl(*family) == AF_INET ) { pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; pptrs->iph_ptr = (u_char *)(pptrs->packet_ptr + 4); return; } if (*family == AF_INET6 || ntohl(*family) == AF_INET6 ) { pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; pptrs->iph_ptr = (u_char *)(pptrs->packet_ptr + 4); return; } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } void sll_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { register const struct sll_header *sllp; register u_short etype; u_char *p; u_int16_t caplen = h->caplen; u_int16_t e8021Q, nl; int cursor; if (caplen < SLL_HDR_LEN) { pptrs->iph_ptr = NULL; return; } pptrs->mac_ptr = NULL; pptrs->vlan_ptr = NULL; pptrs->mpls_ptr = NULL; p = pptrs->packet_ptr; sllp = (const struct sll_header *) pptrs->packet_ptr; etype = ntohs(sllp->sll_protocol); nl = SLL_HDR_LEN; if (EXTRACT_16BITS(&sllp->sll_halen) == ETH_ADDR_LEN) { memcpy(sll_mac[1], sllp->sll_addr, ETH_ADDR_LEN); pptrs->mac_ptr = (u_char *) sll_mac; } recurse: if (etype == ETHERTYPE_IP) { pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; pptrs->iph_ptr = (u_char *)(pptrs->packet_ptr + nl); return; } if (etype == ETHERTYPE_IPV6) { pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; pptrs->iph_ptr = pptrs->packet_ptr + nl; return; } if (etype == LINUX_SLL_P_802_2) { /* going up to LLC/SNAP layer header */ p += SLL_HDR_LEN; caplen -= SLL_HDR_LEN; if ((p = llc_handler(h, caplen, p, pptrs)) != NULL) { pptrs->iph_ptr = p; return; } } /* originally contributed by Rich Gade for eth_handler() */ if (etype == ETHERTYPE_8021Q || etype == ETHERTYPE_8021AD) { if (caplen < IEEE8021Q_TAGLEN) { pptrs->iph_ptr = NULL; return; } memcpy(&e8021Q, (pptrs->packet_ptr + nl + 2), 2); if (!cursor) { pptrs->vlan_ptr = (pptrs->packet_ptr + nl); } else { if (pptrs->vlan_ptr) { pptrs->cvlan_ptr = (pptrs->packet_ptr + nl); } } etype = ntohs(e8021Q); nl += IEEE8021Q_TAGLEN; caplen -= IEEE8021Q_TAGLEN; cursor++; goto recurse; } if (etype == ETHERTYPE_MPLS || etype == ETHERTYPE_MPLS_MULTI) { etype = mpls_handler(pptrs->packet_ptr + nl, &caplen, &nl, pptrs); cursor = 1; goto recurse; } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } u_char *llc_handler(const struct pcap_pkthdr *h, u_int caplen, register u_char *buf, register struct packet_ptrs *pptrs) { struct llc llc; register u_short etype; if (caplen < 3) return NULL; memcpy((char *)&llc, (char *) buf, MIN(caplen, sizeof(llc))); if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP && llc.ctl.snap.snap_ui == LLC_UI) { etype = EXTRACT_16BITS(&llc.ctl.snap_ether.snap_ethertype[0]); if (etype == ETHERTYPE_IP) { pptrs->l3_proto = ETHERTYPE_IP; pptrs->l3_handler = ip_handler; return (u_char *)(buf + MIN(caplen, sizeof(llc))); } if (etype == ETHERTYPE_IPV6) { pptrs->l3_proto = ETHERTYPE_IPV6; pptrs->l3_handler = ip6_handler; return (u_char *)(buf + MIN(caplen, sizeof(llc))); } return NULL; } else return NULL; } pmacct-1.7.8/src/server.c0000644000175000017500000006672614354105275014274 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "imt_plugin.h" #include "ip_flow.h" #include "classifier.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" /* functions */ int build_query_server(char *path_ptr) { struct sockaddr_un sAddr; int sd, rc; sd=socket(AF_UNIX, SOCK_STREAM, 0); if (sd < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): cannot open socket.\n", config.name, config.type); exit_gracefully(1); } sAddr.sun_family = AF_UNIX; strcpy(sAddr.sun_path, path_ptr); unlink(path_ptr); rc = bind(sd, (struct sockaddr *) &sAddr,sizeof(sAddr)); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): cannot bind to file %s .\n", config.name, config.type, path_ptr); exit_gracefully(1); } chmod(path_ptr, S_IRUSR|S_IWUSR|S_IXUSR| S_IRGRP|S_IWGRP|S_IXGRP| S_IROTH|S_IWOTH|S_IXOTH); setnonblocking(sd); listen(sd, 1); Log(LOG_INFO, "OK ( %s/%s ): waiting for data on: '%s'\n", config.name, config.type, path_ptr); return sd; } void process_query_data(int sd, unsigned char *buf, int len, struct extra_primitives *extras, int datasize, int forked) { struct acc *acc_elem = 0; struct bucket_desc bd; struct query_header *q, *uq; struct query_entry request; struct reply_buffer rb; unsigned char *elem, *bufptr; int following_chain=0; unsigned int idx; struct pkt_data dummy; struct pkt_bgp_primitives dummy_pbgp; struct pkt_legacy_bgp_primitives dummy_plbgp; struct pkt_nat_primitives dummy_pnat; struct pkt_mpls_primitives dummy_pmpls; struct pkt_tunnel_primitives dummy_ptun; char *dummy_pcust = NULL, *custbuf = NULL; struct pkt_vlen_hdr_primitives dummy_pvlen; char emptybuf[LARGEBUFLEN]; int reset_counter, offset = PdataSz; dummy_pcust = malloc(config.cpptrs.len); custbuf = malloc(config.cpptrs.len); if (!dummy_pcust || !custbuf) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() dummy_pcust. Exiting.\n", config.name, config.type); exit_gracefully(1); } memset(&dummy, 0, sizeof(struct pkt_data)); memset(&dummy_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&dummy_plbgp, 0, sizeof(struct pkt_legacy_bgp_primitives)); memset(&dummy_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&dummy_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&dummy_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(dummy_pcust, 0, config.cpptrs.len); memset(custbuf, 0, config.cpptrs.len); memset(&dummy_pvlen, 0, sizeof(struct pkt_vlen_hdr_primitives)); memset(emptybuf, 0, LARGEBUFLEN); memset(&rb, 0, sizeof(struct reply_buffer)); memcpy(rb.buf, buf, sizeof(struct query_header)); rb.len = LARGEBUFLEN-sizeof(struct query_header); rb.packed = sizeof(struct query_header); /* arranging some pointer */ uq = (struct query_header *) buf; q = (struct query_header *) rb.buf; rb.ptr = rb.buf+sizeof(struct query_header); bufptr = buf+sizeof(struct query_header); q->ip_sz = sizeof(acc_elem->primitives.src_ip); q->cnt_sz = sizeof(acc_elem->bytes_counter); q->datasize = datasize; if (extras->off_pkt_bgp_primitives) { q->extras.off_pkt_bgp_primitives = offset; offset += sizeof(struct pkt_bgp_primitives); } else q->extras.off_pkt_bgp_primitives = 0; if (extras->off_pkt_lbgp_primitives) { q->extras.off_pkt_lbgp_primitives = offset; offset += sizeof(struct pkt_legacy_bgp_primitives); } else q->extras.off_pkt_lbgp_primitives = 0; if (extras->off_pkt_nat_primitives) { q->extras.off_pkt_nat_primitives = offset; offset += sizeof(struct pkt_nat_primitives); } else q->extras.off_pkt_nat_primitives = 0; if (extras->off_pkt_mpls_primitives) { q->extras.off_pkt_mpls_primitives = offset; offset += sizeof(struct pkt_mpls_primitives); } else q->extras.off_pkt_mpls_primitives = 0; if (extras->off_pkt_tun_primitives) { q->extras.off_pkt_tun_primitives = offset; offset += sizeof(struct pkt_tunnel_primitives); } else q->extras.off_pkt_tun_primitives = 0; if (extras->off_custom_primitives) { q->extras.off_custom_primitives = offset; offset += config.cpptrs.len; } else q->extras.off_custom_primitives = 0; if (extras->off_pkt_vlen_hdr_primitives) { q->extras.off_pkt_vlen_hdr_primitives = offset; offset += sizeof(struct pkt_vlen_hdr_primitives); /* XXX: handle variable legnth part of this structure */ } else q->extras.off_pkt_vlen_hdr_primitives = 0; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Processing data received from client ...\n", config.name, config.type); if (config.imt_plugin_passwd) { if (!strncmp(config.imt_plugin_passwd, q->passwd, MIN(strlen(config.imt_plugin_passwd), 8))); else return; } elem = (unsigned char *) a; reset_counter = q->type & WANT_RESET; if (q->type & WANT_STATS) { q->what_to_count = config.what_to_count; q->what_to_count_2 = config.what_to_count_2; for (idx = 0; idx < config.buckets; idx++) { if (!following_chain) acc_elem = (struct acc *) elem; if (!test_zero_elem(acc_elem)) { enQueue_elem(sd, &rb, acc_elem, PdataSz, datasize); if (extras->off_pkt_bgp_primitives && acc_elem->pbgp) { enQueue_elem(sd, &rb, acc_elem->pbgp, PbgpSz, datasize - extras->off_pkt_bgp_primitives); } if (extras->off_pkt_lbgp_primitives) { if (acc_elem->clbgp) { struct pkt_legacy_bgp_primitives tmp_plbgp; cache_to_pkt_legacy_bgp_primitives(&tmp_plbgp, acc_elem->clbgp); enQueue_elem(sd, &rb, &tmp_plbgp, PlbgpSz, datasize - extras->off_pkt_lbgp_primitives); } } if (extras->off_pkt_nat_primitives && acc_elem->pnat) { enQueue_elem(sd, &rb, acc_elem->pnat, PnatSz, datasize - extras->off_pkt_nat_primitives); } if (extras->off_pkt_mpls_primitives && acc_elem->pmpls) { enQueue_elem(sd, &rb, acc_elem->pmpls, PmplsSz, datasize - extras->off_pkt_mpls_primitives); } if (extras->off_pkt_tun_primitives && acc_elem->ptun) { enQueue_elem(sd, &rb, acc_elem->ptun, PtunSz, datasize - extras->off_pkt_tun_primitives); } if (extras->off_custom_primitives && acc_elem->pcust) { enQueue_elem(sd, &rb, acc_elem->pcust, config.cpptrs.len, datasize - extras->off_custom_primitives); } if (extras->off_pkt_vlen_hdr_primitives && acc_elem->pvlen) { enQueue_elem(sd, &rb, acc_elem->pvlen, PvhdrSz + acc_elem->pvlen->tot_len, datasize - extras->off_pkt_vlen_hdr_primitives); } } if (acc_elem->next != NULL) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Following chain in reply ...\n", config.name, config.type); acc_elem = acc_elem->next; following_chain = TRUE; idx--; } else { elem += sizeof(struct acc); following_chain = FALSE; } } if (rb.packed) send(sd, rb.buf, rb.packed, 0); /* send remainder data */ } else if (q->type & WANT_STATUS) { for (idx = 0; idx < config.buckets; idx++) { /* Administrativia */ following_chain = FALSE; bd.num = 0; bd.howmany = 0; acc_elem = (struct acc *) elem; do { if (following_chain) acc_elem = acc_elem->next; if (!test_zero_elem(acc_elem)) bd.howmany++; bd.num = idx; /* we need to avoid this redundancy */ following_chain = TRUE; } while (acc_elem->next != NULL); enQueue_elem(sd, &rb, &bd, sizeof(struct bucket_desc), sizeof(struct bucket_desc)); elem += sizeof(struct acc); } if (rb.packed) send(sd, rb.buf, rb.packed, 0); } else if (q->type & WANT_MATCH || q->type & WANT_COUNTER) { unsigned int j; q->what_to_count = config.what_to_count; q->what_to_count_2 = config.what_to_count_2; for (j = 0; j < uq->num; j++, bufptr += sizeof(struct query_entry)) { memcpy(&request, bufptr, sizeof(struct query_entry)); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Searching into accounting structure ...\n", config.name, config.type); if (request.what_to_count == config.what_to_count && request.what_to_count_2 == config.what_to_count_2) { struct pkt_data pd_dummy; struct primitives_ptrs prim_ptrs; memset(&pd_dummy, 0, sizeof(pd_dummy)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memcpy(&pd_dummy.primitives, &request.data, sizeof(struct pkt_primitives)); prim_ptrs.data = &pd_dummy; prim_ptrs.pbgp = &request.pbgp; prim_ptrs.plbgp = &request.plbgp; prim_ptrs.pnat = &request.pnat; prim_ptrs.pmpls = &request.pmpls; prim_ptrs.ptun = &request.ptun; prim_ptrs.pcust = request.pcust; prim_ptrs.pvlen = request.pvlen; acc_elem = search_accounting_structure(&prim_ptrs); if (acc_elem) { if (!test_zero_elem(acc_elem)) { enQueue_elem(sd, &rb, acc_elem, PdataSz, datasize); if (extras->off_pkt_bgp_primitives && acc_elem->pbgp) { enQueue_elem(sd, &rb, acc_elem->pbgp, PbgpSz, datasize - extras->off_pkt_bgp_primitives); } if (extras->off_pkt_lbgp_primitives) { if (acc_elem->clbgp) { struct pkt_legacy_bgp_primitives tmp_plbgp; cache_to_pkt_legacy_bgp_primitives(&tmp_plbgp, acc_elem->clbgp); enQueue_elem(sd, &rb, &tmp_plbgp, PlbgpSz, datasize - extras->off_pkt_lbgp_primitives); } } if (extras->off_pkt_nat_primitives && acc_elem->pnat) { enQueue_elem(sd, &rb, acc_elem->pnat, PnatSz, datasize - extras->off_pkt_nat_primitives); } if (extras->off_pkt_mpls_primitives && acc_elem->pmpls) { enQueue_elem(sd, &rb, acc_elem->pmpls, PmplsSz, datasize - extras->off_pkt_mpls_primitives); } if (extras->off_pkt_tun_primitives && acc_elem->ptun) { enQueue_elem(sd, &rb, acc_elem->ptun, PtunSz, datasize - extras->off_pkt_tun_primitives); } if (extras->off_custom_primitives && acc_elem->pcust) { enQueue_elem(sd, &rb, acc_elem->pcust, config.cpptrs.len, datasize - extras->off_custom_primitives); } if (extras->off_pkt_vlen_hdr_primitives && acc_elem->pvlen) { enQueue_elem(sd, &rb, acc_elem->pvlen, PvhdrSz + acc_elem->pvlen->tot_len, datasize - extras->off_pkt_vlen_hdr_primitives); } if (reset_counter) { if (forked) set_reset_flag(acc_elem); else reset_counters(acc_elem); } } else { if (q->type & WANT_COUNTER) { enQueue_elem(sd, &rb, &dummy, PdataSz, datasize); if (extras->off_pkt_bgp_primitives) enQueue_elem(sd, &rb, &dummy_pbgp, PbgpSz, datasize - extras->off_pkt_bgp_primitives); if (extras->off_pkt_lbgp_primitives) enQueue_elem(sd, &rb, &dummy_plbgp, PlbgpSz, datasize - extras->off_pkt_lbgp_primitives); if (extras->off_pkt_nat_primitives) enQueue_elem(sd, &rb, &dummy_pnat, PnatSz, datasize - extras->off_pkt_nat_primitives); if (extras->off_pkt_mpls_primitives) enQueue_elem(sd, &rb, &dummy_pmpls, PmplsSz, datasize - extras->off_pkt_mpls_primitives); if (extras->off_pkt_tun_primitives) enQueue_elem(sd, &rb, &dummy_ptun, PtunSz, datasize - extras->off_pkt_tun_primitives); if (extras->off_custom_primitives) enQueue_elem(sd, &rb, &dummy_pcust, config.cpptrs.len, datasize - extras->off_custom_primitives); if (extras->off_pkt_vlen_hdr_primitives) enQueue_elem(sd, &rb, &dummy_pvlen, PvhdrSz, datasize - extras->off_pkt_vlen_hdr_primitives); } } } else { if (q->type & WANT_COUNTER) { enQueue_elem(sd, &rb, &dummy, PdataSz, datasize); if (extras->off_pkt_bgp_primitives) enQueue_elem(sd, &rb, &dummy_pbgp, PbgpSz, datasize - extras->off_pkt_bgp_primitives); if (extras->off_pkt_lbgp_primitives) enQueue_elem(sd, &rb, &dummy_plbgp, PlbgpSz, datasize - extras->off_pkt_lbgp_primitives); if (extras->off_pkt_nat_primitives) enQueue_elem(sd, &rb, &dummy_pnat, PnatSz, datasize - extras->off_pkt_nat_primitives); if (extras->off_pkt_mpls_primitives) enQueue_elem(sd, &rb, &dummy_pmpls, PmplsSz, datasize - extras->off_pkt_mpls_primitives); if (extras->off_pkt_tun_primitives) enQueue_elem(sd, &rb, &dummy_ptun, PtunSz, datasize - extras->off_pkt_tun_primitives); if (extras->off_custom_primitives) enQueue_elem(sd, &rb, &dummy_pcust, config.cpptrs.len, datasize - extras->off_custom_primitives); if (extras->off_pkt_vlen_hdr_primitives) enQueue_elem(sd, &rb, &dummy_pvlen, PvhdrSz, datasize - extras->off_pkt_vlen_hdr_primitives); } } } else { struct pkt_primitives tbuf; struct pkt_bgp_primitives bbuf; struct pkt_legacy_bgp_primitives lbbuf; struct pkt_nat_primitives nbuf; struct pkt_mpls_primitives mbuf; struct pkt_tunnel_primitives ubuf; struct pkt_data abuf; following_chain = FALSE; elem = (unsigned char *) a; memset(&abuf, 0, sizeof(abuf)); for (idx = 0; idx < config.buckets; idx++) { if (!following_chain) acc_elem = (struct acc *) elem; if (!test_zero_elem(acc_elem)) { /* XXX: support for custom and vlen primitives */ mask_elem(&tbuf, &bbuf, &lbbuf, &nbuf, &mbuf, &ubuf, acc_elem, request.what_to_count, request.what_to_count_2, extras); if (!memcmp(&tbuf, &request.data, sizeof(struct pkt_primitives)) && !memcmp(&bbuf, &request.pbgp, sizeof(struct pkt_bgp_primitives)) && !memcmp(&lbbuf, &request.plbgp, sizeof(struct pkt_legacy_bgp_primitives)) && !memcmp(&nbuf, &request.pnat, sizeof(struct pkt_nat_primitives)) && !memcmp(&mbuf, &request.pmpls, sizeof(struct pkt_mpls_primitives)) && !memcmp(&ubuf, &request.ptun, sizeof(struct pkt_tunnel_primitives))) { if (q->type & WANT_COUNTER) Accumulate_Counters(&abuf, acc_elem); else { enQueue_elem(sd, &rb, acc_elem, PdataSz, datasize); /* q->type == WANT_MATCH */ if (extras->off_pkt_bgp_primitives && acc_elem->pbgp) { enQueue_elem(sd, &rb, acc_elem->pbgp, PbgpSz, datasize - extras->off_pkt_bgp_primitives); } if (extras->off_pkt_lbgp_primitives) { if (acc_elem->clbgp) { struct pkt_legacy_bgp_primitives tmp_plbgp; cache_to_pkt_legacy_bgp_primitives(&tmp_plbgp, acc_elem->clbgp); enQueue_elem(sd, &rb, &tmp_plbgp, PlbgpSz, datasize - extras->off_pkt_lbgp_primitives); } } if (extras->off_pkt_nat_primitives && acc_elem->pnat) { enQueue_elem(sd, &rb, acc_elem->pnat, PnatSz, datasize - extras->off_pkt_nat_primitives); } if (extras->off_pkt_mpls_primitives && acc_elem->pmpls) { enQueue_elem(sd, &rb, acc_elem->pmpls, PmplsSz, datasize - extras->off_pkt_mpls_primitives); } if (extras->off_pkt_tun_primitives && acc_elem->ptun) { enQueue_elem(sd, &rb, acc_elem->ptun, PtunSz, datasize - extras->off_pkt_tun_primitives); } if (extras->off_custom_primitives && acc_elem->pcust) { enQueue_elem(sd, &rb, acc_elem->pcust, config.cpptrs.len, datasize - extras->off_custom_primitives); } if (extras->off_pkt_vlen_hdr_primitives && acc_elem->pvlen) { enQueue_elem(sd, &rb, acc_elem->pvlen, PvhdrSz + acc_elem->pvlen->tot_len, datasize - extras->off_pkt_vlen_hdr_primitives); } } if (reset_counter) set_reset_flag(acc_elem); } } if (acc_elem->next) { acc_elem = acc_elem->next; following_chain = TRUE; idx--; } else { elem += sizeof(struct acc); following_chain = FALSE; } } if (q->type & WANT_COUNTER) enQueue_elem(sd, &rb, &abuf, PdataSz, PdataSz); /* enqueue accumulated data */ } } if (rb.packed) send(sd, rb.buf, rb.packed, 0); /* send remainder data */ } else if (q->type & WANT_CLASS_TABLE) { struct stripped_class dummy; u_int32_t idx = 0, max = 0; max = q->num = pmct_find_first_free(); if (!q->num && class) max = q->num = MAX_CLASSIFIERS; while (idx < max) { enQueue_elem(sd, &rb, &class[idx], sizeof(struct stripped_class), sizeof(struct stripped_class)); idx++; } memset(&dummy, 0, sizeof(dummy)); enQueue_elem(sd, &rb, &dummy, sizeof(dummy), sizeof(dummy)); if (rb.packed) send(sd, rb.buf, rb.packed, 0); /* send remainder data */ } else if (q->type & WANT_CUSTOM_PRIMITIVES_TABLE) { struct imt_custom_primitives custom_primitives_registry; u_int32_t idx; /* compsing new structure */ memset(&custom_primitives_registry, 0, sizeof(custom_primitives_registry)); for (idx = 0; idx < config.cpptrs.num; idx++) { strlcpy(custom_primitives_registry.primitive[idx].name, config.cpptrs.primitive[idx].name, MAX_CUSTOM_PRIMITIVE_NAMELEN); custom_primitives_registry.primitive[idx].off = config.cpptrs.primitive[idx].off; custom_primitives_registry.primitive[idx].field_type = config.cpptrs.primitive[idx].ptr->field_type; custom_primitives_registry.primitive[idx].len = config.cpptrs.primitive[idx].ptr->len; custom_primitives_registry.primitive[idx].semantics = config.cpptrs.primitive[idx].ptr->semantics; custom_primitives_registry.primitive[idx].type = config.cpptrs.primitive[idx].ptr->type; } custom_primitives_registry.num = config.cpptrs.num; custom_primitives_registry.len = config.cpptrs.len; if (idx) enQueue_elem(sd, &rb, &custom_primitives_registry, sizeof(custom_primitives_registry), sizeof(custom_primitives_registry)); else { memset(&dummy, 0, sizeof(dummy)); enQueue_elem(sd, &rb, &dummy, sizeof(dummy), sizeof(dummy)); } if (rb.packed) send(sd, rb.buf, rb.packed, 0); /* send remainder data */ } else if (q->type & WANT_ERASE_LAST_TSTAMP) { enQueue_elem(sd, &rb, &table_reset_stamp, sizeof(table_reset_stamp), sizeof(table_reset_stamp)); if (rb.packed) send(sd, rb.buf, rb.packed, 0); /* send remainder data */ } /* wait a bit due to setnonblocking() then send EOF */ usleep(1000); send(sd, emptybuf, LARGEBUFLEN, 0); if (dummy_pcust) free(dummy_pcust); if (custbuf) free(custbuf); } void mask_elem(struct pkt_primitives *d1, struct pkt_bgp_primitives *d2, struct pkt_legacy_bgp_primitives *d5, struct pkt_nat_primitives *d3, struct pkt_mpls_primitives *d4, struct pkt_tunnel_primitives *d6, struct acc *src, pm_cfgreg_t w, pm_cfgreg_t w2, struct extra_primitives *extras) { struct pkt_primitives *s1 = &src->primitives; struct pkt_bgp_primitives *s2 = src->pbgp; struct pkt_legacy_bgp_primitives tmp_plbgp; struct pkt_legacy_bgp_primitives *s5 = &tmp_plbgp; struct pkt_nat_primitives *s3 = src->pnat; struct pkt_mpls_primitives *s4 = src->pmpls; struct pkt_tunnel_primitives *s6 = src->ptun; cache_to_pkt_legacy_bgp_primitives(s5, src->clbgp); memset(d1, 0, sizeof(struct pkt_primitives)); memset(d2, 0, sizeof(struct pkt_bgp_primitives)); memset(d5, 0, sizeof(struct pkt_legacy_bgp_primitives)); memset(d3, 0, sizeof(struct pkt_nat_primitives)); memset(d4, 0, sizeof(struct pkt_mpls_primitives)); memset(d6, 0, sizeof(struct pkt_tunnel_primitives)); #if defined (HAVE_L2) if (w & COUNT_SRC_MAC) memcpy(d1->eth_shost, s1->eth_shost, ETH_ADDR_LEN); if (w & COUNT_DST_MAC) memcpy(d1->eth_dhost, s1->eth_dhost, ETH_ADDR_LEN); if (w & COUNT_VLAN) d1->vlan_id = s1->vlan_id; if (w2 & COUNT_OUT_VLAN) d1->out_vlan_id = s1->out_vlan_id; if (w & COUNT_COS) d1->cos = s1->cos; if (w & COUNT_ETHERTYPE) d1->etype = s1->etype; #endif if (w & COUNT_SRC_HOST) memcpy(&d1->src_ip, &s1->src_ip, sizeof(d1->src_ip)); if (w & COUNT_DST_HOST) memcpy(&d1->dst_ip, &s1->dst_ip, sizeof(d1->dst_ip)); if (w & COUNT_SRC_NET) memcpy(&d1->src_net, &s1->src_net, sizeof(d1->src_net)); if (w & COUNT_DST_NET) memcpy(&d1->dst_net, &s1->dst_net, sizeof(d1->dst_net)); if (w & COUNT_SRC_NMASK) d1->src_nmask = s1->src_nmask; if (w & COUNT_DST_NMASK) d1->dst_nmask = s1->dst_nmask; if (w & COUNT_SRC_AS) d1->src_as = s1->src_as; if (w & COUNT_DST_AS) d1->dst_as = s1->dst_as; if (w & COUNT_SRC_PORT) d1->src_port = s1->src_port; if (w & COUNT_DST_PORT) d1->dst_port = s1->dst_port; if (w & COUNT_IP_TOS) d1->tos = s1->tos; if (w & COUNT_IP_PROTO) d1->proto = s1->proto; if (w & COUNT_IN_IFACE) d1->ifindex_in = s1->ifindex_in; if (w & COUNT_OUT_IFACE) d1->ifindex_out = s1->ifindex_out; if (w & COUNT_TAG) d1->tag = s1->tag; if (w & COUNT_TAG2) d1->tag2 = s1->tag2; if (w & COUNT_CLASS) d1->class = s1->class; if (w2 & COUNT_EXPORT_PROTO_SEQNO) memcpy(&d1->export_proto_seqno, &s1->export_proto_seqno, sizeof(d1->export_proto_seqno)); if (w2 & COUNT_EXPORT_PROTO_VERSION) memcpy(&d1->export_proto_version, &s1->export_proto_version, sizeof(d1->export_proto_version)); if (w2 & COUNT_EXPORT_PROTO_SYSID) memcpy(&d1->export_proto_sysid, &s1->export_proto_sysid, sizeof(d1->export_proto_sysid)); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (w2 & COUNT_SRC_HOST_COUNTRY) memcpy(&d1->src_ip_country, &s1->src_ip_country, sizeof(d1->src_ip_country)); if (w2 & COUNT_DST_HOST_COUNTRY) memcpy(&d1->dst_ip_country, &s1->dst_ip_country, sizeof(d1->dst_ip_country)); if (w2 & COUNT_SRC_HOST_POCODE) memcpy(&d1->src_ip_pocode, &s1->src_ip_pocode, sizeof(d1->src_ip_pocode)); if (w2 & COUNT_DST_HOST_POCODE) memcpy(&d1->dst_ip_pocode, &s1->dst_ip_pocode, sizeof(d1->dst_ip_pocode)); if (w2 & COUNT_SRC_HOST_COORDS) { memcpy(&d1->src_ip_lat, &s1->src_ip_lat, sizeof(d1->src_ip_lat)); memcpy(&d1->src_ip_lon, &s1->src_ip_lon, sizeof(d1->src_ip_lon)); } if (w2 & COUNT_DST_HOST_COORDS) { memcpy(&d1->dst_ip_lat, &s1->dst_ip_lat, sizeof(d1->dst_ip_lat)); memcpy(&d1->dst_ip_lon, &s1->dst_ip_lon, sizeof(d1->dst_ip_lon)); } #endif #if defined (WITH_NDPI) if (w2 & COUNT_NDPI_CLASS) memcpy(&d1->ndpi_class, &s1->ndpi_class, sizeof(d1->ndpi_class)); #endif if (w2 & COUNT_SAMPLING_RATE) d1->sampling_rate = s1->sampling_rate; if (w2 & COUNT_SAMPLING_DIRECTION) memcpy(&d1->sampling_direction, &s1->sampling_direction, sizeof(d1->sampling_direction)); if (extras->off_pkt_bgp_primitives && s2) { if (w & COUNT_LOCAL_PREF) d2->local_pref = s2->local_pref; if (w & COUNT_SRC_LOCAL_PREF) d2->src_local_pref = s2->src_local_pref; if (w & COUNT_MED) d2->med = s2->med; if (w & COUNT_SRC_MED) d2->src_med = s2->src_med; if (w2 & COUNT_DST_ROA) d2->dst_roa = s2->dst_roa; if (w2 & COUNT_SRC_ROA) d2->src_roa = s2->src_roa; if (w & COUNT_PEER_SRC_AS) d2->peer_src_as = s2->peer_src_as; if (w & COUNT_PEER_DST_AS) d2->peer_dst_as = s2->peer_dst_as; if (w & COUNT_PEER_SRC_IP) memcpy(&d2->peer_src_ip, &s2->peer_src_ip, sizeof(d2->peer_src_ip)); if (w & COUNT_PEER_DST_IP) memcpy(&d2->peer_dst_ip, &s2->peer_dst_ip, sizeof(d2->peer_dst_ip)); if (w & COUNT_MPLS_VPN_RD) memcpy(&d2->mpls_vpn_rd, &s2->mpls_vpn_rd, sizeof(rd_t)); if (w2 & COUNT_MPLS_PW_ID) memcpy(&d2->mpls_pw_id, &s2->mpls_pw_id, sizeof(d2->mpls_pw_id)); } if (extras->off_pkt_lbgp_primitives && s5) { if (w & COUNT_STD_COMM) strlcpy(d5->std_comms, s5->std_comms, MAX_BGP_STD_COMMS); if (w & COUNT_EXT_COMM) strlcpy(d5->ext_comms, s5->ext_comms, MAX_BGP_EXT_COMMS); if (w2 & COUNT_LRG_COMM) strlcpy(d5->lrg_comms, s5->lrg_comms, MAX_BGP_LRG_COMMS); if (w & COUNT_AS_PATH) strlcpy(d5->as_path, s5->as_path, MAX_BGP_ASPATH); if (w & COUNT_SRC_STD_COMM) strlcpy(d5->src_std_comms, s5->src_std_comms, MAX_BGP_STD_COMMS); if (w & COUNT_SRC_EXT_COMM) strlcpy(d5->src_ext_comms, s5->src_ext_comms, MAX_BGP_EXT_COMMS); if (w2 & COUNT_SRC_LRG_COMM) strlcpy(d5->src_lrg_comms, s5->src_lrg_comms, MAX_BGP_LRG_COMMS); if (w & COUNT_SRC_AS_PATH) strlcpy(d5->src_as_path, s5->src_as_path, MAX_BGP_ASPATH); } if (extras->off_pkt_nat_primitives && s3) { if (w2 & COUNT_POST_NAT_SRC_HOST) memcpy(&d3->post_nat_src_ip, &s3->post_nat_src_ip, sizeof(d3->post_nat_src_ip)); if (w2 & COUNT_POST_NAT_DST_HOST) memcpy(&d3->post_nat_src_ip, &s3->post_nat_dst_ip, sizeof(d3->post_nat_dst_ip)); if (w2 & COUNT_POST_NAT_SRC_PORT) d3->post_nat_src_port = s3->post_nat_src_port; if (w2 & COUNT_POST_NAT_DST_PORT) d3->post_nat_dst_port = s3->post_nat_dst_port; if (w2 & COUNT_NAT_EVENT) d3->nat_event = s3->nat_event; if (w2 & COUNT_FW_EVENT) d3->fw_event = s3->fw_event; if (w2 & COUNT_FWD_STATUS) d3->fwd_status = s3->fwd_status; if (w2 & COUNT_TIMESTAMP_START) memcpy(&d3->timestamp_start, &s3->timestamp_start, sizeof(struct timeval)); if (w2 & COUNT_TIMESTAMP_END) memcpy(&d3->timestamp_end, &s3->timestamp_end, sizeof(struct timeval)); if (w2 & COUNT_TIMESTAMP_ARRIVAL) memcpy(&d3->timestamp_arrival, &s3->timestamp_arrival, sizeof(struct timeval)); if (w2 & COUNT_EXPORT_PROTO_TIME) memcpy(&d3->timestamp_export, &s3->timestamp_export, sizeof(struct timeval)); } if (extras->off_pkt_mpls_primitives && s4) { if (w2 & COUNT_MPLS_LABEL_TOP) d4->mpls_label_top = s4->mpls_label_top; if (w2 & COUNT_MPLS_LABEL_BOTTOM) d4->mpls_label_bottom = s4->mpls_label_bottom; } if (extras->off_pkt_tun_primitives && s6) { if (w2 & COUNT_TUNNEL_SRC_MAC) memcpy(&d6->tunnel_eth_shost, &s6->tunnel_eth_shost, sizeof(d6->tunnel_eth_shost)); if (w2 & COUNT_TUNNEL_DST_MAC) memcpy(&d6->tunnel_eth_dhost, &s6->tunnel_eth_dhost, sizeof(d6->tunnel_eth_dhost)); if (w2 & COUNT_TUNNEL_SRC_HOST) memcpy(&d6->tunnel_src_ip, &s6->tunnel_src_ip, sizeof(d6->tunnel_src_ip)); if (w2 & COUNT_TUNNEL_DST_HOST) memcpy(&d6->tunnel_src_ip, &s6->tunnel_dst_ip, sizeof(d6->tunnel_dst_ip)); if (w2 & COUNT_TUNNEL_IP_PROTO) memcpy(&d6->tunnel_proto, &s6->tunnel_proto, sizeof(d6->tunnel_proto)); if (w2 & COUNT_TUNNEL_IP_TOS) memcpy(&d6->tunnel_tos, &s6->tunnel_tos, sizeof(d6->tunnel_tos)); if (w2 & COUNT_TUNNEL_SRC_PORT) memcpy(&d6->tunnel_src_port, &s6->tunnel_src_port, sizeof(d6->tunnel_src_port)); if (w2 & COUNT_TUNNEL_DST_PORT) memcpy(&d6->tunnel_dst_port, &s6->tunnel_dst_port, sizeof(d6->tunnel_dst_port)); if (w2 & COUNT_VXLAN) memcpy(&d6->tunnel_id, &s6->tunnel_id, sizeof(d6->tunnel_id)); } } void enQueue_elem(int sd, struct reply_buffer *rb, void *elem, int size, int tot_size) { if ((rb->packed + tot_size) < rb->len) { memcpy(rb->ptr, elem, size); rb->ptr += size; rb->packed += size; } else { send(sd, rb->buf, rb->packed, 0); rb->len = LARGEBUFLEN; memset(rb->buf, 0, sizeof(rb->buf)); rb->packed = 0; rb->ptr = rb->buf; memcpy(rb->ptr, elem, size); rb->ptr += size; rb->packed += size; } } void Accumulate_Counters(struct pkt_data *abuf, struct acc *elem) { abuf->pkt_len += elem->bytes_counter; abuf->pkt_num += elem->packet_counter; abuf->flo_num += elem->flow_counter; abuf->time_start.tv_sec++; /* XXX: this unused field works as counter of how much entries we are accumulating */ } int test_zero_elem(struct acc *elem) { if (elem && elem->flow_type && !elem->reset_flag) return FALSE; return TRUE; } pmacct-1.7.8/src/sflow.h0000644000175000017500000005063314354105275014113 0ustar paolopaolo/* Copyright (c) 2002-2006 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ /* http://www.inmon.com/technology/sflowlicense.txt */ ///////////////////////////////////////////////////////////////////////////////// /////////////////////// sFlow Sampling Packet Data Types //////////////////////// ///////////////////////////////////////////////////////////////////////////////// #ifndef SFLOW_H #define SFLOW_H 1 #if defined(__cplusplus) extern "C" { #endif enum SFLAddress_type { SFLADDRESSTYPE_IP_V4 = 1, SFLADDRESSTYPE_IP_V6 = 2 }; typedef union _SFLAddress_value { struct in_addr ip_v4; struct in6_addr ip_v6; } SFLAddress_value; typedef struct _SFLAddress { u_int32_t type; /* enum SFLAddress_type */ SFLAddress_value address; } SFLAddress; /* Packet header data */ #define SFL_DEFAULT_HEADER_SIZE DEFAULT_SNAPLEN #define SFL_DEFAULT_COLLECTOR_PORT 6343 #define SFL_DEFAULT_COUNTER_INTERVAL_RATE 20 #define SFL_DEFAULT_FLOW_SAMPLING_RATE 1 /* The header protocol describes the format of the sampled header */ enum SFLHeader_protocol { SFLHEADER_ETHERNET_ISO8023 = 1, SFLHEADER_ISO88024_TOKENBUS = 2, SFLHEADER_ISO88025_TOKENRING = 3, SFLHEADER_FDDI = 4, SFLHEADER_FRAME_RELAY = 5, SFLHEADER_X25 = 6, SFLHEADER_PPP = 7, SFLHEADER_SMDS = 8, SFLHEADER_AAL5 = 9, SFLHEADER_AAL5_IP = 10, /* e.g. Cisco AAL5 mux */ SFLHEADER_IPv4 = 11, SFLHEADER_IPv6 = 12, SFLHEADER_MPLS = 13 }; /* raw sampled header */ typedef struct _SFLSampled_header { u_int32_t header_protocol; /* (enum SFLHeader_protocol) */ u_int32_t frame_length; /* Original length of packet before sampling */ u_int32_t stripped; /* header/trailer bytes stripped by sender */ u_int32_t header_length; /* length of sampled header bytes to follow */ u_int8_t *header_bytes; /* Header bytes */ } SFLSampled_header; /* decoded ethernet header */ typedef struct _SFLSampled_ethernet { u_int32_t eth_len; /* The length of the MAC packet excluding lower layer encapsulations */ u_int8_t src_mac[8]; /* 6 bytes + 2 pad */ u_int8_t dst_mac[8]; u_int32_t eth_type; } SFLSampled_ethernet; /* decoded IP version 4 header */ typedef struct _SFLSampled_ipv4 { u_int32_t length; /* The length of the IP packet excluding lower layer encapsulations */ u_int32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ struct in_addr src_ip; /* Source IP Address */ struct in_addr dst_ip; /* Destination IP Address */ u_int32_t src_port; /* TCP/UDP source port number or equivalent */ u_int32_t dst_port; /* TCP/UDP destination port number or equivalent */ u_int32_t tcp_flags; /* TCP flags */ u_int32_t tos; /* IP type of service */ } SFLSampled_ipv4; /* decoded IP version 6 data */ typedef struct _SFLSampled_ipv6 { u_int32_t length; /* The length of the IP packet excluding lower layer encapsulations */ u_int32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ struct in6_addr src_ip; /* Source IP Address */ struct in6_addr dst_ip; /* Destination IP Address */ u_int32_t src_port; /* TCP/UDP source port number or equivalent */ u_int32_t dst_port; /* TCP/UDP destination port number or equivalent */ u_int32_t tcp_flags; /* TCP flags */ u_int32_t priority; /* IP priority */ } SFLSampled_ipv6; /* Extended data types */ /* Extended switch data */ typedef struct _SFLExtended_switch { u_int32_t src_vlan; /* The 802.1Q VLAN id of incomming frame */ u_int32_t src_priority; /* The 802.1p priority */ u_int32_t dst_vlan; /* The 802.1Q VLAN id of outgoing frame */ u_int32_t dst_priority; /* The 802.1p priority */ } SFLExtended_switch; /* Extended router data */ typedef struct _SFLExtended_router { SFLAddress nexthop; /* IP address of next hop router */ u_int32_t src_mask; /* Source address prefix mask bits */ u_int32_t dst_mask; /* Destination address prefix mask bits */ } SFLExtended_router; /* Extended gateway data */ enum SFLExtended_as_path_segment_type { SFLEXTENDED_AS_SET = 1, /* Unordered set of ASs */ SFLEXTENDED_AS_SEQUENCE = 2 /* Ordered sequence of ASs */ }; typedef struct _SFLExtended_as_path_segment { u_int32_t type; /* enum SFLExtended_as_path_segment_type */ u_int32_t length; /* number of AS numbers in set/sequence */ union { u_int32_t *set; u_int32_t *seq; } as; } SFLExtended_as_path_segment; typedef struct _SFLExtended_gateway { SFLAddress nexthop; /* Address of the border router that should be used for the destination network */ u_int32_t as; /* AS number for this gateway */ u_int32_t src_as; /* AS number of source (origin) */ u_int32_t src_peer_as; /* AS number of source peer */ u_int32_t dst_as_path_segments; /* number of segments in path */ SFLExtended_as_path_segment *dst_as_path; /* list of seqs or sets */ u_int32_t communities_length; /* number of communities */ u_int32_t *communities; /* set of communities */ u_int32_t localpref; /* LocalPref associated with this route */ } SFLExtended_gateway; typedef struct _SFLString { u_int32_t len; char *str; } SFLString; /* Extended user data */ typedef struct _SFLExtended_user { u_int32_t src_charset; /* MIBEnum value of character set used to encode a string - See RFC 2978 Where possible UTF-8 encoding (MIBEnum=106) should be used. A value of zero indicates an unknown encoding. */ SFLString src_user; u_int32_t dst_charset; SFLString dst_user; } SFLExtended_user; /* Extended URL data */ enum SFLExtended_url_direction { SFLEXTENDED_URL_SRC = 1, /* URL is associated with source address */ SFLEXTENDED_URL_DST = 2 /* URL is associated with destination address */ }; typedef struct _SFLExtended_url { u_int32_t direction; /* enum SFLExtended_url_direction */ SFLString url; /* URL associated with the packet flow. Must be URL encoded */ SFLString host; /* The host field from the HTTP header */ } SFLExtended_url; /* Extended MPLS data */ typedef struct _SFLLabelStack { u_int32_t depth; u_int32_t *stack; /* first entry is top of stack - see RFC 3032 for encoding */ } SFLLabelStack; typedef struct _SFLExtended_mpls { SFLAddress nextHop; /* Address of the next hop */ SFLLabelStack in_stack; SFLLabelStack out_stack; } SFLExtended_mpls; /* Extended NAT data Packet header records report addresses as seen at the sFlowDataSource. The extended_nat structure reports on translated source and/or destination addesses for this packet. If an address was not translated it should be equal to that reported for the header. */ typedef struct _SFLExtended_nat { SFLAddress src; /* Source address */ SFLAddress dst; /* Destination address */ } SFLExtended_nat; /* additional Extended MPLS stucts */ typedef struct _SFLExtended_mpls_tunnel { SFLString tunnel_lsp_name; /* Tunnel name */ u_int32_t tunnel_id; /* Tunnel ID */ u_int32_t tunnel_cos; /* Tunnel COS value */ } SFLExtended_mpls_tunnel; typedef struct _SFLExtended_mpls_vc { SFLString vc_instance_name; /* VC instance name */ u_int32_t vll_vc_id; /* VLL/VC instance ID */ u_int32_t vc_label_cos; /* VC Label COS value */ } SFLExtended_mpls_vc; /* Extended MPLS FEC - Definitions from MPLS-FTN-STD-MIB mplsFTNTable */ typedef struct _SFLExtended_mpls_FTN { SFLString mplsFTNDescr; u_int32_t mplsFTNMask; } SFLExtended_mpls_FTN; /* Extended MPLS LVP FEC - Definition from MPLS-LDP-STD-MIB mplsFecTable Note: mplsFecAddrType, mplsFecAddr information available from packet header */ typedef struct _SFLExtended_mpls_LDP_FEC { u_int32_t mplsFecAddrPrefixLength; } SFLExtended_mpls_LDP_FEC; /* Extended VLAN tunnel information Record outer VLAN encapsulations that have been stripped. extended_vlantunnel information should only be reported if all the following conditions are satisfied: 1. The packet has nested vlan tags, AND 2. The reporting device is VLAN aware, AND 3. One or more VLAN tags have been stripped, either because they represent proprietary encapsulations, or because switch hardware automatically strips the outer VLAN encapsulation. Reporting extended_vlantunnel information is not a substitute for reporting extended_switch information. extended_switch data must always be reported to describe the ingress/egress VLAN information for the packet. The extended_vlantunnel information only applies to nested VLAN tags, and then only when one or more tags has been stripped. */ typedef SFLLabelStack SFLVlanStack; typedef struct _SFLExtended_vlan_tunnel { SFLVlanStack stack; /* List of stripped 802.1Q TPID/TCI layers. Each TPID,TCI pair is represented as a single 32 bit integer. Layers listed from outermost to innermost. */ } SFLExtended_vlan_tunnel; typedef struct _SFLExtended_classification { pm_class_t class; } SFLExtended_classification; typedef struct _SFLExtended_classification2 { #if defined (WITH_NDPI) pm_class2_t id; #else u_int64_t id; #endif } SFLExtended_classification2; typedef struct _SFLExtended_tag { pm_id_t tag; pm_id_t tag2; } SFLExtended_tag; enum SFLFlow_type_tag { /* enterprise = 0, format = ... */ SFLFLOW_HEADER = 1, /* Packet headers are sampled */ SFLFLOW_ETHERNET = 2, /* MAC layer information */ SFLFLOW_IPV4 = 3, /* IP version 4 data */ SFLFLOW_IPV6 = 4, /* IP version 6 data */ SFLFLOW_EX_SWITCH = 1001, /* Extended switch information */ SFLFLOW_EX_ROUTER = 1002, /* Extended router information */ SFLFLOW_EX_GATEWAY = 1003, /* Extended gateway router information */ SFLFLOW_EX_USER = 1004, /* Extended TACAS/RADIUS user information */ SFLFLOW_EX_URL = 1005, /* Extended URL information */ SFLFLOW_EX_MPLS = 1006, /* Extended MPLS information */ SFLFLOW_EX_NAT = 1007, /* Extended NAT information */ SFLFLOW_EX_MPLS_TUNNEL = 1008, /* additional MPLS information */ SFLFLOW_EX_MPLS_VC = 1009, SFLFLOW_EX_MPLS_FTN = 1010, SFLFLOW_EX_MPLS_LDP_FEC = 1011, SFLFLOW_EX_VLAN_TUNNEL = 1012, /* VLAN stack */ /* enterprise = 43874 pmacct */ SFLFLOW_EX_CLASS = (43874 << 12) + 1, SFLFLOW_EX_TAG = (43874 << 12) + 2, SFLFLOW_EX_CLASS2 = (43874 << 12) + 3, }; typedef union _SFLFlow_type { SFLSampled_header header; SFLSampled_ethernet ethernet; SFLSampled_ipv4 ipv4; SFLSampled_ipv6 ipv6; SFLExtended_switch sw; SFLExtended_router router; SFLExtended_gateway gateway; SFLExtended_user user; SFLExtended_url url; SFLExtended_mpls mpls; SFLExtended_nat nat; SFLExtended_mpls_tunnel mpls_tunnel; SFLExtended_mpls_vc mpls_vc; SFLExtended_mpls_FTN mpls_ftn; SFLExtended_mpls_LDP_FEC mpls_ldp_fec; SFLExtended_vlan_tunnel vlan_tunnel; SFLExtended_classification class; SFLExtended_classification2 ndpi_class; SFLExtended_tag tag; } SFLFlow_type; typedef struct _SFLFlow_sample_element { struct _SFLFlow_sample_element *nxt; u_int32_t tag; /* SFLFlow_type_tag */ u_int32_t length; SFLFlow_type flowType; } SFLFlow_sample_element; enum SFL_sample_tag { SFLFLOW_SAMPLE = 1, /* enterprise = 0 : format = 1 */ SFLCOUNTERS_SAMPLE = 2, /* enterprise = 0 : format = 2 */ SFLFLOW_SAMPLE_EXPANDED = 3, /* enterprise = 0 : format = 3 */ SFLCOUNTERS_SAMPLE_EXPANDED = 4, /* enterprise = 0 : format = 4 */ SFLACL_BROCADE_SAMPLE = 8155137 /* enterprise = 1991 : format = 1 */ }; /* Format of a single flow sample */ typedef struct _SFLFlow_sample { /* u_int32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ /* u_int32_t length; */ u_int32_t sequence_number; /* Incremented with each flow sample generated */ u_int32_t source_id; /* fsSourceId */ u_int32_t sampling_rate; /* fsPacketSamplingRate */ u_int32_t sample_pool; /* Total number of packets that could have been sampled (i.e. packets skipped by sampling process + total number of samples) */ u_int32_t drops; /* Number of times a packet was dropped due to lack of resources */ u_int32_t input; /* SNMP ifIndex of input interface. 0 if interface is not known. */ u_int32_t output; /* SNMP ifIndex of output interface, 0 if interface is not known. Set most significant bit to indicate multiple destination interfaces (i.e. in case of broadcast or multicast) and set lower order bits to indicate number of destination interfaces. Examples: 0x00000002 indicates ifIndex = 2 0x00000000 ifIndex unknown. 0x80000007 indicates a packet sent to 7 interfaces. 0x80000000 indicates a packet sent to an unknown number of interfaces greater than 1.*/ u_int32_t num_elements; SFLFlow_sample_element *elements; } SFLFlow_sample; /* same thing, but the expanded version (for full 32-bit ifIndex numbers) */ typedef struct _SFLFlow_sample_expanded { /* u_int32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ /* u_int32_t length; */ u_int32_t sequence_number; /* Incremented with each flow sample generated */ u_int32_t ds_class; /* EXPANDED */ u_int32_t ds_index; /* EXPANDED */ u_int32_t sampling_rate; /* fsPacketSamplingRate */ u_int32_t sample_pool; /* Total number of packets that could have been sampled (i.e. packets skipped by sampling process + total number of samples) */ u_int32_t drops; /* Number of times a packet was dropped due to lack of resources */ u_int32_t inputFormat; /* EXPANDED */ u_int32_t input; /* SNMP ifIndex of input interface. 0 if interface is not known. */ u_int32_t outputFormat; /* EXPANDED */ u_int32_t output; /* SNMP ifIndex of output interface, 0 if interface is not known. */ u_int32_t num_elements; SFLFlow_sample_element *elements; } SFLFlow_sample_expanded; /* Counter types */ /* Generic interface counters - see RFC 1573, 2233 */ typedef struct _SFLIf_counters { u_int32_t ifIndex; u_int32_t ifType; u_int64_t ifSpeed; u_int32_t ifDirection; /* Derived from MAU MIB (RFC 2668) 0 = unknown, 1 = full-duplex, 2 = half-duplex, 3 = in, 4 = out */ u_int32_t ifStatus; /* bit field with the following bits assigned: bit 0 = ifAdminStatus (0 = down, 1 = up) bit 1 = ifOperStatus (0 = down, 1 = up) */ u_int64_t ifInOctets; u_int32_t ifInUcastPkts; u_int32_t ifInMulticastPkts; u_int32_t ifInBroadcastPkts; u_int32_t ifInDiscards; u_int32_t ifInErrors; u_int32_t ifInUnknownProtos; u_int64_t ifOutOctets; u_int32_t ifOutUcastPkts; u_int32_t ifOutMulticastPkts; u_int32_t ifOutBroadcastPkts; u_int32_t ifOutDiscards; u_int32_t ifOutErrors; u_int32_t ifPromiscuousMode; } SFLIf_counters; /* Ethernet interface counters - see RFC 2358 */ typedef struct _SFLEthernet_counters { u_int32_t dot3StatsAlignmentErrors; u_int32_t dot3StatsFCSErrors; u_int32_t dot3StatsSingleCollisionFrames; u_int32_t dot3StatsMultipleCollisionFrames; u_int32_t dot3StatsSQETestErrors; u_int32_t dot3StatsDeferredTransmissions; u_int32_t dot3StatsLateCollisions; u_int32_t dot3StatsExcessiveCollisions; u_int32_t dot3StatsInternalMacTransmitErrors; u_int32_t dot3StatsCarrierSenseErrors; u_int32_t dot3StatsFrameTooLongs; u_int32_t dot3StatsInternalMacReceiveErrors; u_int32_t dot3StatsSymbolErrors; } SFLEthernet_counters; /* Token ring counters - see RFC 1748 */ typedef struct _SFLTokenring_counters { u_int32_t dot5StatsLineErrors; u_int32_t dot5StatsBurstErrors; u_int32_t dot5StatsACErrors; u_int32_t dot5StatsAbortTransErrors; u_int32_t dot5StatsInternalErrors; u_int32_t dot5StatsLostFrameErrors; u_int32_t dot5StatsReceiveCongestions; u_int32_t dot5StatsFrameCopiedErrors; u_int32_t dot5StatsTokenErrors; u_int32_t dot5StatsSoftErrors; u_int32_t dot5StatsHardErrors; u_int32_t dot5StatsSignalLoss; u_int32_t dot5StatsTransmitBeacons; u_int32_t dot5StatsRecoverys; u_int32_t dot5StatsLobeWires; u_int32_t dot5StatsRemoves; u_int32_t dot5StatsSingles; u_int32_t dot5StatsFreqErrors; } SFLTokenring_counters; /* 100 BaseVG interface counters - see RFC 2020 */ typedef struct _SFLVg_counters { u_int32_t dot12InHighPriorityFrames; u_int64_t dot12InHighPriorityOctets; u_int32_t dot12InNormPriorityFrames; u_int64_t dot12InNormPriorityOctets; u_int32_t dot12InIPMErrors; u_int32_t dot12InOversizeFrameErrors; u_int32_t dot12InDataErrors; u_int32_t dot12InNullAddressedFrames; u_int32_t dot12OutHighPriorityFrames; u_int64_t dot12OutHighPriorityOctets; u_int32_t dot12TransitionIntoTrainings; u_int64_t dot12HCInHighPriorityOctets; u_int64_t dot12HCInNormPriorityOctets; u_int64_t dot12HCOutHighPriorityOctets; } SFLVg_counters; typedef struct _SFLVlan_counters { u_int32_t vlan_id; u_int64_t octets; u_int32_t ucastPkts; u_int32_t multicastPkts; u_int32_t broadcastPkts; u_int32_t discards; } SFLVlan_counters; /* Counters data */ enum SFLCounters_type_tag { /* enterprise = 0, format = ... */ SFLCOUNTERS_GENERIC = 1, SFLCOUNTERS_ETHERNET = 2, SFLCOUNTERS_TOKENRING = 3, SFLCOUNTERS_VG = 4, SFLCOUNTERS_VLAN = 5 }; typedef union _SFLCounters_type { SFLIf_counters generic; SFLEthernet_counters ethernet; SFLTokenring_counters tokenring; SFLVg_counters vg; SFLVlan_counters vlan; } SFLCounters_type; typedef struct _SFLCounters_sample_element { struct _SFLCounters_sample_element *nxt; /* linked list */ u_int32_t tag; /* SFLCounters_type_tag */ u_int32_t length; SFLCounters_type counterBlock; } SFLCounters_sample_element; typedef struct _SFLCounters_sample { /* u_int32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ /* u_int32_t length; */ u_int32_t sequence_number; /* Incremented with each counters sample generated by this source_id */ u_int32_t source_id; /* fsSourceId */ u_int32_t num_elements; SFLCounters_sample_element *elements; } SFLCounters_sample; /* same thing, but the expanded version, so ds_index can be a full 32 bits */ typedef struct _SFLCounters_sample_expanded { /* u_int32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ /* u_int32_t length; */ u_int32_t sequence_number; /* Incremented with each counters sample generated by this source_id */ u_int32_t ds_class; /* EXPANDED */ u_int32_t ds_index; /* EXPANDED */ u_int32_t num_elements; SFLCounters_sample_element *elements; } SFLCounters_sample_expanded; #define SFLADD_ELEMENT(_sm, _el) do { (_el)->nxt = (_sm)->elements; (_sm)->elements = (_el); } while(0) /* Format of a sample datagram */ enum SFLDatagram_version { SFLDATAGRAM_VERSION2 = 2, SFLDATAGRAM_VERSION4 = 4, SFLDATAGRAM_VERSION5 = 5 }; typedef struct _SFLSample_datagram_hdr { u_int32_t datagram_version; /* (enum SFLDatagram_version) = VERSION5 = 5 */ SFLAddress agent_address; /* IP address of sampling agent */ u_int32_t sub_agent_id; /* Used to distinguishing between datagram streams from separate agent sub entities within an device. */ u_int32_t sequence_number; /* Incremented with each sample datagram generated */ u_int32_t uptime; /* Current time (in milliseconds since device last booted). Should be set as close to datagram transmission time as possible.*/ u_int32_t num_records; /* Number of tag-len-val flow/counter records to follow */ } SFLSample_datagram_hdr; #define SFL_MAX_DATAGRAM_SIZE 1500 #define SFL_MIN_DATAGRAM_SIZE 200 #define SFL_DEFAULT_DATAGRAM_SIZE 1400 #define SFL_DATA_PAD 400 #if defined(__cplusplus) } /* extern "C" */ #endif #endif /* SFLOW_H */ pmacct-1.7.8/src/filters/0000755000175000017500000000000014354105416014246 5ustar paolopaolopmacct-1.7.8/src/filters/murmur2.c0000644000175000017500000000251714354105275016033 0ustar paolopaolo//----------------------------------------------------------------------------- // MurmurHash2, by Austin Appleby // Note - This code makes a few assumptions about how your machine behaves - // 1. We can read a 4-byte value from any address without crashing // 2. sizeof(int) == 4 // And it has a few limitations - // 1. It will not work incrementally. // 2. It will not produce the same results on little-endian and big-endian // machines. /* defines */ unsigned int murmurhash2(const void * key, int len, const unsigned int seed) { // 'm' and 'r' are mixing constants generated offline. // They're not really 'magic', they just happen to work well. const unsigned int m = 0x5bd1e995; const int r = 24; // Initialize the hash to a 'random' value unsigned int h = seed ^ len; // Mix 4 bytes at a time into the hash const unsigned char * data = (const unsigned char *)key; while(len >= 4) { unsigned int k = *(unsigned int *)data; k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; data += 4; len -= 4; } // Handle the last few bytes of the input array switch(len) { case 3: h ^= data[2] << 16; case 2: h ^= data[1] << 8; case 1: h ^= data[0]; h *= m; }; // Do a few final mixes of the hash to ensure the last few // bytes are well-incorporated. h ^= h >> 13; h *= m; h ^= h >> 15; return h; } pmacct-1.7.8/src/filters/bloom.h0000644000175000017500000001115014354105275015530 0ustar paolopaolo/* * Copyright (c) 2012-2017, Jyri J. Virkki * All rights reserved. * * This file is under BSD license. See LICENSE file. */ #ifndef BLOOM_H #define BLOOM_H /** *************************************************************************** * Structure to keep track of one bloom filter. Caller needs to * allocate this and pass it to the functions below. First call for * every struct must be to bloom_init(). * */ struct bloom { // These fields are part of the public interface of this structure. // Client code may read these values if desired. Client code MUST NOT // modify any of these. int entries; double error; int bits; int bytes; int hashes; // Fields below are private to the implementation. These may go away or // change incompatibly at any moment. Client code MUST NOT access or rely // on these. double bpe; unsigned char * bf; int ready; }; /* prototypes */ /** *************************************************************************** * Initialize the bloom filter for use. * * The filter is initialized with a bit field and number of hash functions * according to the computations from the wikipedia entry: * http://en.wikipedia.org/wiki/Bloom_filter * * Optimal number of bits is: * bits = (entries * ln(error)) / ln(2)^2 * * Optimal number of hash functions is: * hashes = bpe * ln(2) * * Parameters: * ----------- * bloom - Pointer to an allocated struct bloom (see above). * entries - The expected number of entries which will be inserted. * Must be at least 1000 (in practice, likely much larger). * error - Probability of collision (as long as entries are not * exceeded). * * Return: * ------- * 0 - on success * 1 - on failure * */ extern int bloom_init(struct bloom * bloom, int entries, double error); /** *************************************************************************** * Deprecated, use bloom_init() * */ extern int bloom_init_size(struct bloom * bloom, int entries, double error, unsigned int cache_size); /** *************************************************************************** * Check if the given element is in the bloom filter. Remember this may * return false positive if a collision occurred. * * Parameters: * ----------- * bloom - Pointer to an allocated struct bloom (see above). * buffer - Pointer to buffer containing element to check. * len - Size of 'buffer'. * * Return: * ------- * 0 - element is not present * 1 - element is present (or false positive due to collision) * -1 - bloom not initialized * */ extern int bloom_check(struct bloom * bloom, const void * buffer, int len); /** *************************************************************************** * Add the given element to the bloom filter. * The return code indicates if the element (or a collision) was already in, * so for the common check+add use case, no need to call check separately. * * Parameters: * ----------- * bloom - Pointer to an allocated struct bloom (see above). * buffer - Pointer to buffer containing element to add. * len - Size of 'buffer'. * * Return: * ------- * 0 - element was not present and was added * 1 - element (or a collision) had already been added previously * -1 - bloom not initialized * */ extern int bloom_add(struct bloom * bloom, const void * buffer, int len); /** *************************************************************************** * Print (to stdout) info about this bloom filter. Debugging aid. * */ extern void bloom_print(struct bloom * bloom); /** *************************************************************************** * Deallocate internal storage. * * Upon return, the bloom struct is no longer usable. You may call bloom_init * again on the same struct to reinitialize it again. * * Parameters: * ----------- * bloom - Pointer to an allocated struct bloom (see above). * * Return: none * */ extern void bloom_free(struct bloom * bloom); /** *************************************************************************** * Erase internal storage. * * Erases all elements. Upon return, the bloom struct returns to its initial * (initialized) state. * * Parameters: * ----------- * bloom - Pointer to an allocated struct bloom (see above). * * Return: * 0 - on success * 1 - on failure * */ extern int bloom_reset(struct bloom * bloom); /** *************************************************************************** * Returns version string compiled into library. * * Return: version string * */ #endif //BLOOM_H pmacct-1.7.8/src/filters/bloom.c0000644000175000017500000000633414354105275015533 0ustar paolopaolo/* * Copyright (c) 2012-2019, Jyri J. Virkki * All rights reserved. * * This file is under BSD license. See LICENSE file. */ /* * Refer to bloom.h for documentation on the public interfaces. */ #include "pmacct.h" #include "murmur2.h" inline static int test_bit_set_bit(unsigned char * buf, unsigned int x, int set_bit) { unsigned int byte = x >> 3; unsigned char c = buf[byte]; // expensive memory access unsigned int mask = 1 << (x % 8); if (c & mask) { return 1; } else { if (set_bit) { buf[byte] = c | mask; } return 0; } } static int bloom_check_add(struct bloom * bloom, const void * buffer, int len, int add) { if (bloom->ready == 0) { printf("bloom at %p not initialized!\n", (void *)bloom); return -1; } int hits = 0; register unsigned int a = murmurhash2(buffer, len, 0x9747b28c); register unsigned int b = murmurhash2(buffer, len, a); register unsigned int x; register unsigned int i; for (i = 0; i < bloom->hashes; i++) { x = (a + i*b) % bloom->bits; if (test_bit_set_bit(bloom->bf, x, add)) { hits++; } else if (!add) { // Don't care about the presence of all the bits. Just our own. return 0; } } if (hits == bloom->hashes) { return 1; // 1 == element already in (or collision) } return 0; } int bloom_init_size(struct bloom * bloom, int entries, double error, unsigned int cache_size) { return bloom_init(bloom, entries, error); } int bloom_init(struct bloom * bloom, int entries, double error) { bloom->ready = 0; if (entries < 1000 || error == 0) { return 1; } bloom->entries = entries; bloom->error = error; double num = log(bloom->error); double denom = 0.480453013918201; // ln(2)^2 bloom->bpe = -(num / denom); double dentries = (double)entries; bloom->bits = (int)(dentries * bloom->bpe); if (bloom->bits % 8) { bloom->bytes = (bloom->bits / 8) + 1; } else { bloom->bytes = bloom->bits / 8; } bloom->hashes = (int)ceil(0.693147180559945 * bloom->bpe); // ln(2) bloom->bf = (unsigned char *)calloc(bloom->bytes, sizeof(unsigned char)); if (bloom->bf == NULL) { // LCOV_EXCL_START return 1; } // LCOV_EXCL_STOP bloom->ready = 1; return 0; } int bloom_check(struct bloom * bloom, const void * buffer, int len) { return bloom_check_add(bloom, buffer, len, 0); } int bloom_add(struct bloom * bloom, const void * buffer, int len) { return bloom_check_add(bloom, buffer, len, 1); } void bloom_print(struct bloom * bloom) { printf("bloom at %p\n", (void *)bloom); printf(" ->entries = %d\n", bloom->entries); printf(" ->error = %f\n", bloom->error); printf(" ->bits = %d\n", bloom->bits); printf(" ->bits per elem = %f\n", bloom->bpe); printf(" ->bytes = %d\n", bloom->bytes); printf(" ->hash functions = %d\n", bloom->hashes); } void bloom_free(struct bloom * bloom) { if (bloom->ready) { free(bloom->bf); } bloom->ready = 0; } int bloom_reset(struct bloom * bloom) { if (!bloom->ready) return 1; memset(bloom->bf, 0, bloom->bytes); return 0; } pmacct-1.7.8/src/filters/Makefile.in0000644000175000017500000005316614354105416016326 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/filters ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmfilters_la_LIBADD = am_libpmfilters_la_OBJECTS = libpmfilters_la-bloom.lo \ libpmfilters_la-murmur2.lo libpmfilters_la_OBJECTS = $(am_libpmfilters_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmfilters_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libpmfilters_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmfilters_la-bloom.Plo \ ./$(DEPDIR)/libpmfilters_la-murmur2.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmfilters_la_SOURCES) DIST_SOURCES = $(libpmfilters_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmfilters.la libpmfilters_la_SOURCES = bloom.c bloom.h murmur2.c murmur2.h libpmfilters_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/filters/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/filters/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmfilters.la: $(libpmfilters_la_OBJECTS) $(libpmfilters_la_DEPENDENCIES) $(EXTRA_libpmfilters_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmfilters_la_LINK) $(libpmfilters_la_OBJECTS) $(libpmfilters_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmfilters_la-bloom.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmfilters_la-murmur2.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmfilters_la-bloom.lo: bloom.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmfilters_la_CFLAGS) $(CFLAGS) -MT libpmfilters_la-bloom.lo -MD -MP -MF $(DEPDIR)/libpmfilters_la-bloom.Tpo -c -o libpmfilters_la-bloom.lo `test -f 'bloom.c' || echo '$(srcdir)/'`bloom.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmfilters_la-bloom.Tpo $(DEPDIR)/libpmfilters_la-bloom.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bloom.c' object='libpmfilters_la-bloom.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmfilters_la_CFLAGS) $(CFLAGS) -c -o libpmfilters_la-bloom.lo `test -f 'bloom.c' || echo '$(srcdir)/'`bloom.c libpmfilters_la-murmur2.lo: murmur2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmfilters_la_CFLAGS) $(CFLAGS) -MT libpmfilters_la-murmur2.lo -MD -MP -MF $(DEPDIR)/libpmfilters_la-murmur2.Tpo -c -o libpmfilters_la-murmur2.lo `test -f 'murmur2.c' || echo '$(srcdir)/'`murmur2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmfilters_la-murmur2.Tpo $(DEPDIR)/libpmfilters_la-murmur2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='murmur2.c' object='libpmfilters_la-murmur2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmfilters_la_CFLAGS) $(CFLAGS) -c -o libpmfilters_la-murmur2.lo `test -f 'murmur2.c' || echo '$(srcdir)/'`murmur2.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmfilters_la-bloom.Plo -rm -f ./$(DEPDIR)/libpmfilters_la-murmur2.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmfilters_la-bloom.Plo -rm -f ./$(DEPDIR)/libpmfilters_la-murmur2.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/filters/Makefile.am0000644000175000017500000000027014354105275016304 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmfilters.la libpmfilters_la_SOURCES = bloom.c bloom.h murmur2.c murmur2.h libpmfilters_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/filters/murmur2.h0000644000175000017500000000022214354105275016027 0ustar paolopaolo#ifndef MURMUR2_H #define MURMUR2_H /* prototypes */ extern unsigned int murmurhash2(const void *, int, const unsigned int); #endif //MURMUR2_H pmacct-1.7.8/src/ip_frag.c0000644000175000017500000004015514354105275014361 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "ip_frag.h" #include "jhash.h" /* global variables */ struct ip_fragment *ipft[IPFT_HASHSZ]; struct lru_l lru_list; struct ip6_fragment *ipft6[IPFT_HASHSZ]; struct lru_l6 lru_list6; u_int32_t ipft_total_nodes; time_t prune_deadline; time_t emergency_prune; u_int32_t trivial_hash_rnd = 140281; /* ummmh */ u_int32_t ipft6_total_nodes; time_t prune_deadline6; time_t emergency_prune6; void enable_ip_fragment_handler() { if (!config.handle_fragments) { config.handle_fragments = TRUE; init_ip_fragment_handler(); } } void init_ip_fragment_handler() { init_ip4_fragment_handler(); init_ip6_fragment_handler(); } void init_ip4_fragment_handler() { if (config.frag_bufsz) ipft_total_nodes = config.frag_bufsz / sizeof(struct ip_fragment); else ipft_total_nodes = DEFAULT_FRAG_BUFFER_SIZE / sizeof(struct ip_fragment); memset(ipft, 0, sizeof(ipft)); lru_list.root = (struct ip_fragment *) malloc(sizeof(struct ip_fragment)); lru_list.last = lru_list.root; memset(lru_list.root, 0, sizeof(struct ip_fragment)); prune_deadline = time(NULL)+PRUNE_INTERVAL; emergency_prune = 0; } int ip_fragment_handler(struct packet_ptrs *pptrs) { u_int32_t now = time(NULL); if (now > prune_deadline) { prune_old_fragments(now, PRUNE_OFFSET); prune_deadline = now+PRUNE_INTERVAL; } return find_fragment(now, pptrs); } int find_fragment(u_int32_t now, struct packet_ptrs *pptrs) { struct pm_iphdr *iphp = (struct pm_iphdr *)pptrs->iph_ptr; struct ip_fragment *fp, *candidate = NULL, *last_seen = NULL; unsigned int bucket = hash_fragment(iphp->ip_id, iphp->ip_src.s_addr, iphp->ip_dst.s_addr, iphp->ip_p); int ret; for (fp = ipft[bucket]; fp; fp = fp->next) { if (fp->ip_id == iphp->ip_id && fp->ip_src == iphp->ip_src.s_addr && fp->ip_dst == iphp->ip_dst.s_addr && fp->ip_p == iphp->ip_p) { /* fragment found; will check for its deadline */ if (fp->deadline > now) { if (fp->got_first) { // pptrs->tlh_ptr = fp->tlhdr; memcpy(pptrs->tlh_ptr, fp->tlhdr, MyTLHdrSz); pptrs->frag_first_found = TRUE; return TRUE; } else { if (!(iphp->ip_off & htons(IP_OFFMASK))) { /* we got our first fragment */ fp->got_first = TRUE; memcpy(fp->tlhdr, pptrs->tlh_ptr, MyTLHdrSz); pptrs->frag_sum_bytes = fp->a; pptrs->frag_sum_pkts = fp->pa; fp->pa = 0; fp->a = 0; pptrs->frag_first_found = TRUE; return TRUE; } else { /* we still don't have the first fragment; increase accumulators */ if (!config.ext_sampling_rate) { fp->pa++; fp->a += ntohs(iphp->ip_len); } pptrs->frag_first_found = FALSE; return FALSE; } } } else { candidate = fp; if (!candidate->got_first) notify_orphan_fragment(candidate); goto create; } } if ((fp->deadline < now) && !candidate) { candidate = fp; if (!candidate->got_first) notify_orphan_fragment(candidate); } last_seen = fp; } create: if (candidate) ret = create_fragment(now, candidate, TRUE, bucket, pptrs); else ret = create_fragment(now, last_seen, FALSE, bucket, pptrs); pptrs->frag_first_found = ret; return ret; } int create_fragment(u_int32_t now, struct ip_fragment *fp, u_int8_t is_candidate, unsigned int bucket, struct packet_ptrs *pptrs) { struct pm_iphdr *iphp = (struct pm_iphdr *)pptrs->iph_ptr; struct ip_fragment *newf; if (!ipft_total_nodes) { if (now > emergency_prune+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/4 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune = now; prune_old_fragments(now, 0); } return FALSE; } if (fp) { /* a 'not candidate' is simply the tail (last node) of the list. We need to allocate a new node */ if (!is_candidate) { newf = (struct ip_fragment *) malloc(sizeof(struct ip_fragment)); if (!newf) { if (now > emergency_prune+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/4 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune = now; prune_old_fragments(now, 0); } return FALSE; } else ipft_total_nodes--; memset(newf, 0, sizeof(struct ip_fragment)); fp->next = newf; newf->prev = fp; lru_list.last->lru_next = newf; /* placing new node as LRU tail */ newf->lru_prev = lru_list.last; lru_list.last = newf; fp = newf; } else { if (fp->lru_next) { /* if fp->lru_next==NULL the node is already the tail */ fp->lru_prev->lru_next = fp->lru_next; fp->lru_next->lru_prev = fp->lru_prev; lru_list.last->lru_next = fp; fp->lru_prev = lru_list.last; fp->lru_next = NULL; lru_list.last = fp; } } } else { /* we don't have any fragment pointer; this is because current bucket doesn't contain any node; we'll allocate first one */ fp = (struct ip_fragment *) malloc(sizeof(struct ip_fragment)); if (!fp) { if (now > emergency_prune+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/4 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune = now; prune_old_fragments(now, 0); } return FALSE; } else ipft_total_nodes--; memset(fp, 0, sizeof(struct ip_fragment)); ipft[bucket] = fp; lru_list.last->lru_next = fp; /* placing new node as LRU tail */ fp->lru_prev = lru_list.last; lru_list.last = fp; } fp->deadline = now+IPF_TIMEOUT; fp->ip_id = iphp->ip_id; fp->ip_p = iphp->ip_p; fp->ip_src = iphp->ip_src.s_addr; fp->ip_dst = iphp->ip_dst.s_addr; fp->bucket = bucket; if (!(iphp->ip_off & htons(IP_OFFMASK))) { /* it's a first fragment */ fp->got_first = TRUE; memcpy(fp->tlhdr, pptrs->tlh_ptr, MyTLHdrSz); return TRUE; } else { /* not a first fragment; increase accumulators */ if (!config.ext_sampling_rate) { fp->pa++; fp->a = ntohs(iphp->ip_len); } return FALSE; } } void prune_old_fragments(u_int32_t now, u_int32_t off) { struct ip_fragment *fp, *temp; u_int32_t deadline = now-off; fp = lru_list.root->lru_next; while (fp) { if (deadline > fp->deadline) { /* we found a stale element; we'll prune it */ if (fp->lru_next) temp = fp->lru_next; else temp = NULL; /* rearranging bucket's pointers */ if (fp->prev && fp->next) { fp->prev->next = fp->next; fp->next->prev = fp->prev; } else if (fp->prev) fp->prev->next = NULL; else if (fp->next) { ipft[fp->bucket] = fp->next; fp->next->prev = NULL; } else ipft[fp->bucket] = NULL; free(fp); ipft_total_nodes++; if (temp) fp = temp; else fp = NULL; } else break; } if (fp) { fp->lru_prev = lru_list.root; lru_list.root->lru_next = fp; } else lru_list.last = lru_list.root; } /* hash_fragment() is taken (it has another name there) from Linux kernel 2.4; see full credits contained in jhash.h */ unsigned int hash_fragment(u_int16_t id, u_int32_t src, u_int32_t dst, u_int8_t proto) { return jhash_3words((u_int32_t)id << 16 | proto, src, dst, trivial_hash_rnd) & (IPFT_HASHSZ-1); } void notify_orphan_fragment(struct ip_fragment *frag) { struct host_addr a; char src_host[INET_ADDRSTRLEN], dst_host[INET_ADDRSTRLEN]; u_int16_t id; a.family = AF_INET; memcpy(&a.address.ipv4, &frag->ip_src, 4); addr_to_str(src_host, &a); memcpy(&a.address.ipv4, &frag->ip_dst, 4); addr_to_str(dst_host, &a); id = ntohs(frag->ip_id); Log(LOG_DEBUG, "DEBUG ( %s/core ): Expiring orphan fragment: ip_src=%s ip_dst=%s proto=%u id=%u\n", config.name, src_host, dst_host, frag->ip_p, id); } void init_ip6_fragment_handler() { if (config.frag_bufsz) ipft6_total_nodes = config.frag_bufsz / sizeof(struct ip6_fragment); else ipft6_total_nodes = DEFAULT_FRAG_BUFFER_SIZE / sizeof(struct ip6_fragment); memset(ipft6, 0, sizeof(ipft6)); lru_list6.root = (struct ip6_fragment *) malloc(sizeof(struct ip6_fragment)); lru_list6.last = lru_list6.root; memset(lru_list6.root, 0, sizeof(struct ip6_fragment)); prune_deadline6 = time(NULL)+PRUNE_INTERVAL; emergency_prune6 = 0; } int ip6_fragment_handler(struct packet_ptrs *pptrs, struct ip6_frag *fhdr) { u_int32_t now = time(NULL); if (now > prune_deadline6) { prune_old_fragments6(now, PRUNE_OFFSET); prune_deadline6 = now+PRUNE_INTERVAL; } return find_fragment6(now, pptrs, fhdr); } unsigned int hash_fragment6(u_int32_t id, struct in6_addr *saddr, struct in6_addr *daddr) { u_int32_t a, b, c; u_int32_t *src = (u_int32_t *)saddr, *dst = (u_int32_t *)daddr; a = src[0]; b = src[1]; c = src[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += trivial_hash_rnd; __jhash_mix(a, b, c); a += src[3]; b += dst[0]; c += dst[1]; __jhash_mix(a, b, c); a += dst[2]; b += dst[3]; c += id; __jhash_mix(a, b, c); return c & (IPFT_HASHSZ - 1); } int find_fragment6(u_int32_t now, struct packet_ptrs *pptrs, struct ip6_frag *fhdr) { struct ip6_hdr *iphp = (struct ip6_hdr *)pptrs->iph_ptr; struct ip6_fragment *fp, *candidate = NULL, *last_seen = NULL; unsigned int bucket = hash_fragment6(fhdr->ip6f_ident, &iphp->ip6_src, &iphp->ip6_dst); for (fp = ipft6[bucket]; fp; fp = fp->next) { if (fp->id == fhdr->ip6f_ident && !ip6_addr_cmp(&fp->src, &iphp->ip6_src) && !ip6_addr_cmp(&fp->dst, &iphp->ip6_dst)) { /* fragment found; will check for its deadline */ if (fp->deadline > now) { if (fp->got_first) { // pptrs->tlh_ptr = fp->tlhdr; memcpy(pptrs->tlh_ptr, fp->tlhdr, MyTLHdrSz); return TRUE; } else { if (!(fhdr->ip6f_offlg & htons(IP6F_OFF_MASK))) { /* we got our first fragment */ fp->got_first = TRUE; memcpy(fp->tlhdr, pptrs->tlh_ptr, MyTLHdrSz); pptrs->frag_sum_bytes = fp->a; pptrs->frag_sum_pkts = fp->pa; fp->pa = 0; fp->a = 0; return TRUE; } else { /* we still don't have the first fragment; increase accumulators */ if (!config.ext_sampling_rate) { fp->pa++; fp->a += IP6HdrSz+ntohs(iphp->ip6_plen); } return FALSE; } } } else { candidate = fp; if (!candidate->got_first) notify_orphan_fragment6(candidate); goto create; } } if ((fp->deadline < now) && !candidate) { candidate = fp; if (!candidate->got_first) notify_orphan_fragment6(candidate); } last_seen = fp; } create: if (candidate) return create_fragment6(now, candidate, TRUE, bucket, pptrs, fhdr); else return create_fragment6(now, last_seen, FALSE, bucket, pptrs, fhdr); } int create_fragment6(u_int32_t now, struct ip6_fragment *fp, u_int8_t is_candidate, unsigned int bucket, struct packet_ptrs *pptrs, struct ip6_frag *fhdr) { struct ip6_hdr *iphp = (struct ip6_hdr *)pptrs->iph_ptr; struct ip6_fragment *newf; if (!ipft6_total_nodes) { if (now > emergency_prune6+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/6 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune6 = now; prune_old_fragments6(now, 0); } return FALSE; } if (fp) { /* a 'not candidate' is simply the tail (last node) of the list. We need to allocate a new node */ if (!is_candidate) { newf = (struct ip6_fragment *) malloc(sizeof(struct ip6_fragment)); if (!newf) { if (now > emergency_prune6+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/6 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune6 = now; prune_old_fragments6(now, 0); } return FALSE; } else ipft6_total_nodes--; memset(newf, 0, sizeof(struct ip6_fragment)); fp->next = newf; newf->prev = fp; lru_list6.last->lru_next = newf; /* placing new node as LRU tail */ newf->lru_prev = lru_list6.last; lru_list6.last = newf; fp = newf; } else { if (fp->lru_next) { /* if fp->lru_next==NULL the node is already the tail */ fp->lru_prev->lru_next = fp->lru_next; fp->lru_next->lru_prev = fp->lru_prev; lru_list6.last->lru_next = fp; fp->lru_prev = lru_list6.last; fp->lru_next = NULL; lru_list6.last = fp; } } } else { /* we don't have any fragment pointer; this is because current bucket doesn't contain any node; we'll allocate first one */ fp = (struct ip6_fragment *) malloc(sizeof(struct ip6_fragment)); if (!fp) { if (now > emergency_prune6+EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Fragment/6 buffer full. Skipping fragments. Increase %s_frag_buffer_size\n", config.name, config.progname); emergency_prune6 = now; prune_old_fragments6(now, 0); } return FALSE; } else ipft6_total_nodes--; memset(fp, 0, sizeof(struct ip6_fragment)); ipft6[bucket] = fp; lru_list6.last->lru_next = fp; /* placing new node as LRU tail */ fp->lru_prev = lru_list6.last; lru_list6.last = fp; } fp->deadline = now+IPF_TIMEOUT; fp->id = fhdr->ip6f_ident; ip6_addr_cpy(&fp->src, &iphp->ip6_src); ip6_addr_cpy(&fp->dst, &iphp->ip6_dst); fp->bucket = bucket; if (!(fhdr->ip6f_offlg & htons(IP6F_OFF_MASK))) { /* it's a first fragment */ fp->got_first = TRUE; memcpy(fp->tlhdr, pptrs->tlh_ptr, MyTLHdrSz); return TRUE; } else { /* not a first fragment; increase accumulators */ if (!config.ext_sampling_rate) { fp->pa++; fp->a = IP6HdrSz+ntohs(iphp->ip6_plen); } return FALSE; } } void prune_old_fragments6(u_int32_t now, u_int32_t off) { struct ip6_fragment *fp, *temp; u_int32_t deadline = now-off; fp = lru_list6.root->lru_next; while (fp) { if (deadline > fp->deadline) { /* we found a stale element; we'll prune it */ if (fp->lru_next) temp = fp->lru_next; else temp = NULL; /* rearranging bucket's pointers */ if (fp->prev && fp->next) { fp->prev->next = fp->next; fp->next->prev = fp->prev; } else if (fp->prev) fp->prev->next = NULL; else if (fp->next) { ipft6[fp->bucket] = fp->next; fp->next->prev = NULL; } else ipft6[fp->bucket] = NULL; free(fp); ipft6_total_nodes++; if (temp) fp = temp; else fp = NULL; } else break; } if (fp) { fp->lru_prev = lru_list6.root; lru_list6.root->lru_next = fp; } else lru_list6.last = lru_list6.root; } void notify_orphan_fragment6(struct ip6_fragment *frag) { struct host_addr a; char src_host[INET6_ADDRSTRLEN], dst_host[INET6_ADDRSTRLEN]; u_int32_t id; a.family = AF_INET6; ip6_addr_cpy(&a.address.ipv6, &frag->src); addr_to_str(src_host, &a); ip6_addr_cpy(&a.address.ipv6, &frag->dst); addr_to_str(dst_host, &a); id = ntohl(frag->id); Log(LOG_DEBUG, "DEBUG ( %s/core ): Expiring orphan fragment: ip_src=%s ip_dst=%s id=%u\n", config.name, src_host, dst_host, id); } pmacct-1.7.8/src/amqp_plugin.h0000644000175000017500000000245414354105275015273 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef AMQP_PLUGIN_COMMON_H #define AMQP_PLUGIN_COMMON_H /* includes */ #include #include #include #include "plugin_common.h" /* defines */ /* structures */ /* prototypes */ extern void p_amqp_get_version(); extern void amqp_plugin(int, struct configuration *, void *); extern void amqp_cache_purge(struct chained_cache *[], int, int); #ifdef WITH_AVRO extern void amqp_avro_schema_purge(char *); #endif #endif //AMQP_PLUGIN_COMMON_H pmacct-1.7.8/src/ndpi/0000755000175000017500000000000014354105416013530 5ustar paolopaolopmacct-1.7.8/src/ndpi/ndpi.h0000644000175000017500000001237214354105275014643 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Originally based on: ndpi.h | nDPI | Copyright (C) 2011-17 - ntop.org */ #ifndef NDPI_H #define NDPI_H /* includes */ #include "ndpi_util.h" /* defines */ #define NDPI_IDLE_SCAN_PERIOD 10 #define NDPI_IDLE_MAX_TIME 600 #define NDPI_IDLE_SCAN_BUDGET 1024 #define NDPI_NUM_ROOTS 512 #define NDPI_MAXFLOWS 200000000 #define NDPI_TICK_RESOLUTION 1000 #define NDPI_GIVEUP_PROTO_TCP 10 #define NDPI_GIVEUP_PROTO_UDP 8 #define NDPI_GIVEUP_PROTO_OTHER 8 #if (NDPI_MAJOR == 4 && NDPI_MINOR >= 2) || NDPI_MAJOR > 4 typedef void ndpi_id_struct_t; #define SIZEOF_ID_STRUCT sizeof(ndpi_id_struct_t) #else typedef struct ndpi_id_struct ndpi_id_struct_t; #endif /* flow tracking */ typedef struct pm_ndpi_flow_info { u_int32_t lower_ip; u_int32_t upper_ip; u_int16_t lower_port; u_int16_t upper_port; u_int8_t detection_completed; u_int8_t guess_completed; u_int8_t tcp_finished; u_int8_t protocol; u_int8_t src_to_dst_direction; u_int16_t vlan_id; struct ndpi_flow_struct *ndpi_flow; u_int8_t ip_version; u_int64_t last_seen; u_int64_t bytes; u_int32_t packets; /* result only, not used for flow identification */ ndpi_protocol detected_protocol; void *src_id; void *dst_id; } pm_ndpi_flow_info_t; /* flow statistics info */ typedef struct pm_ndpi_stats { u_int32_t guessed_flow_protocols; u_int64_t raw_packet_count; u_int64_t ip_packet_count; u_int64_t total_wire_bytes, total_ip_bytes, total_discarded_bytes; u_int64_t protocol_counter[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; u_int64_t protocol_counter_bytes[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; u_int32_t protocol_flows[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; u_int32_t ndpi_flow_count; u_int64_t tcp_count, udp_count; u_int64_t mpls_count, pppoe_count, vlan_count, fragmented_count; u_int64_t packet_len[6]; u_int16_t max_packet_len; } pm_ndpi_stats_t; /* flow preferences */ typedef struct pm_ndpi_workflow_prefs { u_int8_t decode_tunnels; u_int8_t protocol_guess; u_int32_t num_roots; u_int32_t max_ndpi_flows; u_int32_t idle_scan_period; u_int32_t idle_max_time; u_int32_t idle_scan_budget; u_int8_t giveup_proto_tcp; u_int8_t giveup_proto_udp; u_int8_t giveup_proto_other; } pm_ndpi_workflow_prefs_t; struct pm_ndpi_workflow; /* workflow main structure */ typedef struct pm_ndpi_workflow { u_int64_t last_time; u_int64_t last_idle_scan_time; u_int32_t num_idle_flows; u_int32_t idle_scan_idx; struct pm_ndpi_flow_info *idle_flows[NDPI_IDLE_SCAN_BUDGET]; struct pm_ndpi_workflow_prefs prefs; struct pm_ndpi_stats stats; /* allocated by prefs */ void **ndpi_flows_root; struct ndpi_detection_module_struct *ndpi_struct; } pm_ndpi_workflow_t; /* global vars */ extern struct pm_ndpi_workflow *pm_ndpi_wfl; /* prototypes */ /* Free flow_info ndpi support structures but not the flow_info itself */ extern void pm_ndpi_free_flow_info_half(struct pm_ndpi_flow_info *); /* Process a packet and update the workflow */ extern struct ndpi_proto pm_ndpi_workflow_process_packet(struct pm_ndpi_workflow *, struct packet_ptrs *); /* compare two nodes in workflow */ extern int pm_ndpi_workflow_node_cmp(const void *, const void *); extern struct pm_ndpi_flow_info *pm_ndpi_get_flow_info(struct pm_ndpi_workflow *, struct packet_ptrs *, u_int16_t, const struct ndpi_iphdr *, const struct ndpi_ipv6hdr *, u_int16_t, u_int16_t, u_int16_t, struct ndpi_tcphdr **, struct ndpi_udphdr **, u_int16_t *, u_int16_t *, ndpi_id_struct_t **, ndpi_id_struct_t **, u_int8_t *, u_int8_t **, u_int16_t *, u_int8_t *); extern struct pm_ndpi_flow_info *pm_ndpi_get_flow_info6(struct pm_ndpi_workflow *, struct packet_ptrs *, u_int16_t, const struct ndpi_ipv6hdr *, u_int16_t, struct ndpi_tcphdr **, struct ndpi_udphdr **, u_int16_t *, u_int16_t *, ndpi_id_struct_t **, ndpi_id_struct_t **, u_int8_t *, u_int8_t **, u_int16_t *, u_int8_t *); extern struct ndpi_proto pm_ndpi_packet_processing(struct pm_ndpi_workflow *, struct packet_ptrs *, const u_int64_t, u_int16_t, const struct ndpi_iphdr *, struct ndpi_ipv6hdr *, u_int16_t, u_int16_t, u_int16_t); extern u_int16_t pm_ndpi_node_guess_undetected_protocol(struct pm_ndpi_workflow *, struct pm_ndpi_flow_info *); extern void pm_ndpi_idle_flows_cleanup(struct pm_ndpi_workflow *); extern int pm_ndpi_node_idle_scan_walker(const void *, const pm_VISIT, const int, void *); #endif //NDPI_H pmacct-1.7.8/src/ndpi/ndpi_util.h0000644000175000017500000000203114354105275015667 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NDPI_UTIL_H #define NDPI_UTIL_H /* prototypes */ extern struct pm_ndpi_workflow *pm_ndpi_workflow_init(); extern void pm_ndpi_export_proto_to_class(struct pm_ndpi_workflow *); #endif //NDPI_UTIL_H pmacct-1.7.8/src/ndpi/ndpi.c0000644000175000017500000004226014354105275014635 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Originally based on: ndpi.c ndpiReader.c | nDPI | Copyright (C) 2011-17 - ntop.org */ #include "../pmacct.h" #include "../ip_flow.h" #include "../classifier.h" #include "ndpi.h" /* Global variables */ struct pm_ndpi_workflow *pm_ndpi_wfl; void pm_ndpi_free_flow_info_half(struct pm_ndpi_flow_info *flow) { if (flow) { if (flow->ndpi_flow) { ndpi_flow_free(flow->ndpi_flow); flow->ndpi_flow = NULL; } if (flow->src_id) { ndpi_free(flow->src_id); flow->src_id = NULL; } if (flow->dst_id) { ndpi_free(flow->dst_id); flow->dst_id = NULL; } } } int pm_ndpi_workflow_node_cmp(const void *a, const void *b) { struct pm_ndpi_flow_info *fa = (struct pm_ndpi_flow_info*)a; struct pm_ndpi_flow_info *fb = (struct pm_ndpi_flow_info*)b; if(fa->vlan_id < fb->vlan_id ) return(-1); else { if(fa->vlan_id > fb->vlan_id ) return(1); } if(fa->lower_ip < fb->lower_ip ) return(-1); else { if(fa->lower_ip > fb->lower_ip ) return(1); } if(fa->lower_port < fb->lower_port) return(-1); else { if(fa->lower_port > fb->lower_port) return(1); } if(fa->upper_ip < fb->upper_ip ) return(-1); else { if(fa->upper_ip > fb->upper_ip ) return(1); } if(fa->upper_port < fb->upper_port) return(-1); else { if(fa->upper_port > fb->upper_port) return(1); } if(fa->protocol < fb->protocol ) return(-1); else { if(fa->protocol > fb->protocol ) return(1); } return(0); } struct pm_ndpi_flow_info *pm_ndpi_get_flow_info(struct pm_ndpi_workflow *workflow, struct packet_ptrs *pptrs, u_int16_t vlan_id, const struct ndpi_iphdr *iph, const struct ndpi_ipv6hdr *iph6, u_int16_t ip_offset, u_int16_t ipsize, u_int16_t l4_packet_len, struct ndpi_tcphdr **tcph, struct ndpi_udphdr **udph, u_int16_t *sport, u_int16_t *dport, ndpi_id_struct_t **src, ndpi_id_struct_t **dst, u_int8_t *proto, u_int8_t **payload, u_int16_t *payload_len, u_int8_t *src_to_dst_direction) { u_int32_t idx; u_int32_t lower_ip; u_int32_t upper_ip; u_int16_t lower_port; u_int16_t upper_port; struct pm_ndpi_flow_info flow; void *ret; u_int8_t *l4; /* IPv4 fragments handling */ if (pptrs->l3_proto == ETHERTYPE_IP) { if ((((struct pm_iphdr *)pptrs->iph_ptr)->ip_off & htons(IP_OFFMASK))) { if (!log_notification_isset(&log_notifications.ndpi_tmp_frag_warn, pptrs->pkthdr->ts.tv_sec)) { Log(LOG_WARNING, "WARN ( %s/core ): nDPI support for fragmented traffic not implemented. %s: %s\n", config.name, GET_IN_TOUCH_MSG, MANTAINER); log_notification_set(&log_notifications.ndpi_cache_full, pptrs->pkthdr->ts.tv_sec, 180); } if (pptrs->frag_first_found) { // XXX } else return NULL; } } if (iph->saddr < iph->daddr) { lower_ip = iph->saddr; upper_ip = iph->daddr; } else { lower_ip = iph->daddr; upper_ip = iph->saddr; } *proto = iph->protocol; l4 = (u_int8_t *) pptrs->tlh_ptr; /* TCP */ if (iph->protocol == IPPROTO_TCP && l4_packet_len >= 20) { u_int tcp_len; *tcph = (struct ndpi_tcphdr *)l4; *sport = ntohs((*tcph)->source), *dport = ntohs((*tcph)->dest); if (iph->saddr < iph->daddr) { lower_port = (*tcph)->source, upper_port = (*tcph)->dest; *src_to_dst_direction = 1; } else { lower_port = (*tcph)->dest; upper_port = (*tcph)->source; *src_to_dst_direction = 0; if (iph->saddr == iph->daddr) { if (lower_port > upper_port) { u_int16_t p = lower_port; lower_port = upper_port; upper_port = p; } } } tcp_len = ndpi_min(4*(*tcph)->doff, l4_packet_len); *payload = &l4[tcp_len]; *payload_len = ndpi_max(0, l4_packet_len-4*(*tcph)->doff); } /* UDP */ else if (iph->protocol == IPPROTO_UDP && l4_packet_len >= 8) { *udph = (struct ndpi_udphdr *)l4; *sport = ntohs((*udph)->source), *dport = ntohs((*udph)->dest); *payload = &l4[sizeof(struct ndpi_udphdr)]; *payload_len = ndpi_max(0, l4_packet_len-sizeof(struct ndpi_udphdr)); if (iph->saddr < iph->daddr) { lower_port = (*udph)->source, upper_port = (*udph)->dest; *src_to_dst_direction = 1; } else { lower_port = (*udph)->dest, upper_port = (*udph)->source; *src_to_dst_direction = 0; if (iph->saddr == iph->daddr) { if (lower_port > upper_port) { u_int16_t p = lower_port; lower_port = upper_port; upper_port = p; } } } *sport = ntohs(lower_port), *dport = ntohs(upper_port); } else { // non tcp/udp protocols lower_port = 0; upper_port = 0; } flow.protocol = iph->protocol, flow.vlan_id = vlan_id; flow.lower_ip = lower_ip, flow.upper_ip = upper_ip; flow.lower_port = lower_port, flow.upper_port = upper_port; /* Log(LOG_DEBUG, "DEBUG ( %s/core ): "pm_ndpi_get_flow_info(): [%u][%u:%u <-> %u:%u]\n", iph->protocol, lower_ip, ntohs(lower_port), upper_ip, ntohs(upper_port)); */ idx = (vlan_id + lower_ip + upper_ip + iph->protocol + lower_port + upper_port) % workflow->prefs.num_roots; ret = pm_tfind(&flow, &workflow->ndpi_flows_root[idx], pm_ndpi_workflow_node_cmp); if (ret == NULL) { if (workflow->stats.ndpi_flow_count == workflow->prefs.max_ndpi_flows) { if (!log_notification_isset(&log_notifications.ndpi_cache_full, pptrs->pkthdr->ts.tv_sec)) { Log(LOG_WARNING, "WARN ( %s/core ): nDPI maximum flow count (%u) has been exceeded.\n", config.name, workflow->prefs.max_ndpi_flows); log_notification_set(&log_notifications.ndpi_cache_full, pptrs->pkthdr->ts.tv_sec, 60); } return(NULL); } else { struct pm_ndpi_flow_info *newflow = (struct pm_ndpi_flow_info*)malloc(sizeof(struct pm_ndpi_flow_info)); if (newflow == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): pm_ndpi_get_flow_info() not enough memory (1).\n", config.name); exit_gracefully(1); } memset(newflow, 0, sizeof(struct pm_ndpi_flow_info)); newflow->protocol = iph->protocol, newflow->vlan_id = vlan_id; newflow->lower_ip = lower_ip, newflow->upper_ip = upper_ip; newflow->lower_port = lower_port, newflow->upper_port = upper_port; newflow->ip_version = pptrs->l3_proto; newflow->src_to_dst_direction = *src_to_dst_direction; if ((newflow->ndpi_flow = ndpi_flow_malloc(SIZEOF_FLOW_STRUCT)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): pm_ndpi_get_flow_info() not enough memory (2).\n", config.name); exit_gracefully(1); } else memset(newflow->ndpi_flow, 0, SIZEOF_FLOW_STRUCT); if ((newflow->src_id = ndpi_malloc(SIZEOF_ID_STRUCT)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): pm_ndpi_get_flow_info() not enough memory (3).\n", config.name); exit_gracefully(1); } else memset(newflow->src_id, 0, SIZEOF_ID_STRUCT); if ((newflow->dst_id = ndpi_malloc(SIZEOF_ID_STRUCT)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): pm_ndpi_get_flow_info() not enough memory (4).\n", config.name); exit_gracefully(1); } else memset(newflow->dst_id, 0, SIZEOF_ID_STRUCT); pm_tsearch(newflow, &workflow->ndpi_flows_root[idx], pm_ndpi_workflow_node_cmp, 0); /* Add */ workflow->stats.ndpi_flow_count++; *src = newflow->src_id, *dst = newflow->dst_id; return newflow; } } else { struct pm_ndpi_flow_info *flow = *(struct pm_ndpi_flow_info**)ret; if (flow->lower_ip == lower_ip && flow->upper_ip == upper_ip && flow->lower_port == lower_port && flow->upper_port == upper_port) *src = flow->src_id, *dst = flow->dst_id; else *src = flow->dst_id, *dst = flow->src_id; return flow; } } struct pm_ndpi_flow_info *pm_ndpi_get_flow_info6(struct pm_ndpi_workflow *workflow, struct packet_ptrs *pptrs, u_int16_t vlan_id, const struct ndpi_ipv6hdr *iph6, u_int16_t ip_offset, struct ndpi_tcphdr **tcph, struct ndpi_udphdr **udph, u_int16_t *sport, u_int16_t *dport, ndpi_id_struct_t **src, ndpi_id_struct_t **dst, u_int8_t *proto, u_int8_t **payload, u_int16_t *payload_len, u_int8_t *src_to_dst_direction) { struct ndpi_iphdr iph; memset(&iph, 0, sizeof(iph)); iph.version = IPVERSION; iph.saddr = iph6->ip6_src.u6_addr.u6_addr32[2] + iph6->ip6_src.u6_addr.u6_addr32[3]; iph.daddr = iph6->ip6_dst.u6_addr.u6_addr32[2] + iph6->ip6_dst.u6_addr.u6_addr32[3]; iph.protocol = iph6->ip6_hdr.ip6_un1_nxt; if (iph.protocol == IPPROTO_DSTOPTS /* IPv6 destination option */) { u_int8_t *options = (u_int8_t*)iph6 + sizeof(const struct ndpi_ipv6hdr); iph.protocol = options[0]; } return(pm_ndpi_get_flow_info(workflow, pptrs, vlan_id, &iph, iph6, ip_offset, sizeof(struct ndpi_ipv6hdr), ntohs(iph6->ip6_hdr.ip6_un1_plen), tcph, udph, sport, dport, src, dst, proto, payload, payload_len, src_to_dst_direction)); } /* Function to process the packet: determine the flow of a packet and try to decode it @return: 0 if success; else != 0 @Note: ipsize = header->len - ip_offset ; rawsize = header->len */ struct ndpi_proto pm_ndpi_packet_processing(struct pm_ndpi_workflow *workflow, struct packet_ptrs *pptrs, const u_int64_t time, u_int16_t vlan_id, const struct ndpi_iphdr *iph, struct ndpi_ipv6hdr *iph6, u_int16_t ip_offset, u_int16_t ipsize, u_int16_t rawsize) { ndpi_id_struct_t *src, *dst; struct pm_ndpi_flow_info *flow = NULL; struct ndpi_flow_struct *ndpi_flow = NULL; u_int8_t proto; struct ndpi_tcphdr *tcph = NULL; struct ndpi_udphdr *udph = NULL; u_int16_t sport, dport, payload_len; u_int8_t *payload; u_int8_t src_to_dst_direction = 1; struct ndpi_proto nproto = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN }; if (!workflow) return nproto; if (iph) flow = pm_ndpi_get_flow_info(workflow, pptrs, vlan_id, iph, NULL, ip_offset, ipsize, ntohs(iph->tot_len) - (iph->ihl * 4), &tcph, &udph, &sport, &dport, &src, &dst, &proto, &payload, &payload_len, &src_to_dst_direction); else if (iph6) flow = pm_ndpi_get_flow_info6(workflow, pptrs, vlan_id, iph6, ip_offset, &tcph, &udph, &sport, &dport, &src, &dst, &proto, &payload, &payload_len, &src_to_dst_direction); if (flow) { workflow->stats.ip_packet_count++; workflow->stats.total_wire_bytes += rawsize + 24 /* CRC etc */, workflow->stats.total_ip_bytes += rawsize; ndpi_flow = flow->ndpi_flow; flow->packets++, flow->bytes += rawsize; flow->last_seen = time; } else { // flow is NULL workflow->stats.total_discarded_bytes++; return (nproto); } /* Protocol already detected */ if (flow->detection_completed) return(flow->detected_protocol); #if (NDPI_MAJOR == 4 && NDPI_MINOR >= 2) || NDPI_MAJOR > 4 flow->detected_protocol = ndpi_detection_process_packet(workflow->ndpi_struct, ndpi_flow, iph ? (uint8_t *)iph : (uint8_t *)iph6, ipsize, time); #else flow->detected_protocol = ndpi_detection_process_packet(workflow->ndpi_struct, ndpi_flow, iph ? (uint8_t *)iph : (uint8_t *)iph6, ipsize, time, src, dst); #endif if ((flow->detected_protocol.app_protocol != NDPI_PROTOCOL_UNKNOWN) || ((proto == IPPROTO_UDP) && (flow->packets > workflow->prefs.giveup_proto_tcp)) || ((proto == IPPROTO_TCP) && (flow->packets > workflow->prefs.giveup_proto_udp)) || ((proto != IPPROTO_UDP && proto != IPPROTO_TCP) && (flow->packets > workflow->prefs.giveup_proto_other))) { /* New protocol detected or give up */ flow->detection_completed = TRUE; } if (proto == IPPROTO_TCP) { struct pm_tcphdr *tcph = (struct pm_tcphdr *) pptrs->tlh_ptr; if (tcph->th_flags & (TH_FIN|TH_RST)) flow->tcp_finished = TRUE; } if (flow->detection_completed || flow->tcp_finished) { if (flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UNKNOWN) { flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow, 1, &workflow->prefs.protocol_guess); } if (workflow->prefs.protocol_guess) { if (flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UNKNOWN && !flow->guess_completed) { pm_ndpi_node_guess_undetected_protocol(workflow, flow); flow->guess_completed = TRUE; } } } return(flow->detected_protocol); } struct ndpi_proto pm_ndpi_workflow_process_packet(struct pm_ndpi_workflow *workflow, struct packet_ptrs *pptrs) { struct ndpi_iphdr *iph = NULL; struct ndpi_ipv6hdr *iph6 = NULL; struct ndpi_proto nproto = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN }; u_int64_t time = 0; u_int16_t ip_offset = 0, vlan_id = 0; if (!workflow || !pptrs) return nproto; if (pptrs->l3_proto == ETHERTYPE_IP) iph = (struct ndpi_iphdr *) pptrs->iph_ptr; else if (pptrs->l3_proto == ETHERTYPE_IPV6) iph6 = (struct ndpi_ipv6hdr *) pptrs->iph_ptr; /* Increment raw packet counter */ workflow->stats.raw_packet_count++; /* setting time */ time = ((uint64_t) pptrs->pkthdr->ts.tv_sec) * NDPI_TICK_RESOLUTION + pptrs->pkthdr->ts.tv_usec / (1000000 / NDPI_TICK_RESOLUTION); /* safety check */ if (workflow->last_time > time) time = workflow->last_time; /* update last time value */ workflow->last_time = time; if (pptrs->vlan_ptr) { memcpy(&vlan_id, pptrs->vlan_ptr, 2); vlan_id = ntohs(vlan_id); vlan_id = vlan_id & 0x0FFF; } /* safety check */ if (pptrs->iph_ptr < pptrs->packet_ptr) return nproto; ip_offset = (u_int16_t)(pptrs->iph_ptr - pptrs->packet_ptr); /* process the packet */ nproto = pm_ndpi_packet_processing(workflow, pptrs, time, vlan_id, iph, iph6, ip_offset, (pptrs->pkthdr->len - ip_offset), pptrs->pkthdr->len); pm_ndpi_idle_flows_cleanup(workflow); return nproto; } /* * Guess Undetected Protocol */ u_int16_t pm_ndpi_node_guess_undetected_protocol(struct pm_ndpi_workflow *workflow, struct pm_ndpi_flow_info *flow) { if (!flow || !workflow) return 0; flow->detected_protocol = ndpi_guess_undetected_protocol(workflow->ndpi_struct, flow->ndpi_flow, flow->protocol, ntohl(flow->lower_ip), ntohs(flow->lower_port), ntohl(flow->upper_ip), ntohs(flow->upper_port)); return (flow->detected_protocol.app_protocol); } /* * Idle Scan Walker */ int pm_ndpi_node_idle_scan_walker(const void *node, const pm_VISIT which, const int depth, void *user_data) { struct pm_ndpi_flow_info *flow = *(struct pm_ndpi_flow_info **) node; struct pm_ndpi_workflow *workflow = (struct pm_ndpi_workflow *) user_data; if (!flow || !workflow) return FALSE; if (workflow->num_idle_flows == workflow->prefs.idle_scan_budget) return FALSE; if ((which == (pm_VISIT)ndpi_preorder) || (which == (pm_VISIT)ndpi_leaf)) { /* Avoid walking the same node multiple times */ /* expire Idle and TCP finished flows */ if ((flow->last_seen + workflow->prefs.idle_max_time < workflow->last_time) || (flow->tcp_finished == TRUE)) { /* adding to a queue (we can't delete it from the tree inline) */ workflow->idle_flows[workflow->num_idle_flows++] = flow; } } return TRUE; } void pm_ndpi_idle_flows_cleanup(struct pm_ndpi_workflow *workflow) { if (!workflow) return; if ((workflow->last_idle_scan_time + workflow->prefs.idle_scan_period) < workflow->last_time) { /* scan for idle flows */ pm_twalk(workflow->ndpi_flows_root[workflow->idle_scan_idx], pm_ndpi_node_idle_scan_walker, workflow); /* remove idle flows (unfortunately we cannot do this inline) */ while (workflow->num_idle_flows > 0) { /* search and delete the idle flow from the "ndpi_flow_root" (see struct reader thread) - here flows are the node of a b-tree */ pm_tdelete(workflow->idle_flows[--workflow->num_idle_flows], &workflow->ndpi_flows_root[workflow->idle_scan_idx], pm_ndpi_workflow_node_cmp); /* free the memory associated to idle flow in "idle_flows" - (see struct reader thread)*/ pm_ndpi_free_flow_info_half(workflow->idle_flows[workflow->num_idle_flows]); ndpi_free(workflow->idle_flows[workflow->num_idle_flows]); workflow->stats.ndpi_flow_count--; } if (++workflow->idle_scan_idx == workflow->prefs.num_roots) workflow->idle_scan_idx = 0; workflow->last_idle_scan_time = workflow->last_time; } } pmacct-1.7.8/src/ndpi/ndpi_util.c0000644000175000017500000001232014354105275015664 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define NDPI_LIB_COMPILATION /* 4.2.0-stable trick */ #define SAVED_PACKAGE PACKAGE #undef PACKAGE #define SAVED_PACKAGE_BUGREPORT PACKAGE_BUGREPORT #undef PACKAGE_BUGREPORT #define SAVED_PACKAGE_NAME PACKAGE_NAME #undef PACKAGE_NAME #define SAVED_PACKAGE_STRING PACKAGE_STRING #undef PACKAGE_STRING #define SAVED_PACKAGE_TARNAME PACKAGE_TARNAME #undef PACKAGE_TARNAME #define SAVED_PACKAGE_VERSION PACKAGE_VERSION #undef PACKAGE_VERSION #define SAVED_VERSION VERSION #undef VERSION #include "../pmacct.h" /* 4.2.0-stable trick */ #undef PACKAGE #define PACKAGE SAVED_PACKAGE #undef PACKAGE_BUGREPORT #define PACKAGE_BUGREPORT SAVED_PACKAGE_BUGREPORT #undef PACKAGE_NAME #define PACKAGE_NAME SAVED_PACKAGE_NAME #undef PACKAGE_STRING #define PACKAGE_STRING SAVED_PACKAGE_STRING #undef PACKAGE_TARNAME #define PACKAGE_TARNAME SAVED_PACKAGE_TARNAME #undef PACKAGE_VERSION #define PACKAGE_VERSION SAVED_PACKAGE_VERSION #undef VERSION #define VERSION SAVED_VERSION #undef NDPI_LIB_COMPILATION #include "../ip_flow.h" #include "../classifier.h" #include "ndpi.h" struct pm_ndpi_workflow *pm_ndpi_workflow_init() { NDPI_PROTOCOL_BITMASK all; ndpi_init_prefs pm_ndpi_init_prefs = ndpi_no_prefs; struct ndpi_detection_module_struct *module = ndpi_init_detection_module(pm_ndpi_init_prefs); struct pm_ndpi_workflow *workflow = ndpi_calloc(1, sizeof(struct pm_ndpi_workflow)); log_notification_init(&log_notifications.ndpi_cache_full); log_notification_init(&log_notifications.ndpi_tmp_frag_warn); workflow->prefs.decode_tunnels = FALSE; if (config.ndpi_num_roots) workflow->prefs.num_roots = config.ndpi_num_roots; else workflow->prefs.num_roots = NDPI_NUM_ROOTS; if (config.ndpi_max_flows) workflow->prefs.max_ndpi_flows = config.ndpi_max_flows; else workflow->prefs.max_ndpi_flows = NDPI_MAXFLOWS; if (config.ndpi_proto_guess) workflow->prefs.protocol_guess = config.ndpi_proto_guess; else workflow->prefs.protocol_guess = FALSE; if (config.ndpi_idle_scan_period) workflow->prefs.idle_scan_period = config.ndpi_idle_scan_period; else workflow->prefs.idle_scan_period = NDPI_IDLE_SCAN_PERIOD; if (config.ndpi_idle_max_time) workflow->prefs.idle_max_time = config.ndpi_idle_max_time; else workflow->prefs.idle_max_time = NDPI_IDLE_MAX_TIME; if (config.ndpi_idle_scan_budget) workflow->prefs.idle_scan_budget = config.ndpi_idle_scan_budget; else workflow->prefs.idle_scan_budget = NDPI_IDLE_SCAN_BUDGET; if (config.ndpi_giveup_proto_tcp) workflow->prefs.giveup_proto_tcp = config.ndpi_giveup_proto_tcp; else workflow->prefs.giveup_proto_tcp = NDPI_GIVEUP_PROTO_TCP; if (config.ndpi_giveup_proto_udp) workflow->prefs.giveup_proto_udp = config.ndpi_giveup_proto_udp; else workflow->prefs.giveup_proto_udp = NDPI_GIVEUP_PROTO_UDP; if (config.ndpi_giveup_proto_other) workflow->prefs.giveup_proto_other = config.ndpi_giveup_proto_other; else workflow->prefs.giveup_proto_other = NDPI_GIVEUP_PROTO_OTHER; workflow->ndpi_struct = module; if (workflow->ndpi_struct == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): nDPI global structure initialization failed.\n", config.name); exit_gracefully(1); } workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *)); // enable all protocols NDPI_BITMASK_SET_ALL(all); ndpi_set_protocol_detection_bitmask2(workflow->ndpi_struct, &all); ndpi_finalize_initialization(workflow->ndpi_struct); return workflow; } void pm_ndpi_export_proto_to_class(struct pm_ndpi_workflow *workflow) { struct pkt_classifier css; u_int32_t class_st_sz; int idx, ret; if (!workflow || !workflow->ndpi_struct) return; class_st_sz = sizeof(struct pkt_classifier) * workflow->ndpi_struct->ndpi_num_supported_protocols; class = map_shared(0, class_st_sz, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); memset(class, 0, class_st_sz); for (idx = 0; idx < (int) workflow->ndpi_struct->ndpi_num_supported_protocols; idx++) { if (workflow->ndpi_struct->proto_defaults[idx].protoId) { memset(&css, 0, sizeof(css)); css.id = workflow->ndpi_struct->proto_defaults[idx].protoId; strncpy(css.protocol, workflow->ndpi_struct->proto_defaults[idx].protoName, MAX_PROTOCOL_LEN); css.category = workflow->ndpi_struct->proto_defaults[idx].protoCategory; ret = pmct_ndpi_register(&css); if (!ret) Log(LOG_WARNING, "WARN ( %s/core ): unable to register nDPI class ID %u.\n", config.name, css.id); } } } pmacct-1.7.8/src/ndpi/Makefile.in0000644000175000017500000004640414354105416015605 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/ndpi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libndpi_support_la_LIBADD = am_libndpi_support_la_OBJECTS = ndpi.lo ndpi_util.lo libndpi_support_la_OBJECTS = $(am_libndpi_support_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/ndpi.Plo ./$(DEPDIR)/ndpi_util.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libndpi_support_la_SOURCES) DIST_SOURCES = $(libndpi_support_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_LDFLAGS = @NDPI_LIBS@ AM_CFLAGS = $(PMACCT_CFLAGS) $(NDPI_CFLAGS) noinst_LTLIBRARIES = libndpi_support.la libndpi_support_la_SOURCES = ndpi.c ndpi.h ndpi_util.c ndpi_util.h libnddpi_support_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/ndpi/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/ndpi/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libndpi_support.la: $(libndpi_support_la_OBJECTS) $(libndpi_support_la_DEPENDENCIES) $(EXTRA_libndpi_support_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libndpi_support_la_OBJECTS) $(libndpi_support_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ndpi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ndpi_util.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/ndpi.Plo -rm -f ./$(DEPDIR)/ndpi_util.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/ndpi.Plo -rm -f ./$(DEPDIR)/ndpi_util.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/ndpi/Makefile.am0000644000175000017500000000035314354105275015570 0ustar paolopaoloAM_LDFLAGS = @NDPI_LIBS@ AM_CFLAGS = $(PMACCT_CFLAGS) $(NDPI_CFLAGS) noinst_LTLIBRARIES = libndpi_support.la libndpi_support_la_SOURCES = ndpi.c ndpi.h ndpi_util.c ndpi_util.h libnddpi_support_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/network.c0000644000175000017500000004177014354105275014447 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "network.h" #include "thread_pool.h" /* Global variables */ #ifdef WITH_GNUTLS xflow_status_table_t dtls_status_table; #endif struct tunnel_handler tunnel_registry[TUNNEL_REGISTRY_STACKS][TUNNEL_REGISTRY_ENTRIES]; int parse_proxy_header(int fd, struct host_addr *addr, u_int16_t *port) { const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"; char ip_address[INET6_ADDRSTRLEN]; size_t size = 0; proxy_protocol_header hdr; addr_to_str(ip_address, addr); int ret = recv(fd, &hdr, sizeof(hdr), MSG_PEEK); /* 16 bytes can detect both V1 and V2 protocols */ if (ret < 16) { return ERR; } if (memcmp(hdr.v1.line, "PROXY", 5) == 0) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol V1\n", config.name, config.type); char *end = memchr(hdr.v1.line, '\r', ret - 1); if (!end || end[1] != '\n') { return ERR; } (*end) = '\0'; /* V1 Header contains string: PROXY TCP4 \r\n */ Log(LOG_INFO, "INFO ( %s/%s ): Replacing: %s:%u\n", config.name, config.type, ip_address, *port); /* Find the Source IP Address */ char *s = &hdr.v1.line[11]; char *e = strchr(s, ' '); snprintf(ip_address, INET6_ADDRSTRLEN, "%s", s); /* Find the Source TCP Port */ s = e + 1; e = strchr(s, ' '); s = e + 1; *port = strtoul(s, 0, 10); Log(LOG_INFO, "INFO ( %s/%s ): with Proxy Protocol V1 containing: %s:%u\n", config.name, config.type, ip_address, *port); str_to_addr(ip_address, addr); /* Consume the proxy protocol header for real, skip header + CRLF */ size = (end + 2 - hdr.v1.line); } else if (memcmp(&hdr.v2, v2sig, 12) == 0) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol V2\n", config.name, config.type); size = (16 + ntohs(hdr.v2.len)); if (ret < size) { return ERR; } if (((hdr.v2.ver_cmd & 0xF0) == 0x20) && ((hdr.v2.ver_cmd & 0x0F) == 0x01)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol PROXY command\n", config.name, config.type); if (hdr.v2.fam == 0x11) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol TCP/IPv4\n", config.name, config.type); /* Replace IP address string originally obtained from socket */ Log(LOG_INFO, "INFO ( %s/%s ): Replacing: %s:%u\n", config.name, config.type, ip_address, *port); addr->family = AF_INET; memcpy(&addr->address.ipv4.s_addr, &hdr.v2.addr.ip4.src_addr, sizeof(hdr.v2.addr.ip4.src_addr)); *port = ntohs(hdr.v2.addr.ip4.src_port); addr_to_str(ip_address, addr); Log(LOG_INFO, "INFO ( %s/%s ): with Proxy Protocol V2 containing: %s:%u\n", config.name, config.type, ip_address, *port); } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol (TODO) Unsupported family: %u\n", config.name, config.type, hdr.v2.fam); } } else if (((hdr.v2.ver_cmd & 0xF0) == 0x20) && ((hdr.v2.ver_cmd & 0x0F) == 0x00)) { /* LOCAL Command. Health Check. Use real conection endpoints. */ Log(LOG_DEBUG, "DEBUG ( %s/%s ): Proxy Protocol LOCAL command\n", config.name, config.type); } } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Not Proxy Protocol\n", config.name, config.type); } if (size > 0) { /* Consume the proxy protocol header for real */ ret = recv(fd, &hdr, size, 0); } return 0; } /* Computing the internet checksum (RFC 1071) */ u_int16_t pm_checksum(u_int16_t *addr, int len, u_int32_t *prev_sum, int last) { int count = len; u_int32_t sum = 0; u_int16_t answer = 0; if (prev_sum) { sum = (*prev_sum); } /* Sum up 2-byte values until none or only one byte left */ while (count > 1) { sum += *(addr++); count -= 2; } /* Add left-over byte, if any */ if (count > 0) { sum += *(u_int8_t *) addr; } if (last) { /* Fold 32-bit sum into 16 bits; we lose information by doing this sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits) */ while (sum >> 16) { sum = (sum & 0xffff) + (sum >> 16); } /* Making one-complement of it */ answer = ~sum; } if (prev_sum) { (*prev_sum) = sum; } return (answer); } /* Build IPv6 UDP pseudo-header and call checksum function (Section 8.1 of RFC 2460). */ u_int16_t pm_udp6_checksum(struct ip6_hdr *ip6hdr, struct pm_udphdr *udphdr, u_char *payload, int payload_len) { u_char buf[2]; u_int32_t sum = 0; u_int16_t answer = 0; /* Copy source IP address into buf (128 bits) */ pm_checksum ((u_int16_t *)&ip6hdr->ip6_src.s6_addr, sizeof (ip6hdr->ip6_src.s6_addr), &sum, FALSE); /* Seed destination IP address (128 bits) */ pm_checksum ((u_int16_t *)&ip6hdr->ip6_dst.s6_addr, sizeof (ip6hdr->ip6_dst.s6_addr), &sum, FALSE); /* Seed UDP length (32 bits) */ pm_checksum ((u_int16_t *)&udphdr->uh_ulen, sizeof (udphdr->uh_ulen), &sum, FALSE); /* Seed next header field (8 + 8 bits) */ memset(buf, 0, sizeof(buf)); buf[1] = ip6hdr->ip6_nxt; pm_checksum ((u_int16_t *)buf, 2, &sum, FALSE); /* Seed CUDP source port (16 bits) */ pm_checksum ((u_int16_t *)&udphdr->uh_sport, sizeof (udphdr->uh_sport), &sum, FALSE); /* Seed UDP destination port (16 bits) */ pm_checksum ((u_int16_t *)&udphdr->uh_dport, sizeof (udphdr->uh_dport), &sum, FALSE); /* Seed UDP length again (16 bits) */ pm_checksum ((u_int16_t *)&udphdr->uh_ulen, sizeof (udphdr->uh_ulen), &sum, FALSE); /* Seed payload and take into account padding (16-bit boundary) */ if (payload_len % 2) { pm_checksum ((u_int16_t *)payload, (payload_len - 1), &sum, FALSE); buf[0] = payload[payload_len]; buf[1] = '\0'; answer = pm_checksum ((u_int16_t *) buf, 2, &sum, TRUE); } else { answer = pm_checksum ((u_int16_t *)payload, payload_len, &sum, TRUE); } return answer; } #ifdef WITH_GNUTLS void pm_dtls_init(pm_dtls_glob_t *dtls_globs, char *files_path) { char cafile[LONGLONGSRVBUFLEN]; char certfile[LONGLONGSRVBUFLEN], keyfile[LONGLONGSRVBUFLEN]; int ret; gnutls_global_init(); if (config.debug) { gnutls_global_set_log_function(pm_dtls_server_log); gnutls_global_set_log_level(4711); } gnutls_certificate_allocate_credentials(&dtls_globs->x509_cred); strcpy(cafile, files_path); strcat(cafile, "/"); strcat(cafile, PM_GNUTLS_CAFILE); gnutls_certificate_set_x509_trust_file(dtls_globs->x509_cred, cafile, GNUTLS_X509_FMT_PEM); strcpy(certfile, files_path); strcat(certfile, "/"); strcat(certfile, PM_GNUTLS_CERTFILE); strcpy(keyfile, files_path); strcat(keyfile, "/"); strcat(keyfile, PM_GNUTLS_KEYFILE); ret = gnutls_certificate_set_x509_key_file(dtls_globs->x509_cred, certfile, keyfile, GNUTLS_X509_FMT_PEM); if (ret < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): No DTLS certificate or key were found\n", config.name, config.type); exit_gracefully(1); } gnutls_certificate_set_known_dh_params(dtls_globs->x509_cred, GNUTLS_SEC_PARAM_MEDIUM); gnutls_priority_init2(&dtls_globs->priority_cache, "%SERVER_PRECEDENCE", NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND); gnutls_key_generate(&dtls_globs->cookie_key, GNUTLS_COOKIE_KEY_SIZE); } void pm_dtls_client_init(pm_dtls_peer_t *peer, int fd, struct sockaddr_storage *sock, socklen_t sock_len, char *verify_cert) { int ret; if (!peer) { Log(LOG_ERR, "ERROR ( %s/%s ): DTLS struct not found.\n", config.name, config.type); exit_gracefully(1); } memset(peer, 0, sizeof(pm_dtls_peer_t)); gnutls_init(&peer->session, GNUTLS_CLIENT | GNUTLS_DATAGRAM); gnutls_set_default_priority(peer->session); gnutls_credentials_set(peer->session, GNUTLS_CRD_CERTIFICATE, config.dtls_globs.x509_cred); if (verify_cert) { gnutls_server_name_set(peer->session, GNUTLS_NAME_DNS, verify_cert, strlen(verify_cert)); gnutls_session_set_verify_cert(peer->session, verify_cert, 0); } gnutls_handshake_set_timeout(peer->session, PM_DTLS_TIMEOUT_HS); // XXX gnutls_dtls_set_timeouts(peer->session, PM_DTLS_TIMEOUT_RETRANS, PM_DTLS_TIMEOUT_TOTAL); gnutls_dtls_set_mtu(peer->session, PM_DTLS_MTU); // XXX: PMTU? gnutls_transport_set_int(peer->session, fd); peer->conn.fd = fd; memcpy(&peer->conn.peer, sock, sock_len); peer->conn.peer_len = sock_len; /* starting async rx to collect DTLS feedback messages, ie. disconnects */ peer->conn.async_rx = allocate_thread_pool(1); assert(peer->conn.async_rx); send_to_pool(peer->conn.async_rx, pm_dtls_client_recv_async, peer); /* Perform the TLS handshake */ do { ret = gnutls_handshake(peer->session); peer->conn.stage = PM_DTLS_STAGE_HANDSHAKE; } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); if (ret < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): [dtls] handshake: %s\n", config.name, config.type, gnutls_strerror(ret)); pm_dtls_server_bye(peer); } else { char *desc; desc = gnutls_session_get_desc(peer->session); Log(LOG_INFO, "INFO ( %s/%s ): [dtls] handshake: %s\n", config.name, config.type, desc); gnutls_free(desc); peer->conn.stage = PM_DTLS_STAGE_UP; } } ssize_t pm_dtls_server_recv(gnutls_transport_ptr_t p, void *data, size_t len) { pm_dtls_conn_t *conn = p; struct sockaddr_storage client; socklen_t clen; int ret; memset(&client, 0, sizeof(client)); clen = sizeof(client); ret = recvfrom(conn->fd, data, len, 0, (struct sockaddr *) &client, &clen); /* validate message is received from the expected source */ ipv4_mapped_to_ipv4(&client); if (clen == conn->peer_len && !memcmp(&client, &conn->peer, clen)) { return ret; } return ERR; } ssize_t pm_dtls_server_send(gnutls_transport_ptr_t p, const void *data, size_t len) { pm_dtls_conn_t *conn = p; return sendto(conn->fd, data, len, 0, (struct sockaddr *) &conn->peer, conn->peer_len); } ssize_t pm_dtls_client_send(pm_dtls_peer_t *peer, const void *data, size_t len) { int ret = 0; if (peer->conn.stage == PM_DTLS_STAGE_UP) { ret = gnutls_record_send(peer->session, data, len); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/%s ): pm_dtls_client_send() failed: %s\n", config.name, config.type, gnutls_strerror(ret)); pm_dtls_client_bye(peer); } } return ret; } int pm_dtls_server_select(gnutls_transport_ptr_t p, unsigned int ms) { return 1; } int pm_dtls_client_recv_async(pm_dtls_peer_t *peer) { int ret = 0, buflen = PM_DTLS_MTU; char buf[buflen]; for (;;) { if (peer->conn.stage == PM_DTLS_STAGE_UP) { ret = gnutls_record_recv(peer->session, buf, buflen); if (ret == 0) { /* Peer has closed the DTLS connection */ peer->conn.do_reconnect = TRUE; Log(LOG_INFO, "INFO ( %s/%s ): [dtls] recv_async: server closed connection.\n", config.name, config.type); return ERR; } else if (ret < 0) { /* Error */ peer->conn.do_reconnect = TRUE; Log(LOG_ERR, "ERROR ( %s/%s ): [dtls] recv_async: %s\n", config.name, config.type, gnutls_strerror(ret)); return ERR; } if (ret > 0) { /* OK: noop */ } } else { sleep(1); } } return SUCCESS; } void pm_dtls_server_log(int level, const char *str) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [dtls] %d | %s", config.name, config.type, level, str); } void pm_dtls_server_bye(pm_dtls_peer_t *peer) { struct xflow_status_entry *entry; int idx; if (peer) { if (peer->conn.fd) { gnutls_bye(peer->session, GNUTLS_SHUT_WR); gnutls_deinit(peer->session); memset(peer, 0, sizeof(pm_dtls_peer_t)); } } else { for (idx = 0; idx < XFLOW_STATUS_TABLE_SZ; idx++) { entry = dtls_status_table.t[idx]; if (entry) { next: if (entry->dtls.conn.fd) { gnutls_bye(entry->dtls.session, GNUTLS_SHUT_WR); gnutls_deinit(entry->dtls.session); memset(peer, 0, sizeof(pm_dtls_peer_t)); } if (entry->next) { entry = entry->next; goto next; } } } } } void pm_dtls_client_bye(pm_dtls_peer_t *peer) { gnutls_bye(peer->session, GNUTLS_SHUT_WR); gnutls_deinit(peer->session); peer->conn.stage = PM_DTLS_STAGE_DOWN; peer->conn.do_reconnect = FALSE; if (peer->conn.async_rx) deallocate_thread_pool((thread_pool_t **) &peer->conn.async_rx); if (peer->conn.async_tx) deallocate_thread_pool((thread_pool_t **) &peer->conn.async_tx); } int pm_dtls_server_process(int dtls_sock, struct sockaddr_storage *client, socklen_t clen, u_char *dtls_packet, int len, void *st) { int hash = hash_status_table(0, (struct sockaddr *) client, XFLOW_STATUS_TABLE_SZ); xflow_status_table_t *status_table = st; struct xflow_status_entry *entry = NULL; int dtls_ret = 0, ret = 0; if (hash >= 0) { entry = search_status_table(status_table, (struct sockaddr *) client, 0, 0, hash, XFLOW_STATUS_TABLE_MAX_ENTRIES); if (entry) { if (entry->dtls.session) { /* Finalizing Hello stage */ if (entry->dtls.conn.stage == PM_DTLS_STAGE_HELLO) { dtls_ret = gnutls_dtls_cookie_verify(&config.dtls_globs.cookie_key, client, sizeof(struct sockaddr_storage), dtls_packet, len, &entry->dtls.prestate); if (dtls_ret < 0) { Log(LOG_ERR, "ERROR ( %s/core ): [dtls] hello: %s\n", config.name, gnutls_strerror(dtls_ret)); pm_dtls_server_bye(&entry->dtls); } else { gnutls_dtls_prestate_set(entry->dtls.session, &entry->dtls.prestate); entry->dtls.conn.stage = PM_DTLS_STAGE_HANDSHAKE; } } /* Handshake */ if (entry->dtls.conn.stage == PM_DTLS_STAGE_HANDSHAKE) { do { dtls_ret = gnutls_handshake(entry->dtls.session); } while (dtls_ret < 0 && !gnutls_error_is_fatal(dtls_ret)); if (dtls_ret < 0) { Log(LOG_ERR, "ERROR ( %s/core ): [dtls] handshake: %s\n", config.name, gnutls_strerror(dtls_ret)); pm_dtls_server_bye(&entry->dtls); } else { entry->dtls.conn.stage = PM_DTLS_STAGE_UP; } } /* Data */ if (entry->dtls.conn.stage == PM_DTLS_STAGE_UP) { ret = gnutls_record_recv_seq(entry->dtls.session, dtls_packet, PKT_MSG_SIZE, entry->dtls.conn.seq); if (ret < 0) { if (!gnutls_error_is_fatal(ret)) { Log(LOG_WARNING, "WARN ( %s/core ): [dtls] data: %s\n", config.name, gnutls_strerror(dtls_ret)); } else { Log(LOG_ERR, "ERROR ( %s/core ): [dtls] data: %s\n", config.name, gnutls_strerror(dtls_ret)); pm_dtls_server_bye(&entry->dtls); } } else { /* All good */ if (config.debug) { u_char hexbuf[2 * LARGEBUFLEN]; serialize_hex(dtls_packet, hexbuf, ret); Log(LOG_DEBUG, "DEBUG ( %s/core ): [dtls] data received: seq=%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x len=%d hex=%s\n", config.name, entry->dtls.conn.seq[0], entry->dtls.conn.seq[1], entry->dtls.conn.seq[2], entry->dtls.conn.seq[3], entry->dtls.conn.seq[4], entry->dtls.conn.seq[5], entry->dtls.conn.seq[6], entry->dtls.conn.seq[7], ret, hexbuf); } /* EOF */ if (ret == 0) { pm_dtls_server_bye(&entry->dtls); } } } if (entry->dtls.conn.stage == PM_DTLS_STAGE_UP) { return ret; } } else { gnutls_init(&entry->dtls.session, GNUTLS_SERVER | GNUTLS_DATAGRAM); gnutls_handshake_set_timeout(entry->dtls.session, PM_DTLS_TIMEOUT_HS); // XXX gnutls_dtls_set_timeouts(entry->dtls.session, PM_DTLS_TIMEOUT_RETRANS, PM_DTLS_TIMEOUT_TOTAL); gnutls_dtls_set_mtu(entry->dtls.session, PM_DTLS_MTU); // XXX: PMTU? gnutls_priority_set(entry->dtls.session, config.dtls_globs.priority_cache); gnutls_credentials_set(entry->dtls.session, GNUTLS_CRD_CERTIFICATE, config.dtls_globs.x509_cred); entry->dtls.conn.fd = dtls_sock; memcpy(&entry->dtls.conn.peer, client, clen); entry->dtls.conn.peer_len = clen; gnutls_transport_set_ptr(entry->dtls.session, &entry->dtls.conn); gnutls_transport_set_pull_function(entry->dtls.session, pm_dtls_server_recv); gnutls_transport_set_pull_timeout_function(entry->dtls.session, pm_dtls_server_select); gnutls_transport_set_push_function(entry->dtls.session, pm_dtls_server_send); /* Sending Hello with cookie */ dtls_ret = gnutls_dtls_cookie_send(&config.dtls_globs.cookie_key, client, sizeof(struct sockaddr_storage), &entry->dtls.prestate, (gnutls_transport_ptr_t) &entry->dtls.conn, pm_dtls_server_send); if (dtls_ret < 0) { Log(LOG_ERR, "ERROR ( %s/core ): [dtls] cookie: %s\n", config.name, gnutls_strerror(dtls_ret)); pm_dtls_server_bye(&entry->dtls); } else { entry->dtls.conn.stage = PM_DTLS_STAGE_HELLO; } /* discard peeked data */ recv(dtls_sock, (unsigned char *) dtls_packet, PKT_MSG_SIZE, 0); } } } return FALSE; } #endif pmacct-1.7.8/src/amqp_common.c0000644000175000017500000003112314354105275015253 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_common.h" #include "amqp_common.h" /* Global variables */ struct p_amqp_host amqpp_amqp_host; struct p_amqp_host bgp_daemon_msglog_amqp_host; struct p_amqp_host bmp_daemon_msglog_amqp_host; struct p_amqp_host sfacctd_counter_amqp_host; struct p_amqp_host telemetry_daemon_msglog_amqp_host; char rabbitmq_user[] = "guest"; char rabbitmq_pwd[] = "guest"; char default_amqp_exchange[] = "pmacct"; char default_amqp_exchange_type[] = "direct"; char default_amqp_routing_key[] = "acct"; char default_amqp_host[] = "127.0.0.1"; char default_amqp_vhost[] = "/"; /* Functions */ void p_amqp_init_host(struct p_amqp_host *amqp_host) { if (amqp_host) { memset(amqp_host, 0, sizeof(struct p_amqp_host)); p_amqp_set_frame_max(amqp_host, AMQP_DEFAULT_FRAME_SIZE); p_amqp_set_heartbeat_interval(amqp_host, AMQP_DEFAULT_HEARTBEAT); P_broker_timers_set_retry_interval(&amqp_host->btimers, AMQP_DEFAULT_RETRY); } } void p_amqp_set_user(struct p_amqp_host *amqp_host, char *user) { if (amqp_host) amqp_host->user = user; } void p_amqp_set_passwd(struct p_amqp_host *amqp_host, char *passwd) { if (amqp_host) amqp_host->passwd = passwd; } void p_amqp_set_exchange(struct p_amqp_host *amqp_host, char *exchange) { if (amqp_host) amqp_host->exchange = exchange; } void p_amqp_set_routing_key(struct p_amqp_host *amqp_host, char *routing_key) { if (amqp_host) amqp_host->routing_key = routing_key; } void p_amqp_unset_routing_key(struct p_amqp_host *amqp_host) { if (amqp_host) amqp_host->routing_key = NULL; } char *p_amqp_get_routing_key(struct p_amqp_host *amqp_host) { if (amqp_host) return amqp_host->routing_key; return NULL; } void p_amqp_init_routing_key_rr(struct p_amqp_host *amqp_host) { if (amqp_host) memset(&amqp_host->rk_rr, 0, sizeof(struct p_table_rr)); } void p_amqp_set_routing_key_rr(struct p_amqp_host *amqp_host, int rk_rr) { if (amqp_host) amqp_host->rk_rr.max = rk_rr; } int p_amqp_get_routing_key_rr(struct p_amqp_host *amqp_host) { if (amqp_host) return amqp_host->rk_rr.max; return FALSE; } void p_amqp_set_exchange_type(struct p_amqp_host *amqp_host, char *exchange_type) { if (amqp_host && exchange_type) { lower_string(exchange_type); amqp_host->exchange_type = exchange_type; } } void p_amqp_set_host(struct p_amqp_host *amqp_host, char *host) { if (amqp_host) amqp_host->host = host; } void p_amqp_set_vhost(struct p_amqp_host *amqp_host, char *vhost) { if (amqp_host) amqp_host->vhost = vhost; } void p_amqp_set_frame_max(struct p_amqp_host *amqp_host, u_int32_t opt) { if (amqp_host) { if (opt > PM_AMQP_MIN_FRAME_SIZE) amqp_host->frame_max = opt; } } void p_amqp_set_heartbeat_interval(struct p_amqp_host *amqp_host, int opt) { if (amqp_host) { amqp_host->heartbeat_interval = opt; } } void p_amqp_set_persistent_msg(struct p_amqp_host *amqp_host, int opt) { if (amqp_host) amqp_host->persistent_msg = opt; } void p_amqp_set_content_type_json(struct p_amqp_host *amqp_host) { if (amqp_host) { amqp_host->msg_props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG; amqp_host->msg_props.content_type = amqp_cstring_bytes("application/json"); } } void p_amqp_set_content_type_binary(struct p_amqp_host *amqp_host) { if (amqp_host) { amqp_host->msg_props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG; amqp_host->msg_props.content_type = amqp_cstring_bytes("application/octet-stream"); } } int p_amqp_get_sockfd(struct p_amqp_host *amqp_host) { if (amqp_host) { if (!P_broker_timers_get_last_fail(&amqp_host->btimers)) return amqp_get_sockfd(amqp_host->conn); } return ERR; } void p_amqp_get_version() { printf("rabbimq-c %s\n", amqp_version()); } int p_amqp_connect_to_publish(struct p_amqp_host *amqp_host) { amqp_host->conn = amqp_new_connection(); amqp_host->socket = amqp_tcp_socket_new(amqp_host->conn); if (!amqp_host->socket) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_connect_to_publish(): no socket\n", config.name, config.type); p_amqp_close(amqp_host, TRUE); return ERR; } amqp_host->status = amqp_socket_open(amqp_host->socket, amqp_host->host, 5672 /* default port */); if (amqp_host->status != AMQP_STATUS_OK) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_connect_to_publish(): unable to open socket\n", config.name, config.type); p_amqp_close(amqp_host, TRUE); return ERR; } amqp_host->ret = amqp_login(amqp_host->conn, amqp_host->vhost, 0, amqp_host->frame_max, amqp_host->heartbeat_interval, AMQP_SASL_METHOD_PLAIN, amqp_host->user, amqp_host->passwd); if (amqp_host->ret.reply_type != AMQP_RESPONSE_NORMAL) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_connect_to_publish(): login\n", config.name, config.type); p_amqp_close(amqp_host, TRUE); return ERR; } amqp_channel_open(amqp_host->conn, 1); amqp_host->ret = amqp_get_rpc_reply(amqp_host->conn); if (amqp_host->ret.reply_type != AMQP_RESPONSE_NORMAL) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_connect_to_publish(): unable to open channel\n", config.name, config.type); p_amqp_close(amqp_host, TRUE); return ERR; } if (amqp_host->persistent_msg) amqp_exchange_declare(amqp_host->conn, 1, amqp_cstring_bytes(amqp_host->exchange), amqp_cstring_bytes(amqp_host->exchange_type), 0, 1 /* durable */, 0, 0, amqp_empty_table); else amqp_exchange_declare(amqp_host->conn, 1, amqp_cstring_bytes(amqp_host->exchange), amqp_cstring_bytes(amqp_host->exchange_type), 0, 0, 0, 0, amqp_empty_table); amqp_host->ret = amqp_get_rpc_reply(amqp_host->conn); if (amqp_host->ret.reply_type != AMQP_RESPONSE_NORMAL) { const char *err_msg; switch (amqp_host->ret.reply_type) { case AMQP_RESPONSE_NONE: err_msg = "Missing RPC reply type"; break; case AMQP_RESPONSE_LIBRARY_EXCEPTION: err_msg = "Client library exception"; break; case AMQP_RESPONSE_SERVER_EXCEPTION: err_msg = "Server generated an exception"; break; default: err_msg = "Unknown"; break; } Log(LOG_ERR, "ERROR ( %s/%s ): Handshake with RabbitMQ failed: %s\n", config.name, config.type, err_msg); p_amqp_close(amqp_host, TRUE); return ERR; } // XXX: to be removed amqp_host->msg_props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG; amqp_host->msg_props.content_type = amqp_cstring_bytes("application/json"); if (amqp_host->persistent_msg) { amqp_host->msg_props._flags |= AMQP_BASIC_DELIVERY_MODE_FLAG; amqp_host->msg_props.delivery_mode = 2; /* persistent delivery */ } Log(LOG_DEBUG, "DEBUG ( %s/%s ): Connection successful to RabbitMQ: p_amqp_connect_to_publish()\n", config.name, config.type); P_broker_timers_unset_last_fail(&amqp_host->btimers); return SUCCESS; } int p_amqp_publish_string(struct p_amqp_host *amqp_host, char *json_str) { if (p_amqp_is_alive(amqp_host) == ERR) { p_amqp_close(amqp_host, TRUE); return ERR; } amqp_host->status = amqp_basic_publish(amqp_host->conn, 1, amqp_cstring_bytes(amqp_host->exchange), amqp_cstring_bytes(amqp_host->routing_key), 0, 0, &amqp_host->msg_props, amqp_cstring_bytes(json_str)); if (amqp_host->status) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_publish_string() [E=%s RK=%s DM=%u]\n", config.name, config.type, amqp_host->exchange, amqp_host->routing_key, amqp_host->msg_props.delivery_mode); p_amqp_close(amqp_host, TRUE); return ERR; } else { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): publishing to RabbitMQ: p_amqp_publish_string() [E=%s RK=%s DM=%u]: %s\n", config.name, config.type, amqp_host->exchange, amqp_host->routing_key, amqp_host->msg_props.delivery_mode, json_str); } return SUCCESS; } int p_amqp_publish_binary(struct p_amqp_host *amqp_host, void *data, u_int32_t data_len) { amqp_bytes_t pdata; if (p_amqp_is_alive(amqp_host) == ERR) { p_amqp_close(amqp_host, TRUE); return ERR; } memset(&pdata, 0, sizeof(pdata)); pdata.len = data_len; pdata.bytes = data; amqp_host->status = amqp_basic_publish(amqp_host->conn, 1, amqp_cstring_bytes(amqp_host->exchange), amqp_cstring_bytes(amqp_host->routing_key), 0, 0, &amqp_host->msg_props, pdata); if (amqp_host->status) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_publish_binary() [E=%s RK=%s DM=%u]\n", config.name, config.type, amqp_host->exchange, amqp_host->routing_key, amqp_host->msg_props.delivery_mode); p_amqp_close(amqp_host, TRUE); return ERR; } else { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): publishing to RabbitMQ: p_amqp_publish_binary() [E=%s RK=%s DM=%u]\n", config.name, config.type, amqp_host->exchange, amqp_host->routing_key, amqp_host->msg_props.delivery_mode); } return SUCCESS; } void p_amqp_close(struct p_amqp_host *amqp_host, int set_fail) { if (amqp_host->conn) { if (amqp_get_socket(amqp_host->conn)) amqp_connection_close(amqp_host->conn, AMQP_REPLY_SUCCESS); if (set_fail) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to RabbitMQ: p_amqp_close()\n", config.name, config.type); P_broker_timers_set_last_fail(&amqp_host->btimers, time(NULL)); } amqp_destroy_connection(amqp_host->conn); amqp_host->conn = NULL; } } int p_amqp_is_alive(struct p_amqp_host *amqp_host) { if (amqp_host->status == AMQP_STATUS_OK && amqp_host->conn && (amqp_get_sockfd(amqp_host->conn) >= 0)) return SUCCESS; else return ERR; } #if defined WITH_JANSSON int write_and_free_json_amqp(void *amqp_log, void *obj) { char *orig_amqp_routing_key = NULL, dyn_amqp_routing_key[SRVBUFLEN]; struct p_amqp_host *alog = (struct p_amqp_host *) amqp_log; int ret = ERR; char *tmpbuf = NULL; json_t *json_obj = (json_t *) obj; tmpbuf = json_dumps(json_obj, JSON_PRESERVE_ORDER); json_decref(json_obj); if (tmpbuf) { if (alog->rk_rr.max) { orig_amqp_routing_key = p_amqp_get_routing_key(alog); P_handle_table_dyn_rr(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &alog->rk_rr); p_amqp_set_routing_key(alog, dyn_amqp_routing_key); } ret = p_amqp_publish_string(alog, tmpbuf); free(tmpbuf); if (alog->rk_rr.max) p_amqp_set_routing_key(alog, orig_amqp_routing_key); } return ret; } #else int write_and_free_json_amqp(void *amqp_log, void *obj) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): write_and_free_json_amqp(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); } #endif int write_binary_amqp(void *amqp_log, void *obj, size_t len) { char *orig_amqp_routing_key = NULL, dyn_amqp_routing_key[SRVBUFLEN]; struct p_amqp_host *alog = (struct p_amqp_host *) amqp_log; int ret = ERR; if (obj && len) { if (alog->rk_rr.max) { orig_amqp_routing_key = p_amqp_get_routing_key(alog); P_handle_table_dyn_rr(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &alog->rk_rr); p_amqp_set_routing_key(alog, dyn_amqp_routing_key); } ret = p_amqp_publish_binary(alog, obj, len); if (alog->rk_rr.max) p_amqp_set_routing_key(alog, orig_amqp_routing_key); } return ret; } int write_string_amqp(void *amqp_log, char *obj) { char *orig_amqp_routing_key = NULL, dyn_amqp_routing_key[SRVBUFLEN]; struct p_amqp_host *alog = (struct p_amqp_host *) amqp_log; int ret = ERR; if (obj) { if (alog->rk_rr.max) { orig_amqp_routing_key = p_amqp_get_routing_key(alog); P_handle_table_dyn_rr(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &alog->rk_rr); p_amqp_set_routing_key(alog, dyn_amqp_routing_key); } ret = p_amqp_publish_string(alog, obj); if (alog->rk_rr.max) p_amqp_set_routing_key(alog, orig_amqp_routing_key); } return ret; } pmacct-1.7.8/src/pkt_handlers.c0000644000175000017500000073400014354105275015427 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "nfacctd.h" #include "sflow.h" #include "sfacctd.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "bgp/bgp.h" #include "isis/prefix.h" #include "isis/table.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif //Global variables struct channels_list_entry channels_list[MAX_N_PLUGINS]; pkt_handler phandler[N_PRIMITIVES]; /* functions */ void warn_unsupported_packet_handler(u_int64_t primitive, u_int64_t tool) { char *primitive_str = NULL, *tool_str = NULL; primitive_str = lookup_id_to_string_struct(_primitives_map, primitive); tool_str = lookup_id_to_string_struct(_tools_map, tool); if (primitive_str) { if (tool_str) { Log(LOG_WARNING, "WARN ( %s/%s ): primitive '%s' is not supported by '%s'.\n", config.name, config.type, primitive_str, tool_str); } else { Log(LOG_WARNING, "WARN ( %s/%s ): primitive '%s' is not supported by the tool in use.\n", config.name, config.type, primitive_str); } } else { if (tool_str) { Log(LOG_WARNING, "WARN ( %s/%s ): primitive %" PRIu64 "is not supported by '%s'.\n", config.name, config.type, primitive, tool_str); } else { Log(LOG_WARNING, "WARN ( %s/%s ): primitive %" PRIu64 "is not supported by the tool in use.\n", config.name, config.type, primitive); } } } void evaluate_packet_handlers() { int primitives = 0, index = 0; while (channels_list[index].aggregation) { primitives = 0; memset(&channels_list[index].phandler, 0, N_PRIMITIVES*sizeof(pkt_handler)); #if defined (HAVE_L2) if (channels_list[index].aggregation & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_mac_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_mac_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_mac_handler; primitives++; } if (channels_list[index].aggregation & (COUNT_DST_MAC|COUNT_SUM_MAC)) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_mac_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_mac_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_mac_handler; primitives++; } if (channels_list[index].aggregation & COUNT_VLAN) { if (config.tmp_vlan_legacy) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = vlan_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_vlan_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_vlan_handler; primitives++; } else { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = vlan_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_in_vlan_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_in_vlan_handler; primitives++; } } if (channels_list[index].aggregation_2 & COUNT_OUT_VLAN) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_OUT_VLAN, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_out_vlan_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_out_vlan_handler; primitives++; } if (channels_list[index].aggregation & COUNT_COS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = cos_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_cos_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_cos_handler; primitives++; } if (channels_list[index].aggregation & COUNT_ETHERTYPE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = etype_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_etype_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_etype_handler; primitives++; } #endif if (channels_list[index].aggregation & (COUNT_SRC_HOST|COUNT_SRC_NET|COUNT_SUM_HOST|COUNT_SUM_NET)) { /* always copy the host */ if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_host_handler; primitives++; /* optionally copy mask */ if (channels_list[index].aggregation & (COUNT_SRC_NET|COUNT_SUM_NET)) { if (!(channels_list[index].aggregation & COUNT_SRC_NMASK)) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_nmask_handler; else primitives--; /* Just in case */ primitives++; } } } } if (channels_list[index].aggregation & (COUNT_DST_HOST|COUNT_DST_NET|COUNT_SUM_HOST|COUNT_SUM_NET)) { /* always copy the host */ if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_host_handler; primitives++; /* optionally copy mask */ if (channels_list[index].aggregation & (COUNT_DST_NET|COUNT_SUM_NET)) { if (!(channels_list[index].aggregation & COUNT_DST_NMASK)) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_nmask_handler; else primitives--; /* Just in case */ primitives++; } } } } if (channels_list[index].aggregation & COUNT_SRC_NMASK) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_nmask_handler; else primitives--; /* Just in case */ primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & (NF_NET_COMPAT|NF_NET_NEW)) { if (!(channels_list[index].aggregation & (COUNT_SRC_HOST|COUNT_SRC_NET|COUNT_SUM_HOST|COUNT_SUM_NET))) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_host_handler; primitives++; } } } if (channels_list[index].aggregation & COUNT_DST_NMASK) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_nmask_handler; else primitives--; /* Just in case */ primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & (NF_NET_COMPAT|NF_NET_NEW)) { if (!(channels_list[index].aggregation & (COUNT_DST_HOST|COUNT_DST_NET|COUNT_SUM_HOST|COUNT_SUM_NET))) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_host_handler; primitives++; } } } if (channels_list[index].aggregation & (COUNT_SRC_AS|COUNT_SUM_AS)) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_as_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_as_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_NEW) { if (!(channels_list[index].aggregation & (COUNT_SRC_HOST|COUNT_SRC_NET|COUNT_SUM_HOST|COUNT_SUM_NET))) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_host_handler; primitives++; } if (!(channels_list[index].aggregation & COUNT_SRC_NMASK)) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_src_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_nmask_handler; else primitives--; /* Just in case */ primitives++; } } } } if (channels_list[index].aggregation & (COUNT_DST_AS|COUNT_SUM_AS)) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_as_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_as_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_NEW) { if (!(channels_list[index].aggregation & (COUNT_DST_HOST|COUNT_DST_NET|COUNT_SUM_HOST|COUNT_SUM_NET))) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_host_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_host_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_host_handler; primitives++; } if (!(channels_list[index].aggregation & COUNT_DST_NMASK)) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_dst_nmask_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_nmask_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_nmask_handler; else primitives--; /* Just in case */ primitives++; } } } } if (channels_list[index].aggregation & COUNT_PEER_SRC_IP) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_PEER_SRC_IP, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_peer_src_ip_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_peer_src_ip_handler; primitives++; } if (channels_list[index].aggregation & COUNT_PEER_DST_IP) { if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_BGP) { channels_list[index].phandler[primitives] = bgp_peer_dst_ip_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_IGP) { channels_list[index].phandler[primitives] = igp_peer_dst_ip_handler; primitives++; } if (channels_list[index].plugin->cfg.nfacctd_net & NF_NET_KEEP) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_peer_dst_ip_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_peer_dst_ip_handler; else primitives--; /* Just in case */ primitives++; } } if (channels_list[index].aggregation & COUNT_AS_PATH) { if (config.acct_type == ACCT_SF) { if (config.nfacctd_as & NF_AS_KEEP) { channels_list[index].phandler[primitives] = SF_as_path_handler; primitives++; } } } if (channels_list[index].aggregation & COUNT_PEER_SRC_AS) { if (config.acct_type == ACCT_NF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP && config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_KEEP) { if (channels_list[index].plugin->cfg.nfprobe_peer_as) { channels_list[index].phandler[primitives] = NF_src_as_handler; primitives++; } else { channels_list[index].phandler[primitives] = NF_peer_src_as_handler; primitives++; } } } else if (config.acct_type == ACCT_SF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP && config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_KEEP) { if (channels_list[index].plugin->cfg.nfprobe_peer_as) { channels_list[index].phandler[primitives] = SF_src_as_handler; primitives++; } else { channels_list[index].phandler[primitives] = SF_peer_src_as_handler; primitives++; } } } } if (channels_list[index].aggregation & COUNT_PEER_DST_AS) { if (config.acct_type == ACCT_NF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { if (channels_list[index].plugin->cfg.nfprobe_peer_as) { channels_list[index].phandler[primitives] = NF_dst_as_handler; primitives++; } else { channels_list[index].phandler[primitives] = NF_peer_dst_as_handler; primitives++; } } } else if (config.acct_type == ACCT_SF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { if (channels_list[index].plugin->cfg.nfprobe_peer_as) { channels_list[index].phandler[primitives] = SF_dst_as_handler; primitives++; } else { channels_list[index].phandler[primitives] = SF_peer_dst_as_handler; primitives++; } } } } if (channels_list[index].aggregation & COUNT_LOCAL_PREF) { if (config.acct_type == ACCT_SF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { channels_list[index].phandler[primitives] = SF_local_pref_handler; primitives++; } } } if (channels_list[index].aggregation & COUNT_STD_COMM) { if (config.acct_type == ACCT_SF) { if (channels_list[index].plugin->cfg.nfacctd_as & NF_AS_KEEP) { channels_list[index].phandler[primitives] = SF_std_comms_handler; primitives++; } } } if ((channels_list[index].aggregation & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_LOCAL_PREF|COUNT_MED| COUNT_AS_PATH|COUNT_PEER_DST_AS|COUNT_SRC_AS_PATH|COUNT_SRC_STD_COMM| COUNT_SRC_EXT_COMM|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF|COUNT_SRC_AS| COUNT_DST_AS|COUNT_PEER_SRC_AS) || channels_list[index].aggregation_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM|COUNT_SRC_ROA|COUNT_DST_ROA)) && channels_list[index].plugin->cfg.nfacctd_as & NF_AS_BGP) { if (config.acct_type == ACCT_PM && (config.bgp_daemon || config.bmp_daemon)) { if (channels_list[index].plugin->type.id == PLUGIN_ID_SFPROBE) { channels_list[index].phandler[primitives] = sfprobe_bgp_ext_handler; } else if (channels_list[index].plugin->type.id == PLUGIN_ID_NFPROBE) { channels_list[index].phandler[primitives] = nfprobe_bgp_ext_handler; } else { channels_list[index].phandler[primitives] = bgp_ext_handler; } primitives++; } else if (config.acct_type == ACCT_NF && (config.bgp_daemon || config.bmp_daemon)) { channels_list[index].phandler[primitives] = bgp_ext_handler; primitives++; } else if (config.acct_type == ACCT_SF && (config.bgp_daemon || config.bmp_daemon)) { channels_list[index].phandler[primitives] = bgp_ext_handler; primitives++; } } if (channels_list[index].aggregation & COUNT_MPLS_VPN_RD) { if (config.nfacctd_flow_to_rd_map) { channels_list[index].phandler[primitives] = mpls_vpn_rd_frommap_handler; primitives++; } if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_mpls_vpn_id_handler; primitives++; channels_list[index].phandler[primitives] = NF_mpls_vpn_rd_handler; primitives++; } } if (channels_list[index].aggregation_2 & COUNT_MPLS_PW_ID) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_MPLS_PW_ID, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_mpls_pw_id_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_mpls_pw_id_handler; primitives++; } if (channels_list[index].aggregation & COUNT_PEER_SRC_AS) { if (config.acct_type == ACCT_PM && config.bgp_daemon) { if (config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_peer_src_as_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_NF) { if (config.bgp_daemon && config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_peer_src_as_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_SF) { if (config.bgp_daemon && config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_peer_src_as_frommap_handler; primitives++; } } } if (channels_list[index].aggregation & COUNT_SRC_LOCAL_PREF) { if (config.acct_type == ACCT_PM && config.bgp_daemon) { if (config.bgp_daemon_src_local_pref_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_local_pref_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_NF && config.bgp_daemon) { if (config.bgp_daemon_src_local_pref_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_local_pref_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_SF && config.bgp_daemon) { if (config.bgp_daemon_src_local_pref_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_local_pref_frommap_handler; primitives++; } } } if (channels_list[index].aggregation & COUNT_SRC_MED) { if (config.acct_type == ACCT_PM && config.bgp_daemon) { if (config.bgp_daemon_src_med_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_med_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_NF && config.bgp_daemon) { if (config.bgp_daemon_src_med_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_med_frommap_handler; primitives++; } } else if (config.acct_type == ACCT_SF && config.bgp_daemon) { if (config.bgp_daemon_src_med_type & BGP_SRC_PRIMITIVES_MAP) { channels_list[index].phandler[primitives] = bgp_src_med_frommap_handler; primitives++; } } } if (channels_list[index].aggregation & (COUNT_SRC_PORT|COUNT_SUM_PORT)) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = src_port_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_src_port_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_src_port_handler; primitives++; } if (channels_list[index].aggregation & (COUNT_DST_PORT|COUNT_SUM_PORT)) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = dst_port_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_dst_port_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_dst_port_handler; primitives++; } if (channels_list[index].aggregation & COUNT_IP_TOS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = ip_tos_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_ip_tos_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_ip_tos_handler; primitives++; } if (channels_list[index].aggregation & COUNT_IP_PROTO) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = ip_proto_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_ip_proto_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_ip_proto_handler; primitives++; } if (channels_list[index].aggregation & COUNT_TCPFLAGS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tcp_flags_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_tcp_flags_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tcp_flags_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_FWD_STATUS) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_FWD_STATUS, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_fwd_status_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_FWD_STATUS, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation & COUNT_FLOWS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = flows_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_flows_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_flows_handler; primitives++; } if (channels_list[index].aggregation & COUNT_CLASS) { if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_class_handler; else primitives--; primitives++; } #if defined (WITH_NDPI) if (channels_list[index].aggregation_2 & COUNT_NDPI_CLASS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = ndpi_class_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_ndpi_class_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_ndpi_class_handler; primitives++; } #endif if (channels_list[index].aggregation & COUNT_IN_IFACE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = in_iface_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_in_iface_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_in_iface_handler; primitives++; } if (channels_list[index].aggregation & COUNT_OUT_IFACE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = out_iface_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_out_iface_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_out_iface_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_SAMPLING_RATE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = sampling_rate_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_sampling_rate_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_sampling_rate_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_SAMPLING_DIRECTION) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = sampling_direction_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_sampling_direction_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = SF_sampling_direction_handler; primitives++; } #if defined (WITH_GEOIP) if (channels_list[index].aggregation_2 & COUNT_SRC_HOST_COUNTRY) { channels_list[index].phandler[primitives] = src_host_country_geoip_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_DST_HOST_COUNTRY) { channels_list[index].phandler[primitives] = dst_host_country_geoip_handler; primitives++; } #endif #if defined (WITH_GEOIPV2) pm_geoipv2_init(); if (channels_list[index].aggregation_2 & (COUNT_SRC_HOST_COUNTRY|COUNT_SRC_HOST_POCODE|COUNT_SRC_HOST_COORDS) /* other GeoIP primitives here */) { channels_list[index].phandler[primitives] = src_host_geoipv2_lookup_handler; primitives++; if (channels_list[index].aggregation_2 & COUNT_SRC_HOST_COUNTRY) { channels_list[index].phandler[primitives] = src_host_country_geoipv2_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_SRC_HOST_POCODE) { channels_list[index].phandler[primitives] = src_host_pocode_geoipv2_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_SRC_HOST_COORDS) { channels_list[index].phandler[primitives] = src_host_coords_geoipv2_handler; primitives++; } } if (channels_list[index].aggregation_2 & (COUNT_DST_HOST_COUNTRY|COUNT_DST_HOST_POCODE|COUNT_DST_HOST_COORDS) /* other GeoIP primitives here */) { channels_list[index].phandler[primitives] = dst_host_geoipv2_lookup_handler; primitives++; if (channels_list[index].aggregation_2 & COUNT_DST_HOST_COUNTRY) { channels_list[index].phandler[primitives] = dst_host_country_geoipv2_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_DST_HOST_POCODE) { channels_list[index].phandler[primitives] = dst_host_pocode_geoipv2_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_DST_HOST_COORDS) { channels_list[index].phandler[primitives] = dst_host_coords_geoipv2_handler; primitives++; } } #endif if (channels_list[index].aggregation_2 & COUNT_POST_NAT_SRC_HOST) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_SRC_HOST, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_post_nat_src_host_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_SRC_HOST, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_POST_NAT_DST_HOST) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_DST_HOST, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_post_nat_dst_host_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_SRC_HOST, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_POST_NAT_SRC_PORT) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_SRC_PORT, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_post_nat_src_port_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_SRC_PORT, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_POST_NAT_DST_PORT) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_DST_PORT, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_post_nat_dst_port_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_POST_NAT_DST_PORT, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_NAT_EVENT) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_NAT_EVENT, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_nat_event_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_NAT_EVENT, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_FW_EVENT) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_FW_EVENT, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_fw_event_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_FW_EVENT, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_SRC_MAC) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_src_mac_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_SRC_MAC, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_src_mac_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_DST_MAC) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_dst_mac_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_DST_MAC, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_dst_mac_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_SRC_HOST) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_src_host_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_SRC_HOST, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_src_host_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_DST_HOST) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_dst_host_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_DST_HOST, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_dst_host_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_IP_PROTO) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_ip_proto_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_IP_PROTO, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_ip_proto_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_IP_TOS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_ip_tos_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_IP_TOS, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_ip_tos_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_SRC_PORT) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_src_port_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_SRC_PORT, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_src_port_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_DST_PORT) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_dst_port_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_DST_PORT, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_dst_port_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TUNNEL_TCPFLAGS) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = tunnel_tcp_flags_handler; else if (config.acct_type == ACCT_NF) { warn_unsupported_packet_handler(COUNT_INT_TUNNEL_TCPFLAGS, ACCT_NF); primitives--; } else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tunnel_tcp_flags_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_VXLAN) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = vxlan_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_vxlan_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_vxlan_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_MPLS_LABEL_STACK) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = mpls_label_stack_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_mpls_label_stack_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_mpls_label_stack_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_MPLS_LABEL_TOP) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = mpls_label_top_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_mpls_label_top_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_mpls_label_top_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_MPLS_LABEL_BOTTOM) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = mpls_label_bottom_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_mpls_label_bottom_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_mpls_label_bottom_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_TIMESTAMP_START) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = timestamp_start_handler; // XXX: to be removed else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_timestamp_start_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_TIMESTAMP_START, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_TIMESTAMP_END) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_TIMESTAMP_END, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_timestamp_end_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_TIMESTAMP_END, ACCT_SF); primitives--; } primitives++; } if (channels_list[index].aggregation_2 & COUNT_TIMESTAMP_ARRIVAL) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = timestamp_arrival_handler; else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_timestamp_arrival_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_timestamp_arrival_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_EXPORT_PROTO_SEQNO) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_EXPORT_PROTO_SEQNO, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_sequence_number_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_sequence_number_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_EXPORT_PROTO_VERSION) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_EXPORT_PROTO_VERSION, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_version_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_version_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_EXPORT_PROTO_SYSID) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_EXPORT_PROTO_SYSID, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_sysid_handler; else if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_sysid_handler; primitives++; } if (channels_list[index].aggregation_2 & COUNT_EXPORT_PROTO_TIME) { if (config.acct_type == ACCT_PM) { warn_unsupported_packet_handler(COUNT_INT_EXPORT_PROTO_TIME, ACCT_PM); primitives--; } else if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_timestamp_export_handler; else if (config.acct_type == ACCT_SF) { warn_unsupported_packet_handler(COUNT_INT_EXPORT_PROTO_TIME, ACCT_SF); primitives--; } primitives++; } /* if cpptrs.num > 0 one or multiple custom primitives are defined */ if (channels_list[index].plugin->cfg.cpptrs.num) { if (config.acct_type == ACCT_PM) { channels_list[index].phandler[primitives] = custom_primitives_handler; primitives++; } else if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_custom_primitives_handler; primitives++; } else if (config.acct_type == ACCT_SF) { channels_list[index].phandler[primitives] = SF_custom_primitives_handler; primitives++; } } if (channels_list[index].aggregation & COUNT_COUNTERS) { if (config.acct_type == ACCT_PM) { channels_list[index].phandler[primitives] = counters_handler; primitives++; if (config.nfacctd_time == NF_TIME_NEW) channels_list[index].phandler[primitives] = time_new_handler; else channels_list[index].phandler[primitives] = time_pcap_handler; /* default */ if (channels_list[index].s.rate) { primitives++; if (channels_list[index].plugin->type.id == PLUGIN_ID_SFPROBE) { channels_list[index].phandler[primitives] = sfprobe_sampling_handler; } else { channels_list[index].phandler[primitives] = sampling_handler; } } if (config.sfacctd_renormalize && (config.ext_sampling_rate || channels_list[index].s.rate)) { primitives++; channels_list[index].phandler[primitives] = counters_renormalize_handler; } } else if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_counters_handler; primitives++; if (config.nfacctd_time == NF_TIME_SECS) channels_list[index].phandler[primitives] = NF_time_secs_handler; else if (config.nfacctd_time == NF_TIME_NEW) channels_list[index].phandler[primitives] = NF_time_new_handler; else channels_list[index].phandler[primitives] = NF_time_msecs_handler; /* default */ if (config.sfacctd_renormalize) { primitives++; if (config.ext_sampling_rate) { channels_list[index].phandler[primitives] = counters_renormalize_handler; } else if (config.sampling_map) { channels_list[index].phandler[primitives] = NF_counters_map_renormalize_handler; /* Fallback to advertised sampling rate if needed */ primitives++; channels_list[index].phandler[primitives] = NF_counters_renormalize_handler; } else { channels_list[index].phandler[primitives] = NF_counters_renormalize_handler; } } } else if (config.acct_type == ACCT_SF) { channels_list[index].phandler[primitives] = SF_counters_handler; if (config.sfacctd_renormalize) { primitives++; if (config.ext_sampling_rate) { channels_list[index].phandler[primitives] = counters_renormalize_handler; } else if (config.sampling_map) { channels_list[index].phandler[primitives] = SF_counters_map_renormalize_handler; /* Fallback to advertised sampling rate if needed */ primitives++; channels_list[index].phandler[primitives] = SF_counters_renormalize_handler; } else { channels_list[index].phandler[primitives] = SF_counters_renormalize_handler; } } } primitives++; } if (channels_list[index].plugin->type.id == PLUGIN_ID_NFPROBE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = nfprobe_extras_handler; else primitives--; /* This case is filtered out at startup: getting out silently */ primitives++; } if (config.acct_type == ACCT_PM || config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { if (channels_list[index].aggregation & COUNT_TAG) { /* we infer 'pre_tag_map' from configuration because it's global */ if (channels_list[index].plugin->cfg.pre_tag_map) { channels_list[index].phandler[primitives] = pre_tag_handler; primitives++; } if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_cust_tag_handler; primitives++; } else if (config.acct_type == ACCT_SF) { channels_list[index].phandler[primitives] = SF_tag_handler; primitives++; } if (channels_list[index].tag) { channels_list[index].phandler[primitives] = post_tag_handler; primitives++; } } } if (config.acct_type == ACCT_PM || config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { if (channels_list[index].aggregation & COUNT_TAG2) { if (channels_list[index].plugin->cfg.pre_tag_map) { channels_list[index].phandler[primitives] = pre_tag2_handler; primitives++; } if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_cust_tag2_handler; primitives++; } else if (config.acct_type == ACCT_SF) { channels_list[index].phandler[primitives] = SF_tag2_handler; primitives++; } if (channels_list[index].tag2) { channels_list[index].phandler[primitives] = post_tag2_handler; primitives++; } } } /* struct pkt_vlen_hdr_primitives/off_pkt_vlen_hdr_primitives handling: START */ if (channels_list[index].aggregation_2 & COUNT_LABEL) { if (channels_list[index].plugin->cfg.pre_tag_map) { channels_list[index].phandler[primitives] = pre_tag_label_handler; primitives++; } if (config.acct_type == ACCT_NF) { channels_list[index].phandler[primitives] = NF_cust_label_handler; primitives++; } } /* struct pkt_vlen_hdr_primitives/off_pkt_vlen_hdr_primitives handling: END */ /* sfprobe plugin: struct pkt_payload handling */ if (channels_list[index].aggregation & COUNT_PAYLOAD) { if (channels_list[index].plugin->type.id == PLUGIN_ID_SFPROBE) { if (config.acct_type == ACCT_PM) channels_list[index].phandler[primitives] = sfprobe_payload_handler; else primitives--; /* This case is filtered out at startup: getting out silently */ } primitives++; } /* tee plugin: struct pkt_msg handling */ if (channels_list[index].aggregation & COUNT_NONE) { if (channels_list[index].plugin->type.id == PLUGIN_ID_TEE) { if (config.acct_type == ACCT_SF) channels_list[index].phandler[primitives] = SF_tee_payload_handler; if (config.acct_type == ACCT_NF) channels_list[index].phandler[primitives] = NF_tee_payload_handler; else primitives--; /* This case is filtered out at startup: getting out silently */ } primitives++; } index++; } assert(primitives < N_PRIMITIVES); } #if defined (HAVE_L2) void src_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->mac_ptr) memcpy(pdata->primitives.eth_shost, (pptrs->mac_ptr + ETH_ADDR_LEN), ETH_ADDR_LEN); } void dst_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->mac_ptr) memcpy(pdata->primitives.eth_dhost, pptrs->mac_ptr, ETH_ADDR_LEN); } void vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; u_int16_t vlan_id = 0; if (pptrs->vlan_ptr) { memcpy(&vlan_id, pptrs->vlan_ptr, 2); pdata->primitives.vlan_id = ntohs(vlan_id); pdata->primitives.vlan_id = pdata->primitives.vlan_id & 0x0FFF; } } void cos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; u_int16_t cos = 0; if (pptrs->vlan_ptr) { memcpy(&cos, pptrs->vlan_ptr, 2); cos = ntohs(cos); pdata->primitives.cos = cos >> 13; } } void etype_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.etype = pptrs->l3_proto; } #endif void mpls_label_top_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); u_int32_t *label = (u_int32_t *) pptrs->mpls_ptr; if (label) pmpls->mpls_label_top = MPLS_LABEL(ntohl(*label)); } void mpls_label_bottom_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); u_int32_t lvalue = 0, *label = (u_int32_t *) pptrs->mpls_ptr; if (label) { do { lvalue = ntohl(*label); label += 4; } while (!MPLS_STACK(lvalue)); pmpls->mpls_label_bottom = MPLS_LABEL(lvalue); } } void mpls_label_stack_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); u_int32_t lvalue = 0, *label = (u_int32_t *) pptrs->mpls_ptr, idx = 0; u_int32_t label_stack[MAX_MPLS_LABELS]; u_int8_t label_stack_len = 0; memset(&label_stack, 0, sizeof(label_stack)); if (label) { do { lvalue = ntohl(*label); if (idx < MAX_MPLS_LABELS) { label_stack[idx] = MPLS_LABEL(lvalue); label_stack_len += 4; idx++; } label += 4; } while (!MPLS_STACK(lvalue)); } if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + label_stack_len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_MPLS_LABEL_STACK, label_stack_len, (u_char *) label_stack, PM_MSG_BIN_COPY); } void bgp_src_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct bgp_node *ret = (struct bgp_node *) pptrs->bgp_src; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_net, NF_NET_BGP)) return; if (ret) pdata->primitives.src_nmask = ret->p.prefixlen; } void bgp_dst_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct bgp_node *ret = (struct bgp_node *) pptrs->bgp_dst; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_BGP)) return; if (ret) pdata->primitives.dst_nmask = ret->p.prefixlen; } void bgp_peer_dst_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); struct bgp_info *nh_info = NULL; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_BGP)) return; if (pptrs->bgp_nexthop_info) nh_info = (struct bgp_info *) pptrs->bgp_nexthop_info; else if (pptrs->bgp_dst_info) nh_info = (struct bgp_info *) pptrs->bgp_dst_info; if (nh_info && nh_info->attr) { if (nh_info->attr->mp_nexthop.family == AF_INET) { pbgp->peer_dst_ip.family = AF_INET; memcpy(&pbgp->peer_dst_ip.address.ipv4, &nh_info->attr->mp_nexthop.address.ipv4, 4); } else if (nh_info->attr->mp_nexthop.family == AF_INET6) { pbgp->peer_dst_ip.family = AF_INET6; memcpy(&pbgp->peer_dst_ip.address.ipv6, &nh_info->attr->mp_nexthop.address.ipv6, 16); } else { pbgp->peer_dst_ip.family = AF_INET; pbgp->peer_dst_ip.address.ipv4.s_addr = nh_info->attr->nexthop.s_addr; } } } void igp_src_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct route_node *ret = (struct route_node *) pptrs->igp_src; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_net, NF_NET_IGP)) return; if (ret) pdata->primitives.src_nmask = ret->p.prefixlen; } void igp_dst_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct route_node *ret = (struct route_node *) pptrs->igp_dst; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_IGP)) return; if (ret) pdata->primitives.dst_nmask = ret->p.prefixlen; } void igp_peer_dst_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct route_node *ret = (struct route_node *) pptrs->igp_dst; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_IGP)) return; if (ret) { pbgp->peer_dst_ip.family = AF_INET; memcpy(&pbgp->peer_dst_ip.address.ipv4, &ret->p.adv_router, 4); } } void src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l3_proto == ETHERTYPE_IP) { pdata->primitives.src_ip.address.ipv4.s_addr = ((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr; pdata->primitives.src_ip.family = AF_INET; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&pdata->primitives.src_ip.address.ipv6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, IP6AddrSz); pdata->primitives.src_ip.family = AF_INET6; } } void dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l3_proto == ETHERTYPE_IP) { pdata->primitives.dst_ip.address.ipv4.s_addr = ((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr; pdata->primitives.dst_ip.family = AF_INET; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&pdata->primitives.dst_ip.address.ipv6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, IP6AddrSz); pdata->primitives.dst_ip.family = AF_INET6; } } void src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l4_proto == IPPROTO_UDP || pptrs->l4_proto == IPPROTO_TCP) pdata->primitives.src_port = ntohs(((struct pm_tlhdr *) pptrs->tlh_ptr)->src_port); else pdata->primitives.src_port = 0; } void dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l4_proto == IPPROTO_UDP || pptrs->l4_proto == IPPROTO_TCP) pdata->primitives.dst_port = ntohs(((struct pm_tlhdr *) pptrs->tlh_ptr)->dst_port); else pdata->primitives.dst_port = 0; } void ip_tos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; u_int32_t tos = 0; if (pptrs->l3_proto == ETHERTYPE_IP) { pdata->primitives.tos = ((struct pm_iphdr *) pptrs->iph_ptr)->ip_tos; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { tos = ntohl(((struct ip6_hdr *) pptrs->iph_ptr)->ip6_flow); tos = ((tos & 0x0ff00000) >> 20); pdata->primitives.tos = tos; } if (chptr->plugin->cfg.tos_encode_as_dscp) { pdata->primitives.tos = pdata->primitives.tos >> 2; } } void ip_proto_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.proto = pptrs->l4_proto; } void tcp_flags_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l4_proto == IPPROTO_TCP) pdata->tcp_flags = pptrs->tcp_flags; } void tunnel_src_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (tpptrs->mac_ptr) memcpy(ptun->tunnel_eth_shost, (tpptrs->mac_ptr + ETH_ADDR_LEN), ETH_ADDR_LEN); } } void tunnel_dst_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (tpptrs->mac_ptr) memcpy(ptun->tunnel_eth_dhost, tpptrs->mac_ptr, ETH_ADDR_LEN); } } void tunnel_src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (tpptrs->l3_proto == ETHERTYPE_IP) { ptun->tunnel_src_ip.address.ipv4.s_addr = ((struct pm_iphdr *) tpptrs->iph_ptr)->ip_src.s_addr; ptun->tunnel_src_ip.family = AF_INET; } else if (tpptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&ptun->tunnel_src_ip.address.ipv6, &((struct ip6_hdr *) tpptrs->iph_ptr)->ip6_src, IP6AddrSz); ptun->tunnel_src_ip.family = AF_INET6; } } } void tunnel_dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (tpptrs->l3_proto == ETHERTYPE_IP) { ptun->tunnel_dst_ip.address.ipv4.s_addr = ((struct pm_iphdr *) tpptrs->iph_ptr)->ip_dst.s_addr; ptun->tunnel_dst_ip.family = AF_INET; } else if (tpptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&ptun->tunnel_dst_ip.address.ipv6, &((struct ip6_hdr *) tpptrs->iph_ptr)->ip6_dst, IP6AddrSz); ptun->tunnel_dst_ip.family = AF_INET6; } } } void tunnel_ip_proto_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) ptun->tunnel_proto = tpptrs->l4_proto;; } void tunnel_ip_tos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; u_int32_t tos = 0; if (tpptrs) { if (tpptrs->l3_proto == ETHERTYPE_IP) { ptun->tunnel_tos = ((struct pm_iphdr *) tpptrs->iph_ptr)->ip_tos; } else if (tpptrs->l3_proto == ETHERTYPE_IPV6) { tos = ntohl(((struct ip6_hdr *) tpptrs->iph_ptr)->ip6_flow); tos = ((tos & 0x0ff00000) >> 20); ptun->tunnel_tos = tos; } if (chptr->plugin->cfg.tos_encode_as_dscp) { ptun->tunnel_tos = ptun->tunnel_tos >> 2; } } } void tunnel_src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; ptun->tunnel_src_port = 0; if (tpptrs) { if (tpptrs->l4_proto == IPPROTO_UDP || tpptrs->l4_proto == IPPROTO_TCP) { ptun->tunnel_src_port = ntohs(((struct pm_tlhdr *) tpptrs->tlh_ptr)->src_port); } } } void tunnel_dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (tpptrs->l4_proto == IPPROTO_UDP || tpptrs->l4_proto == IPPROTO_TCP) { ptun->tunnel_dst_port = ntohs(((struct pm_tlhdr *) tpptrs->tlh_ptr)->dst_port); } } } void tunnel_tcp_flags_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; if (tpptrs) { if (pptrs->l4_proto == IPPROTO_TCP) { pdata->tunnel_tcp_flags = tpptrs->tcp_flags; } } } void vxlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); u_char *vni_ptr; if (pptrs->vxlan_ptr) { vni_ptr = pptrs->vxlan_ptr; ptun->tunnel_id = *vni_ptr++; ptun->tunnel_id <<= 8; ptun->tunnel_id += *vni_ptr++; ptun->tunnel_id <<= 8; ptun->tunnel_id += *vni_ptr++; } } void counters_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->l3_proto == ETHERTYPE_IP) pdata->pkt_len = ntohs(((struct pm_iphdr *) pptrs->iph_ptr)->ip_len); else if (pptrs->l3_proto == ETHERTYPE_IPV6) pdata->pkt_len = ntohs(((struct ip6_hdr *) pptrs->iph_ptr)->ip6_plen)+IP6HdrSz; else if (config.aggregate_unknown_etype) pdata->pkt_len = pptrs->pkthdr->len-ETHER_HDRLEN; if (pptrs->frag_sum_bytes) { pdata->pkt_len += pptrs->frag_sum_bytes; pptrs->frag_sum_bytes = 0; } pdata->pkt_num = 1; if (pptrs->frag_sum_pkts) { pdata->pkt_num += pptrs->frag_sum_pkts; pptrs->frag_sum_pkts = 0; } pdata->flow_type = pptrs->flow_type.traffic_type; } void counters_renormalize_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->renormalized) return; if (config.ext_sampling_rate) { pdata->pkt_len = pdata->pkt_len * config.ext_sampling_rate; pdata->pkt_num = pdata->pkt_num * config.ext_sampling_rate; } else { pdata->pkt_len = pdata->pkt_len * chptr->s.rate; pdata->pkt_num = pdata->pkt_num * chptr->s.rate; } pptrs->renormalized = TRUE; } void time_new_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->time_start.tv_sec = 0; pdata->time_start.tv_usec = 0; pdata->time_end.tv_sec = 0; pdata->time_end.tv_usec = 0; } void time_pcap_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->time_start.tv_sec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec; pdata->time_start.tv_usec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_usec; pdata->time_end.tv_sec = 0; pdata->time_end.tv_usec = 0; } void post_tag_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.tag = chptr->tag; } void post_tag2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.tag2 = chptr->tag2; } void flows_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->new_flow) pdata->flo_num = 1; } #if defined (WITH_NDPI) void ndpi_class_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; memcpy(&pdata->primitives.ndpi_class, &pptrs->ndpi_class, sizeof(pm_class2_t)); } #endif void sfprobe_payload_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_payload *payload = (struct pkt_payload *) *data; struct pkt_data tmp; struct pkt_bgp_primitives tmp_bgp; struct eth_header eh; char *buf = (char *) *data, *tmpp = (char *) &tmp; char *tmp_bgpp = (char *) &tmp_bgp; int space = (chptr->bufend - chptr->bufptr) - PpayloadSz; int ethHdrLen = 0; memset(&tmp, 0, sizeof(tmp)); memset(&tmp_bgp, 0, sizeof(tmp_bgp)); if (chptr->plugin->cfg.nfacctd_as & NF_AS_NEW || chptr->plugin->cfg.nfacctd_net == NF_NET_NEW) { src_host_handler(chptr, pptrs, &tmpp); dst_host_handler(chptr, pptrs, &tmpp); memcpy(&payload->src_ip, &tmp.primitives.src_ip, HostAddrSz); memcpy(&payload->dst_ip, &tmp.primitives.dst_ip, HostAddrSz); } if (chptr->plugin->cfg.nfacctd_net == NF_NET_BGP) { bgp_src_nmask_handler(chptr, pptrs, &tmpp); bgp_dst_nmask_handler(chptr, pptrs, &tmpp); payload->src_nmask = tmp.primitives.src_nmask; payload->dst_nmask = tmp.primitives.dst_nmask; bgp_peer_dst_ip_handler(chptr, pptrs, &tmp_bgpp); memcpy(&payload->bgp_next_hop, &tmp_bgp.peer_dst_ip, HostAddrSz); } payload->cap_len = ((struct pcap_pkthdr *)pptrs->pkthdr)->caplen; payload->pkt_len = ((struct pcap_pkthdr *)pptrs->pkthdr)->len; payload->pkt_num = 1; payload->time_start = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec; payload->class = pptrs->class; #if defined (WITH_NDPI) memcpy(&payload->ndpi_class, &pptrs->ndpi_class, sizeof(pm_class2_t)); #endif payload->tag = pptrs->tag; payload->tag2 = pptrs->tag2; if (pptrs->ifindex_in > 0) payload->ifindex_in = pptrs->ifindex_in; if (pptrs->ifindex_out > 0) payload->ifindex_out = pptrs->ifindex_out; if (pptrs->vlan_ptr) { u_int16_t vlan_id = 0; memcpy(&vlan_id, pptrs->vlan_ptr, 2); vlan_id = ntohs(vlan_id); payload->vlan = vlan_id & 0x0FFF; payload->priority = vlan_id >> 13; } /* Typically don't have L2 info under NFLOG */ if (!pptrs->mac_ptr) { ethHdrLen = sizeof(struct eth_header); memset(&eh, 0, ethHdrLen); eh.ether_type = htons(pptrs->l3_proto); payload->cap_len += ethHdrLen; payload->pkt_len += ethHdrLen; } /* We could be capturing the entire packet; DEFAULT_SFPROBE_PLOAD_SIZE is our cut-off point */ if (payload->cap_len > DEFAULT_SFPROBE_PLOAD_SIZE) { payload->cap_len = DEFAULT_SFPROBE_PLOAD_SIZE; } if (space >= payload->cap_len) { buf += PpayloadSz; if (!pptrs->mac_ptr) { memcpy(buf, &eh, ethHdrLen); buf += ethHdrLen; } memcpy(buf, pptrs->packet_ptr, payload->cap_len-ethHdrLen); chptr->bufptr += payload->cap_len; /* don't count pkt_payload here */ #if NEED_ALIGN while (chptr->bufptr % 4 != 0) chptr->bufptr++; /* Don't worry, it's harmless increasing here */ #endif } else { chptr->bufptr += space; chptr->reprocess = TRUE; } } void NF_tee_payload_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_msg *pmsg = (struct pkt_msg *) *data; char *ppayload = ((*data) + PmsgSz); if (!pptrs->tee_dissect) { pmsg->seqno = pptrs->seqno; pmsg->len = pptrs->f_len; pmsg->payload = NULL; memcpy(&pmsg->agent, pptrs->f_agent, sizeof(pmsg->agent)); pmsg->tag = pptrs->tag; pmsg->tag2 = pptrs->tag2; pmsg->bcast = FALSE; if (!check_pipe_buffer_space(chptr, NULL, pptrs->f_len)) { memcpy(ppayload, pptrs->f_header, pptrs->f_len); } } else { struct NF_dissect *tee_dissect = (struct NF_dissect *) pptrs->tee_dissect; pmsg->seqno = pptrs->seqno; pmsg->len = (tee_dissect->hdrLen + tee_dissect->flowSetLen + tee_dissect->elemLen); pmsg->payload = NULL; memcpy(&pmsg->agent, pptrs->f_agent, sizeof(pmsg->agent)); pmsg->tag = pptrs->tag; pmsg->tag2 = pptrs->tag2; pmsg->bcast = pptrs->tee_dissect_bcast; if (!check_pipe_buffer_space(chptr, NULL, pmsg->len)) { memcpy(ppayload, tee_dissect->hdrBasePtr, tee_dissect->hdrLen); if (tee_dissect->flowSetLen) memcpy((ppayload + tee_dissect->hdrLen), tee_dissect->flowSetBasePtr, tee_dissect->flowSetLen); memcpy((ppayload + tee_dissect->hdrLen + tee_dissect->flowSetLen), tee_dissect->elemBasePtr, tee_dissect->elemLen); /* fix-ups */ ((struct struct_header_v5 *)ppayload)->version = htons(tee_dissect->hdrVersion); switch (tee_dissect->hdrVersion) { case 5: ((struct struct_header_v5 *)ppayload)->count = htons(tee_dissect->hdrCount); break; case 9: ((struct struct_header_v9 *)ppayload)->count = htons(tee_dissect->hdrCount); ((struct data_hdr_v9 *)(ppayload + tee_dissect->hdrLen))->flow_len = htons(tee_dissect->flowSetLen + tee_dissect->elemLen); break; case 10: ((struct struct_header_ipfix *)ppayload)->len = htons(tee_dissect->hdrLen + tee_dissect->flowSetLen + tee_dissect->elemLen); ((struct data_hdr_v9 *)(ppayload + tee_dissect->hdrLen))->flow_len = htons(tee_dissect->flowSetLen + tee_dissect->elemLen); break; } } } } void SF_tee_payload_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_msg *pmsg = (struct pkt_msg *) *data; char *ppayload = ((*data) + PmsgSz); if (!pptrs->tee_dissect) { pmsg->seqno = pptrs->seqno; pmsg->len = pptrs->f_len; pmsg->payload = NULL; memcpy(&pmsg->agent, pptrs->f_agent, sizeof(pmsg->agent)); pmsg->tag = pptrs->tag; pmsg->tag2 = pptrs->tag2; pmsg->bcast = FALSE; if (!check_pipe_buffer_space(chptr, NULL, pptrs->f_len)) { memcpy(ppayload, pptrs->f_header, pptrs->f_len); } } else { struct SF_dissect *dissect = (struct SF_dissect *) pptrs->tee_dissect; pmsg->seqno = pptrs->seqno; pmsg->len = (dissect->hdrLen + dissect->flowLen); pmsg->payload = NULL; memcpy(&pmsg->agent, pptrs->f_agent, sizeof(pmsg->agent)); pmsg->tag = pptrs->tag; pmsg->tag2 = pptrs->tag2; if (!check_pipe_buffer_space(chptr, NULL, pmsg->len)) { memcpy(ppayload, dissect->hdrBasePtr, dissect->hdrLen); memcpy((ppayload + dissect->hdrLen), dissect->flowBasePtr, dissect->flowLen); } } } void nfprobe_extras_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct pkt_extras *pextras = (struct pkt_extras *) ++pdata; --pdata; /* Bringing back to original place */ if (pptrs->l4_proto == IPPROTO_TCP) { pextras->tcp_flags = pptrs->tcp_flags; } if (pptrs->l4_proto == IPPROTO_ICMP || pptrs->l4_proto == IPPROTO_ICMPV6) { pextras->icmp_type = pptrs->icmp_type; pextras->icmp_code = pptrs->icmp_code; } } void in_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->ifindex_in > 0) pdata->primitives.ifindex_in = pptrs->ifindex_in; } void out_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (pptrs->ifindex_out > 0) pdata->primitives.ifindex_out = pptrs->ifindex_out; } void sampling_rate_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; if (config.ext_sampling_rate || config.sampling_rate) { if (config.ext_sampling_rate) { pdata->primitives.sampling_rate = config.ext_sampling_rate; } else { pdata->primitives.sampling_rate = config.sampling_rate; } } else { pdata->primitives.sampling_rate = 1; } if (config.sfacctd_renormalize) { pdata->primitives.sampling_rate = 1; /* already renormalized */ } } void sampling_direction_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; /* dummy */ pdata->primitives.sampling_direction = SAMPLING_DIRECTION_UNKNOWN; } void mpls_vpn_rd_frommap_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); if (pbgp && pptrs->bitr) { memcpy(&pbgp->mpls_vpn_rd, &pptrs->bitr, sizeof(rd_t)); bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } } void timestamp_start_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); pnat->timestamp_start.tv_sec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec; if (!chptr->plugin->cfg.timestamps_secs) { pnat->timestamp_start.tv_usec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_usec; } } void timestamp_arrival_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); pnat->timestamp_arrival.tv_sec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec; if (!chptr->plugin->cfg.timestamps_secs) { pnat->timestamp_arrival.tv_usec = ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_usec; } } void custom_primitives_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { u_char *pcust = (u_char *)((*data) + chptr->extras.off_custom_primitives); struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); struct custom_primitive_entry *cpe; int cpptrs_idx, pd_ptr_idx; for (cpptrs_idx = 0; cpptrs_idx < chptr->plugin->cfg.cpptrs.num; cpptrs_idx++) { if (chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].ptr) { cpe = chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].ptr; for (pd_ptr_idx = 0; pd_ptr_idx < MAX_CUSTOM_PRIMITIVE_PD_PTRS && cpe->pd_ptr[pd_ptr_idx].ptr_idx.set; pd_ptr_idx++) { if (pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] && ((pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] - pptrs->pkt_data_ptrs[0]) + cpe->pd_ptr[pd_ptr_idx].off + (cpe->len % PM_VARIABLE_LENGTH)) < ((struct pcap_pkthdr *)pptrs->pkthdr)->caplen) { if (!cpe->pd_ptr[pd_ptr_idx].proto.set || pptrs->pkt_proto[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] == cpe->pd_ptr[pd_ptr_idx].proto.n) { if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { unsigned char hexbuf[cpe->alloc_len]; int hexbuflen = 0; hexbuflen = serialize_hex((pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] + cpe->pd_ptr[pd_ptr_idx].off), hexbuf, cpe->len); if (cpe->alloc_len < hexbuflen) hexbuf[cpe->alloc_len-1] = '\0'; memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, hexbuf, MIN(hexbuflen, cpe->alloc_len)); } else { // XXX: maybe prone to SEGV if not a string: check to be added? if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_STRING && cpe->len == PM_VARIABLE_LENGTH) { char *str_ptr = (char *)(pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] + cpe->pd_ptr[pd_ptr_idx].off); int remaining_len, str_len; remaining_len = (((struct pcap_pkthdr *)pptrs->pkthdr)->caplen - ((pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n] - pptrs->pkt_data_ptrs[0]) + cpe->pd_ptr[pd_ptr_idx].off)); if (remaining_len > 0) { str_ptr[remaining_len-1] = '\0'; /* maybe too simplistic */ str_len = strlen(str_ptr); if (str_len) { if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + str_len + 1 /* terminating zero */)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, cpe->type, str_len, (u_char *) str_ptr, PM_MSG_STR_COPY_ZERO); } } } else { memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, pptrs->pkt_data_ptrs[cpe->pd_ptr[pd_ptr_idx].ptr_idx.n]+cpe->pd_ptr[pd_ptr_idx].off, cpe->len); } } } } } } } } #if defined (HAVE_L2) void NF_src_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_SRC_MAC].len) memcpy(&pdata->primitives.eth_shost, pptrs->f_data+tpl->tpl[NF9_IN_SRC_MAC].off, MIN(tpl->tpl[NF9_IN_SRC_MAC].len, 6)); else if (tpl->tpl[NF9_OUT_SRC_MAC].len) memcpy(&pdata->primitives.eth_shost, pptrs->f_data+tpl->tpl[NF9_OUT_SRC_MAC].off, MIN(tpl->tpl[NF9_OUT_SRC_MAC].len, 6)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) src_mac_handler(chptr, pptrs, data); break; default: break; } } void NF_dst_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_DST_MAC].len) memcpy(&pdata->primitives.eth_dhost, pptrs->f_data+tpl->tpl[NF9_IN_DST_MAC].off, MIN(tpl->tpl[NF9_IN_DST_MAC].len, 6)); else if (tpl->tpl[NF9_OUT_DST_MAC].len) memcpy(&pdata->primitives.eth_dhost, pptrs->f_data+tpl->tpl[NF9_OUT_DST_MAC].off, MIN(tpl->tpl[NF9_OUT_DST_MAC].len, 6)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) dst_mac_handler(chptr, pptrs, data); break; default: break; } } void NF_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t direction; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DIRECTION].len) { memcpy(&direction, pptrs->f_data+tpl->tpl[NF9_DIRECTION].off, MIN(tpl->tpl[NF9_DIRECTION].len, 1)); if (direction == FALSE) { if (tpl->tpl[NF9_IN_VLAN].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off, MIN(tpl->tpl[NF9_IN_VLAN].len, 2)); else if (tpl->tpl[NF9_DOT1QVLANID].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_DOT1QVLANID].off, MIN(tpl->tpl[NF9_DOT1QVLANID].len, 2)); } else if (direction == TRUE) { if (tpl->tpl[NF9_OUT_VLAN].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_OUT_VLAN].off, MIN(tpl->tpl[NF9_OUT_VLAN].len, 2)); else if (tpl->tpl[NF9_POST_DOT1QVLANID].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_POST_DOT1QVLANID].off, MIN(tpl->tpl[NF9_POST_DOT1QVLANID].len, 2)); } } else { if (tpl->tpl[NF9_IN_VLAN].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off, MIN(tpl->tpl[NF9_IN_VLAN].len, 2)); else if (tpl->tpl[NF9_OUT_VLAN].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_OUT_VLAN].off, MIN(tpl->tpl[NF9_OUT_VLAN].len, 2)); else if (tpl->tpl[NF9_DOT1QVLANID].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_DOT1QVLANID].off, MIN(tpl->tpl[NF9_DOT1QVLANID].len, 2)); else if (tpl->tpl[NF9_POST_DOT1QVLANID].len) memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_POST_DOT1QVLANID].off, MIN(tpl->tpl[NF9_POST_DOT1QVLANID].len, 2)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { vlan_handler(chptr, pptrs, data); break; } } pdata->primitives.vlan_id = ntohs(pdata->primitives.vlan_id); break; default: break; } } void NF_in_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_VLAN].len) { memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off, MIN(tpl->tpl[NF9_IN_VLAN].len, 2)); } else if (tpl->tpl[NF9_DOT1QVLANID].len) { memcpy(&pdata->primitives.vlan_id, pptrs->f_data+tpl->tpl[NF9_DOT1QVLANID].off, MIN(tpl->tpl[NF9_DOT1QVLANID].len, 2)); } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { vlan_handler(chptr, pptrs, data); break; } pdata->primitives.vlan_id = ntohs(pdata->primitives.vlan_id); break; default: break; } } void NF_out_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_OUT_VLAN].len) { memcpy(&pdata->primitives.out_vlan_id, pptrs->f_data+tpl->tpl[NF9_OUT_VLAN].off, MIN(tpl->tpl[NF9_OUT_VLAN].len, 2)); } else if (tpl->tpl[NF9_POST_DOT1QVLANID].len) { memcpy(&pdata->primitives.out_vlan_id, pptrs->f_data+tpl->tpl[NF9_POST_DOT1QVLANID].off, MIN(tpl->tpl[NF9_POST_DOT1QVLANID].len, 2)); } pdata->primitives.out_vlan_id = ntohs(pdata->primitives.out_vlan_id); break; default: break; } } void NF_cos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DOT1QPRIORITY].len) memcpy(&pdata->primitives.cos, pptrs->f_data+tpl->tpl[NF9_DOT1QPRIORITY].off, MIN(tpl->tpl[NF9_DOT1QPRIORITY].len, 1)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) cos_handler(chptr, pptrs, data); break; default: break; } } void NF_etype_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_ETHERTYPE].len == 2) { memcpy(&pdata->primitives.etype, pptrs->f_data+tpl->tpl[NF9_ETHERTYPE].off, MIN(tpl->tpl[NF9_ETHERTYPE].len, 2)); pdata->primitives.etype = ntohs(pdata->primitives.etype); } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) etype_handler(chptr, pptrs, data); else pdata->primitives.etype = pptrs->l3_proto; break; default: pdata->primitives.etype = pptrs->l3_proto; break; } } #endif void NF_src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP || pptrs->flow_type.traffic_type == NF9_FTYPE_NAT_EVENT /* NAT64 case */) { if (tpl->tpl[NF9_IPV4_SRC_ADDR].len) { memcpy(&pdata->primitives.src_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV4_SRC_ADDR].len, 4)); pdata->primitives.src_ip.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_SRC_PREFIX].len) { memcpy(&pdata->primitives.src_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_SRC_PREFIX].len, 4)); pdata->primitives.src_ip.family = AF_INET; } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) src_host_handler(chptr, pptrs, data); } if (pptrs->l3_proto == ETHERTYPE_IPV6 || pptrs->flow_type.traffic_type == NF9_FTYPE_NAT_EVENT /* NAT64 case */) { if (tpl->tpl[NF9_IPV6_SRC_ADDR].len) { memcpy(&pdata->primitives.src_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV6_SRC_ADDR].len, 16)); pdata->primitives.src_ip.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_SRC_PREFIX].len) { memcpy(&pdata->primitives.src_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_SRC_PREFIX].len, 16)); pdata->primitives.src_ip.family = AF_INET6; } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) src_host_handler(chptr, pptrs, data); } break; case 5: pdata->primitives.src_ip.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->srcaddr.s_addr; pdata->primitives.src_ip.family = AF_INET; break; default: break; } } void NF_dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP || pptrs->flow_type.traffic_type == NF9_FTYPE_NAT_EVENT /* NAT64 case */) { if (tpl->tpl[NF9_IPV4_DST_ADDR].len) { memcpy(&pdata->primitives.dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV4_DST_ADDR].len, 4)); pdata->primitives.dst_ip.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_DST_PREFIX].len) { memcpy(&pdata->primitives.dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_DST_PREFIX].len, 4)); pdata->primitives.dst_ip.family = AF_INET; } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) dst_host_handler(chptr, pptrs, data); } if (pptrs->l3_proto == ETHERTYPE_IPV6 || pptrs->flow_type.traffic_type == NF9_FTYPE_NAT_EVENT /* NAT64 case */) { if (tpl->tpl[NF9_IPV6_DST_ADDR].len) { memcpy(&pdata->primitives.dst_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV6_DST_ADDR].len, 16)); pdata->primitives.dst_ip.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_DST_PREFIX].len) { memcpy(&pdata->primitives.dst_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_DST_PREFIX].len, 16)); pdata->primitives.dst_ip.family = AF_INET6; } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) dst_host_handler(chptr, pptrs, data); } break; case 5: pdata->primitives.dst_ip.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->dstaddr.s_addr; pdata->primitives.dst_ip.family = AF_INET; break; default: break; } } void NF_src_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP) { if (tpl->tpl[NF9_SRC_MASK].len) memcpy(&pdata->primitives.src_nmask, pptrs->f_data+tpl->tpl[NF9_SRC_MASK].off, tpl->tpl[NF9_SRC_MASK].len); } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { if (tpl->tpl[NF9_IPV6_SRC_MASK].len) memcpy(&pdata->primitives.src_nmask, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_MASK].off, tpl->tpl[NF9_IPV6_SRC_MASK].len); } break; case 5: pdata->primitives.src_nmask = ((struct struct_export_v5 *) pptrs->f_data)->src_mask; break; default: break; } } void NF_dst_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP) { if (tpl->tpl[NF9_DST_MASK].len) memcpy(&pdata->primitives.dst_nmask, pptrs->f_data+tpl->tpl[NF9_DST_MASK].off, tpl->tpl[NF9_DST_MASK].len); } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { if (tpl->tpl[NF9_IPV6_DST_MASK].len) memcpy(&pdata->primitives.dst_nmask, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_MASK].off, tpl->tpl[NF9_IPV6_DST_MASK].len); } break; case 5: pdata->primitives.dst_nmask = ((struct struct_export_v5 *) pptrs->f_data)->dst_mask; break; default: break; } } void NF_src_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int16_t asn16 = 0; u_int32_t asn32 = 0; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_SRC_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 2); pdata->primitives.src_as = ntohs(asn16); } else if (tpl->tpl[NF9_SRC_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 4); pdata->primitives.src_as = ntohl(asn32); } break; case 5: pdata->primitives.src_as = ntohs(((struct struct_export_v5 *) pptrs->f_data)->src_as); break; default: break; } if (chptr->plugin->cfg.nfprobe_peer_as) { if (chptr->aggregation & COUNT_PEER_SRC_AS) pbgp->peer_src_as = pdata->primitives.src_as; pdata->primitives.src_as = 0; } } void NF_dst_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int16_t asn16 = 0; u_int32_t asn32 = 0; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DST_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 2); pdata->primitives.dst_as = ntohs(asn16); } else if (tpl->tpl[NF9_DST_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 4); pdata->primitives.dst_as = ntohl(asn32); } break; case 5: pdata->primitives.dst_as = ntohs(((struct struct_export_v5 *) pptrs->f_data)->dst_as); break; default: break; } if (chptr->plugin->cfg.nfprobe_peer_as) { if (chptr->aggregation & COUNT_PEER_DST_AS) pbgp->peer_dst_as = pdata->primitives.dst_as; pdata->primitives.dst_as = 0; } } void NF_peer_src_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int16_t asn16 = 0; u_int32_t asn32 = 0; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PEER_SRC_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_PEER_SRC_AS].off, 2); pbgp->peer_src_as = ntohs(asn16); } else if (tpl->tpl[NF9_PEER_SRC_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_PEER_SRC_AS].off, 4); pbgp->peer_src_as = ntohl(asn32); } break; default: break; } } void NF_peer_dst_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int16_t asn16 = 0; u_int32_t asn32 = 0; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PEER_DST_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_PEER_DST_AS].off, 2); pbgp->peer_dst_as = ntohs(asn16); } else if (tpl->tpl[NF9_PEER_DST_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_PEER_DST_AS].off, 4); pbgp->peer_dst_as = ntohl(asn32); } break; default: break; } } void NF_peer_src_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent; /* 1) NF9_EXPORTER_IPV[46]_ADDRESS from NetFlow v9/IPFIX options */ if (entry->exp_addr.family) { memcpy(&pbgp->peer_src_ip, &entry->exp_addr, sizeof(struct host_addr)); } /* 2) Socket IP address */ else { if (sa->sa_family == AF_INET) { pbgp->peer_src_ip.address.ipv4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; pbgp->peer_src_ip.family = AF_INET; } else if (sa->sa_family == AF_INET6) { memcpy(&pbgp->peer_src_ip.address.ipv6, &((struct sockaddr_in6 *)sa)->sin6_addr, IP6AddrSz); pbgp->peer_src_ip.family = AF_INET6; } } /* 3) NetFlow v9/IPFIX inline NF9_EXPORTER_IPV[46]_ADDRESS */ if (!pbgp->peer_src_ip.family) { int got_ipv4 = FALSE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].len) { memcpy(&pbgp->peer_src_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].off, MIN(tpl->tpl[NF9_EXPORTER_IPV4_ADDRESS].len, 4)); pbgp->peer_src_ip.family = AF_INET; if (!is_any(&pbgp->peer_src_ip)) { got_ipv4 = TRUE; } } if (!got_ipv4 && tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].len) { memcpy(&pbgp->peer_src_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].off, MIN(tpl->tpl[NF9_EXPORTER_IPV6_ADDRESS].len, 16)); pbgp->peer_src_ip.family = AF_INET6; } } } } void NF_peer_dst_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp; int use_ip_next_hop = FALSE; /* we determine if this is called by exec_plugins() or bgp_srcdst_lookup() */ if (chptr) { pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); use_ip_next_hop = chptr->plugin->cfg.use_ip_next_hop; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; } else { pbgp = (struct pkt_bgp_primitives *) (*data); use_ip_next_hop = config.use_ip_next_hop; } switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len) { memcpy(&pbgp->peer_dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].off, MIN(tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len, 4)); pbgp->peer_dst_ip.family = AF_INET; } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len) { memcpy(&pbgp->peer_dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].off, MIN(tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len, 4)); pbgp->peer_dst_ip.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_NEXT_HOP].len) { if (use_ip_next_hop) { memcpy(&pbgp->peer_dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_NEXT_HOP].off, MIN(tpl->tpl[NF9_IPV4_NEXT_HOP].len, 4)); pbgp->peer_dst_ip.family = AF_INET; } } else if (tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len) { memcpy(&pbgp->peer_dst_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].off, MIN(tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len, 16)); pbgp->peer_dst_ip.family = AF_INET6; } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len) { memcpy(&pbgp->peer_dst_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].off, MIN(tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len, 16)); pbgp->peer_dst_ip.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_NEXT_HOP].len) { if (use_ip_next_hop) { memcpy(&pbgp->peer_dst_ip.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_NEXT_HOP].off, MIN(tpl->tpl[NF9_IPV6_NEXT_HOP].len, 16)); pbgp->peer_dst_ip.family = AF_INET6; } } break; case 5: if (use_ip_next_hop) { pbgp->peer_dst_ip.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->nexthop.s_addr; pbgp->peer_dst_ip.family = AF_INET; } break; default: break; } } void NF_src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t l4_proto = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_L4_PROTOCOL].len == 1) memcpy(&l4_proto, pptrs->f_data+tpl->tpl[NF9_L4_PROTOCOL].off, 1); if (tpl->tpl[NF9_L4_SRC_PORT].len) memcpy(&pdata->primitives.src_port, pptrs->f_data+tpl->tpl[NF9_L4_SRC_PORT].off, MIN(tpl->tpl[NF9_L4_SRC_PORT].len, 2)); else if (tpl->tpl[NF9_UDP_SRC_PORT].len) memcpy(&pdata->primitives.src_port, pptrs->f_data+tpl->tpl[NF9_UDP_SRC_PORT].off, MIN(tpl->tpl[NF9_UDP_SRC_PORT].len, 2)); else if (tpl->tpl[NF9_TCP_SRC_PORT].len) memcpy(&pdata->primitives.src_port, pptrs->f_data+tpl->tpl[NF9_TCP_SRC_PORT].off, MIN(tpl->tpl[NF9_TCP_SRC_PORT].len, 2)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { src_port_handler(chptr, pptrs, data); break; } pdata->primitives.src_port = ntohs(pdata->primitives.src_port); break; case 5: if ((((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_UDP) || ((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_TCP) { pdata->primitives.src_port = ntohs(((struct struct_export_v5 *) pptrs->f_data)->srcport); } else pdata->primitives.src_port = 0; break; default: break; } } void NF_dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t l4_proto = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_L4_PROTOCOL].len == 1) memcpy(&l4_proto, pptrs->f_data+tpl->tpl[NF9_L4_PROTOCOL].off, 1); if (tpl->tpl[NF9_L4_DST_PORT].len) memcpy(&pdata->primitives.dst_port, pptrs->f_data+tpl->tpl[NF9_L4_DST_PORT].off, MIN(tpl->tpl[NF9_L4_DST_PORT].len, 2)); else if (tpl->tpl[NF9_UDP_DST_PORT].len) memcpy(&pdata->primitives.dst_port, pptrs->f_data+tpl->tpl[NF9_UDP_DST_PORT].off, MIN(tpl->tpl[NF9_UDP_DST_PORT].len, 2)); else if (tpl->tpl[NF9_TCP_DST_PORT].len) memcpy(&pdata->primitives.dst_port, pptrs->f_data+tpl->tpl[NF9_TCP_DST_PORT].off, MIN(tpl->tpl[NF9_TCP_DST_PORT].len, 2)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { dst_port_handler(chptr, pptrs, data); break; } pdata->primitives.dst_port = ntohs(pdata->primitives.dst_port); break; case 5: if ((((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_UDP) || ((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_TCP || ((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_ICMP || ((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_ICMPV6) { pdata->primitives.dst_port = ntohs(((struct struct_export_v5 *) pptrs->f_data)->dstport); } else { pdata->primitives.dst_port = 0; } break; default: break; } } void NF_ip_tos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; /* setting tos from pre_tag_map */ if (pptrs->set_tos.set) { pdata->primitives.tos = pptrs->set_tos.n; return; } switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_SRC_TOS].len) memcpy(&pdata->primitives.tos, pptrs->f_data+tpl->tpl[NF9_SRC_TOS].off, MIN(tpl->tpl[NF9_SRC_TOS].len, 1)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) ip_tos_handler(chptr, pptrs, data); break; case 5: pdata->primitives.tos = ((struct struct_export_v5 *) pptrs->f_data)->tos; break; default: break; } if (chptr->plugin->cfg.tos_encode_as_dscp) { pdata->primitives.tos = pdata->primitives.tos >> 2; } } void NF_ip_proto_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_L4_PROTOCOL].len) memcpy(&pdata->primitives.proto, pptrs->f_data+tpl->tpl[NF9_L4_PROTOCOL].off, MIN(tpl->tpl[NF9_L4_PROTOCOL].len, 1)); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) ip_proto_handler(chptr, pptrs, data); break; case 5: pdata->primitives.proto = ((struct struct_export_v5 *) pptrs->f_data)->prot; break; default: break; } } void NF_tcp_flags_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t tcp_flags = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_TCP_FLAGS].len == 1) { memcpy(&tcp_flags, pptrs->f_data+tpl->tpl[NF9_TCP_FLAGS].off, 1); pdata->tcp_flags = tcp_flags; } else if (tpl->tpl[NF9_TCP_FLAGS].len == 2) { /* trash the first octet and copy over the second one */ memcpy(&tcp_flags, (pptrs->f_data + tpl->tpl[NF9_TCP_FLAGS].off + 1), 1); pdata->tcp_flags = tcp_flags; } else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) tcp_flags_handler(chptr, pptrs, data); break; case 5: if (((struct struct_export_v5 *) pptrs->f_data)->prot == IPPROTO_TCP && hdr->version == 5) pdata->tcp_flags = ((struct struct_export_v5 *) pptrs->f_data)->tcp_flags; break; default: break; } } void NF_fwd_status_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t fwd_status = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FWD_STATUS].len == 1) { memcpy(&fwd_status, pptrs->f_data+tpl->tpl[NF9_FWD_STATUS].off, MIN(tpl->tpl[NF9_FWD_STATUS].len, 1)); pnat->fwd_status = fwd_status; } break; case 5: break; default: break; } } void NF_counters_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t t32 = 0; u_int64_t t64 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_BYTES].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_IN_BYTES].off, 4); pdata->pkt_len = ntohl(t32); } else if (tpl->tpl[NF9_IN_BYTES].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_IN_BYTES].off, 8); pdata->pkt_len = pm_ntohll(t64); } else if (tpl->tpl[NF9_FLOW_BYTES].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_BYTES].off, 4); pdata->pkt_len = ntohl(t32); } else if (tpl->tpl[NF9_FLOW_BYTES].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FLOW_BYTES].off, 8); pdata->pkt_len = pm_ntohll(t64); } else if (tpl->tpl[NF9_OUT_BYTES].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_OUT_BYTES].off, 4); pdata->pkt_len = ntohl(t32); } else if (tpl->tpl[NF9_OUT_BYTES].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_OUT_BYTES].off, 8); pdata->pkt_len = pm_ntohll(t64); } else if (tpl->tpl[NF9_LAYER2OCTETDELTACOUNT].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAYER2OCTETDELTACOUNT].off, 8); pdata->pkt_len = pm_ntohll(t64); } else if (tpl->tpl[NF9_INITIATOR_OCTETS].len == 4) { if (chptr->plugin->cfg.tmp_asa_bi_flow) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_INITIATOR_OCTETS].off, 4); pdata->pkt_len = ntohl(t32); } } else if (tpl->tpl[NF9_INITIATOR_OCTETS].len == 8) { if (chptr->plugin->cfg.tmp_asa_bi_flow) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_INITIATOR_OCTETS].off, 8); pdata->pkt_len = pm_ntohll(t64); } } if (tpl->tpl[NF9_IN_PACKETS].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_IN_PACKETS].off, 4); pdata->pkt_num = ntohl(t32); } else if (tpl->tpl[NF9_IN_PACKETS].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_IN_PACKETS].off, 8); pdata->pkt_num = pm_ntohll(t64); } else if (tpl->tpl[NF9_FLOW_PACKETS].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_PACKETS].off, 4); pdata->pkt_num = ntohl(t32); } else if (tpl->tpl[NF9_FLOW_PACKETS].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FLOW_PACKETS].off, 8); pdata->pkt_num = pm_ntohll(t64); } else if (tpl->tpl[NF9_OUT_PACKETS].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_OUT_PACKETS].off, 4); pdata->pkt_num = ntohl(t32); } else if (tpl->tpl[NF9_OUT_PACKETS].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_OUT_PACKETS].off, 8); pdata->pkt_num = pm_ntohll(t64); } else if (tpl->tpl[NF9_RESPONDER_OCTETS].len == 4) { if (chptr->plugin->cfg.tmp_asa_bi_flow) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_RESPONDER_OCTETS].off, 4); pdata->pkt_num = ntohl(t32); } } else if (tpl->tpl[NF9_RESPONDER_OCTETS].len == 8) { if (chptr->plugin->cfg.tmp_asa_bi_flow) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_RESPONDER_OCTETS].off, 8); pdata->pkt_num = pm_ntohll(t64); } } if (!pdata->pkt_len && !pdata->pkt_num) { if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) counters_handler(chptr, pptrs, data); } break; case 5: pdata->pkt_len = ntohl(((struct struct_export_v5 *) pptrs->f_data)->dOctets); pdata->pkt_num = ntohl(((struct struct_export_v5 *) pptrs->f_data)->dPkts); break; default: break; } pdata->flow_type = pptrs->flow_type.traffic_type; } /* times from the netflow engine are in msecs */ void NF_time_msecs_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; time_t fstime = 0; u_int32_t t32 = 0; u_int64_t t64 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FIRST_SWITCHED].len && hdr->version == 9) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED].off, tpl->tpl[NF9_FIRST_SWITCHED].len); pdata->time_start.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime))/1000); if (config.debug) { if (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime) < ntohl(fstime)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%u] firstSwitched > sysUptime timestamp. Overflow detected.\n", config.name, config.type, ntohl(((struct struct_header_v9 *) pptrs->f_header)->flow_sequence)); } } } else if (tpl->tpl[NF9_FIRST_SWITCHED].len && hdr->version == 10) { if (tpl->tpl[NF9_SYS_UPTIME_MSEC].len == 8) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED].off, tpl->tpl[NF9_FIRST_SWITCHED].len); memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SYS_UPTIME_MSEC].off, tpl->tpl[NF9_SYS_UPTIME_MSEC].len); t32 = pm_ntohll(t64)/1000; pdata->time_start.tv_sec = t32+(ntohl(fstime)/1000); } } else if (tpl->tpl[NF9_FIRST_SWITCHED_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_MSEC].off, tpl->tpl[NF9_FIRST_SWITCHED_MSEC].len); pdata->time_start.tv_sec = pm_ntohll(t64)/1000; pdata->time_start.tv_usec = (pm_ntohll(t64)%1000)*1000; } else if (tpl->tpl[NF9_FIRST_SWITCHED_USEC].len) { if (tpl->tpl[NF9_FIRST_SWITCHED_USEC].len == 16) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_USEC].off, 8); pdata->time_start.tv_sec = pm_ntohll(t64); memcpy(&t64, (pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_USEC].off+8), 8); pdata->time_start.tv_usec = pm_ntohll(t64); } } else if (tpl->tpl[NF9_OBSERVATION_TIME_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_OBSERVATION_TIME_MSEC].off, tpl->tpl[NF9_OBSERVATION_TIME_MSEC].len); pdata->time_start.tv_sec = pm_ntohll(t64)/1000; pdata->time_start.tv_usec = (pm_ntohll(t64)%1000)*1000; } /* sec handling here: msec vs sec restricted to NetFlow v5 */ else if (tpl->tpl[NF9_FIRST_SWITCHED_SEC].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_SEC].off, tpl->tpl[NF9_FIRST_SWITCHED_SEC].len); pdata->time_start.tv_sec = ntohl(t32); } else if (tpl->tpl[NF9_FIRST_SWITCHED_SEC].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_SEC].off, tpl->tpl[NF9_FIRST_SWITCHED_SEC].len); pdata->time_start.tv_sec = pm_ntohll(t64); } else if (tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].len && hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; u_int32_t t32h = 0, h32h = 0; u_int64_t t64_1 = 0, t64_2 = 0; memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].off, tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].len); t32h = ntohl(t32); h32h = ntohl(hdr_ipfix->unix_secs); t64 = h32h; t64 = t64 * 1000 * 1000; t64 -= t32h; t64_1 = (t64 / (1000 * 1000)); t64_2 = (t64 % (1000 * 1000)); pdata->time_start.tv_sec = t64_1; pdata->time_start.tv_usec = t64_2; } /* fallback to header timestamp if no other time reference is available */ if (!pdata->time_start.tv_sec) { if (hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; pdata->time_start.tv_sec = ntohl(hdr_ipfix->unix_secs); } else if (hdr->version == 9) { struct struct_header_v9 *hdr_v9 = (struct struct_header_v9 *) pptrs->f_header; pdata->time_start.tv_sec = ntohl(hdr_v9->unix_secs); } } if (tpl->tpl[NF9_LAST_SWITCHED].len && hdr->version == 9) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED].off, tpl->tpl[NF9_LAST_SWITCHED].len); pdata->time_end.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime))/1000); if (config.debug) { if (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime) < ntohl(fstime)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%u] lastSwitched > sysUptime timestamp. Overflow detected.\n", config.name, config.type, ntohl(((struct struct_header_v9 *) pptrs->f_header)->flow_sequence)); } } } else if (tpl->tpl[NF9_LAST_SWITCHED].len && hdr->version == 10) { if (tpl->tpl[NF9_SYS_UPTIME_MSEC].len == 8) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED].off, tpl->tpl[NF9_LAST_SWITCHED].len); memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SYS_UPTIME_MSEC].off, tpl->tpl[NF9_SYS_UPTIME_MSEC].len); t32 = pm_ntohll(t64)/1000; pdata->time_end.tv_sec = t32+(ntohl(fstime)/1000); } } else if (tpl->tpl[NF9_LAST_SWITCHED_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_MSEC].off, tpl->tpl[NF9_LAST_SWITCHED_MSEC].len); pdata->time_end.tv_sec = pm_ntohll(t64)/1000; pdata->time_end.tv_usec = (pm_ntohll(t64)%1000)*1000; } else if (tpl->tpl[NF9_LAST_SWITCHED_USEC].len) { if (tpl->tpl[NF9_LAST_SWITCHED_USEC].len == 16) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_USEC].off, 8); pdata->time_end.tv_sec = pm_ntohll(t64); memcpy(&t64, (pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_USEC].off+8), 8); pdata->time_end.tv_usec = pm_ntohll(t64); } } /* sec handling here: msec vs sec restricted to NetFlow v5 */ else if (tpl->tpl[NF9_LAST_SWITCHED_SEC].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_SEC].off, tpl->tpl[NF9_LAST_SWITCHED_SEC].len); pdata->time_end.tv_sec = ntohl(t32); } else if (tpl->tpl[NF9_LAST_SWITCHED_SEC].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_SEC].off, tpl->tpl[NF9_LAST_SWITCHED_SEC].len); pdata->time_end.tv_sec = pm_ntohll(t64); } else if (tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].len && hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; u_int32_t t32h = 0, h32h = 0; u_int64_t t64_1 = 0, t64_2 = 0; memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].off, tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].len); t32h = ntohl(t32); h32h = ntohl(hdr_ipfix->unix_secs); t64 = h32h; t64 = t64 * 1000 * 1000; t64 -= t32h; t64_1 = (t64 / (1000 * 1000)); t64_2 = (t64 % (1000 * 1000)); pdata->time_end.tv_sec = t64_1; pdata->time_end.tv_usec = t64_2; } break; case 5: pdata->time_start.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime))/1000)+ ((ntohl(((struct struct_export_v5 *) pptrs->f_data)->First))/1000); pdata->time_end.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime))/1000)+ ((ntohl(((struct struct_export_v5 *) pptrs->f_data)->Last))/1000); break; default: break; } pdata->flow_type = pptrs->flow_type.traffic_type; } /* times from the netflow engine are in secs */ void NF_time_secs_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; time_t fstime = 0; switch(hdr->version) { case 10: case 9: memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED].off, tpl->tpl[NF9_FIRST_SWITCHED].len); pdata->time_start.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime)); if (config.debug) { if (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime) < ntohl(fstime)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%u] firstSwitched > sysUptime timestamp. Overflow detected.\n", config.name, config.type, ntohl(((struct struct_header_v9 *) pptrs->f_header)->flow_sequence)); } } memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED].off, tpl->tpl[NF9_LAST_SWITCHED].len); pdata->time_end.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime)); if (config.debug) { if (ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime) < ntohl(fstime)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%u] lastSwitched > sysUptime timestamp. Overflow detected.\n", config.name, config.type, ntohl(((struct struct_header_v9 *) pptrs->f_header)->flow_sequence)); } } break; case 5: pdata->time_start.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- (ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime)-ntohl(((struct struct_export_v5 *) pptrs->f_data)->First)); pdata->time_end.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- (ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime)-ntohl(((struct struct_export_v5 *) pptrs->f_data)->Last)); break; default: break; } pdata->flow_type = pptrs->flow_type.traffic_type; } /* ignore netflow engine times and generate new ones */ void NF_time_new_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->time_start.tv_sec = 0; pdata->time_start.tv_usec = 0; pdata->time_end.tv_sec = 0; pdata->time_end.tv_usec = 0; pdata->flow_type = pptrs->flow_type.traffic_type; } void pre_tag_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.tag = pptrs->tag; } void pre_tag2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->primitives.tag2 = pptrs->tag2; } void pre_tag_label_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + pptrs->label.len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_LABEL, pptrs->label.len, (u_char *) pptrs->label.val, PM_MSG_STR_COPY); } void NF_flows_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t t32 = 0; u_int64_t t64 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FLOWS].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOWS].off, 4); pdata->flo_num = ntohl(t32); } else if (tpl->tpl[NF9_FLOWS].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FLOWS].off, 8); pdata->flo_num = pm_ntohll(t64); } if (!pdata->flo_num) pdata->flo_num = 1; break; case 5: pdata->flo_num = 1; break; default: break; } } void NF_in_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t iface16 = 0; u_int32_t iface32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_INPUT_SNMP].len == 2) { memcpy(&iface16, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, 2); pdata->primitives.ifindex_in = ntohs(iface16); } else if (tpl->tpl[NF9_INPUT_SNMP].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, 4); pdata->primitives.ifindex_in = ntohl(iface32); } else if (tpl->tpl[NF9_INPUT_PHYSINT].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_INPUT_PHYSINT].off, 4); pdata->primitives.ifindex_in = ntohl(iface32); } break; case 5: iface16 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->input); pdata->primitives.ifindex_in = iface16; break; default: break; } } void NF_out_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t iface16 = 0; u_int32_t iface32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_OUTPUT_SNMP].len == 2) { memcpy(&iface16, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, 2); pdata->primitives.ifindex_out = ntohs(iface16); } else if (tpl->tpl[NF9_OUTPUT_SNMP].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, 4); pdata->primitives.ifindex_out = ntohl(iface32); } else if (tpl->tpl[NF9_OUTPUT_PHYSINT].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_PHYSINT].off, 4); pdata->primitives.ifindex_out = ntohl(iface32); } break; case 5: iface16 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->output); pdata->primitives.ifindex_out = iface16; break; default: break; } } void NF_sampling_rate_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status; struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status; struct xflow_status_entry_sampling *sentry = NULL; struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t srate = 0; u_int16_t t16 = 0; u_int32_t sampler_id = 0, sample_pool = 0, t32 = 0; u_int8_t t8 = 0; u_int64_t t64 = 0; pdata->primitives.sampling_rate = 0; /* 0 = unknown */ if (config.sampling_map) { if (sampling_map_caching && xsentry && timeval_cmp(&xsentry->st.stamp, &reload_map_tstamp) > 0) { pdata->primitives.sampling_rate = xsentry->st.tag; } else { find_id_func((struct id_table *)pptrs->sampling_table, pptrs, (pm_id_t *) &pdata->primitives.sampling_rate, NULL); if (xsentry) { xsentry->st.tag = pdata->primitives.sampling_rate; gettimeofday(&xsentry->st.stamp, NULL); } } } if (pdata->primitives.sampling_rate == 0) { /* 0 = still unknown */ switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len || tpl->tpl[NF9_SELECTOR_ID].len == 8) { if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 1) { memcpy(&t8, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 1); sampler_id = t8; } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 2); sampler_id = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 4); sampler_id = ntohl(t32); } else if (tpl->tpl[NF9_SELECTOR_ID].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SELECTOR_ID].off, 8); sampler_id = pm_ntohll(t64); /* XXX: sampler_id to be moved to 64 bit */ } if (entry) { sentry = search_smp_id_status_table(entry->sampling, sampler_id, TRUE); if (!sentry && pptrs->f_status_g) { entry = (struct xflow_status_entry *) pptrs->f_status_g; sentry = search_smp_id_status_table(entry->sampling, sampler_id, FALSE); } } if (sentry) pdata->primitives.sampling_rate = sentry->sample_pool; } /* SAMPLING_INTERVAL part of the NetFlow v9/IPFIX record seems to be reality, ie. FlowMon by Invea-Tech */ else if (tpl->tpl[NF9_SAMPLING_INTERVAL].len || tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len) { if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 2); sample_pool = ntohs(t16); } else if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 4); sample_pool = ntohl(t32); } if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 2); sample_pool = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 4); sample_pool = ntohl(t32); } pdata->primitives.sampling_rate = sample_pool; } /* case of no SAMPLER_ID, ALU & IPFIX */ else { if (entry) { sentry = search_smp_id_status_table(entry->sampling, 0, TRUE); if (!sentry && pptrs->f_status_g) { entry = (struct xflow_status_entry *) pptrs->f_status_g; sentry = search_smp_id_status_table(entry->sampling, 0, FALSE); } } if (sentry) pdata->primitives.sampling_rate = sentry->sample_pool; } break; case 5: /* is_sampled = ( ntohs(hdr->sampling) & 0xC000 ); */ srate = ( ntohs(hdr->sampling) & 0x3FFF ); if (srate) pdata->primitives.sampling_rate = srate; break; default: break; } } if (config.sfacctd_renormalize && pdata->primitives.sampling_rate) { pdata->primitives.sampling_rate = 1; /* already renormalized */ } } void NF_sampling_direction_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t direction8; int direction = ERR; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DIRECTION].len == 1) { memcpy(&direction8, pptrs->f_data+tpl->tpl[NF9_DIRECTION].off, 1); direction = direction8; } break; default: break; } switch(direction) { case 0: pdata->primitives.sampling_direction = SAMPLING_DIRECTION_INGRESS; break; case 1: pdata->primitives.sampling_direction = SAMPLING_DIRECTION_EGRESS; break; default: pdata->primitives.sampling_direction = SAMPLING_DIRECTION_UNKNOWN; break; } } void NF_timestamp_start_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); time_t fstime = 0; u_int32_t t32 = 0; u_int64_t t64 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FIRST_SWITCHED].len && hdr->version == 9) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED].off, tpl->tpl[NF9_FIRST_SWITCHED].len); pnat->timestamp_start.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime))/1000); } else if (tpl->tpl[NF9_FIRST_SWITCHED].len && hdr->version == 10) { if (tpl->tpl[NF9_SYS_UPTIME_MSEC].len == 8) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED].off, tpl->tpl[NF9_FIRST_SWITCHED].len); memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SYS_UPTIME_MSEC].off, tpl->tpl[NF9_SYS_UPTIME_MSEC].len); t32 = pm_ntohll(t64)/1000; pnat->timestamp_start.tv_sec = t32+(ntohl(fstime)/1000); } } else if (tpl->tpl[NF9_FIRST_SWITCHED_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_MSEC].off, tpl->tpl[NF9_FIRST_SWITCHED_MSEC].len); pnat->timestamp_start.tv_sec = pm_ntohll(t64)/1000; pnat->timestamp_start.tv_usec = (pm_ntohll(t64)%1000)*1000; } else if (tpl->tpl[NF9_OBSERVATION_TIME_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_OBSERVATION_TIME_MSEC].off, tpl->tpl[NF9_OBSERVATION_TIME_MSEC].len); pnat->timestamp_start.tv_sec = pm_ntohll(t64)/1000; pnat->timestamp_start.tv_usec = (pm_ntohll(t64)%1000)*1000; } else if (tpl->tpl[NF9_FIRST_SWITCHED_USEC].len) { if (tpl->tpl[NF9_FIRST_SWITCHED_USEC].len == 16) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_USEC].off, 8); pnat->timestamp_start.tv_sec = pm_ntohll(t64); memcpy(&t64, (pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_USEC].off+8), 8); pnat->timestamp_start.tv_usec = pm_ntohll(t64); } } /* sec handling here: msec vs sec restricted to NetFlow v5 */ else if (tpl->tpl[NF9_FIRST_SWITCHED_SEC].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_SEC].off, tpl->tpl[NF9_FIRST_SWITCHED_SEC].len); pnat->timestamp_start.tv_sec = ntohl(t32); } else if (tpl->tpl[NF9_FIRST_SWITCHED_SEC].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_SEC].off, tpl->tpl[NF9_FIRST_SWITCHED_SEC].len); pnat->timestamp_start.tv_sec = pm_ntohll(t64); } else if (tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].len && hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; u_int32_t t32h = 0, h32h = 0; u_int64_t t64_1 = 0, t64_2 = 0; memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].off, tpl->tpl[NF9_FIRST_SWITCHED_DELTA_MICRO].len); t32h = ntohl(t32); h32h = ntohl(hdr_ipfix->unix_secs); t64 = h32h; t64 = t64 * 1000 * 1000; t64 -= t32h; t64_1 = (t64 / (1000 * 1000)); t64_2 = (t64 % (1000 * 1000)); pnat->timestamp_start.tv_sec = t64_1; pnat->timestamp_start.tv_usec = t64_2; } /* fallback to header timestamp if no other time reference is available */ if (!pnat->timestamp_start.tv_sec) { if (hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; pnat->timestamp_start.tv_sec = ntohl(hdr_ipfix->unix_secs); } else if (hdr->version == 9) { struct struct_header_v9 *hdr_v9 = (struct struct_header_v9 *) pptrs->f_header; pnat->timestamp_start.tv_sec = ntohl(hdr_v9->unix_secs); } } break; case 5: pnat->timestamp_start.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime)-ntohl(((struct struct_export_v5 *) pptrs->f_data)->First))/1000); break; default: break; } if (chptr->plugin->cfg.timestamps_secs) pnat->timestamp_start.tv_usec = 0; } void NF_timestamp_end_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); time_t fstime = 0; u_int32_t t32 = 0; u_int64_t t64 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_LAST_SWITCHED].len && hdr->version == 9) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED].off, tpl->tpl[NF9_LAST_SWITCHED].len); pnat->timestamp_end.tv_sec = ntohl(((struct struct_header_v9 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v9 *) pptrs->f_header)->SysUptime)-ntohl(fstime))/1000); } else if (tpl->tpl[NF9_LAST_SWITCHED].len && hdr->version == 10) { if (tpl->tpl[NF9_SYS_UPTIME_MSEC].len == 8) { memcpy(&fstime, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED].off, tpl->tpl[NF9_LAST_SWITCHED].len); memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SYS_UPTIME_MSEC].off, tpl->tpl[NF9_SYS_UPTIME_MSEC].len); t32 = pm_ntohll(t64)/1000; pnat->timestamp_end.tv_sec = t32+(ntohl(fstime)/1000); } } else if (tpl->tpl[NF9_LAST_SWITCHED_MSEC].len) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_MSEC].off, tpl->tpl[NF9_LAST_SWITCHED_MSEC].len); pnat->timestamp_end.tv_sec = pm_ntohll(t64)/1000; pnat->timestamp_end.tv_usec = (pm_ntohll(t64)%1000)*1000; } else if (tpl->tpl[NF9_LAST_SWITCHED_USEC].len) { if (tpl->tpl[NF9_LAST_SWITCHED_USEC].len == 16) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_USEC].off, 8); pnat->timestamp_end.tv_sec = pm_ntohll(t64); memcpy(&t64, (pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_USEC].off+8), 8); pnat->timestamp_end.tv_usec = pm_ntohll(t64); } } /* sec handling here: msec vs sec restricted to NetFlow v5 */ else if (tpl->tpl[NF9_LAST_SWITCHED_SEC].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_SEC].off, tpl->tpl[NF9_LAST_SWITCHED_SEC].len); pnat->timestamp_end.tv_sec = ntohl(t32); } else if (tpl->tpl[NF9_LAST_SWITCHED_SEC].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_SEC].off, tpl->tpl[NF9_LAST_SWITCHED_SEC].len); pnat->timestamp_end.tv_sec = pm_ntohll(t64); } else if (tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].len && hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; u_int32_t t32h = 0, h32h = 0; u_int64_t t64_1 = 0, t64_2 = 0; memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].off, tpl->tpl[NF9_LAST_SWITCHED_DELTA_MICRO].len); t32h = ntohl(t32); h32h = ntohl(hdr_ipfix->unix_secs); t64 = h32h; t64 = t64 * 1000 * 1000; t64 -= t32h; t64_1 = (t64 / (1000 * 1000)); t64_2 = (t64 % (1000 * 1000)); pnat->timestamp_end.tv_sec = t64_1; pnat->timestamp_end.tv_usec = t64_2; } break; case 5: pnat->timestamp_end.tv_sec = ntohl(((struct struct_header_v5 *) pptrs->f_header)->unix_secs)- ((ntohl(((struct struct_header_v5 *) pptrs->f_header)->SysUptime)-ntohl(((struct struct_export_v5 *) pptrs->f_data)->Last))/1000); break; default: break; } if (chptr->plugin->cfg.timestamps_secs) pnat->timestamp_end.tv_usec = 0; } void NF_timestamp_arrival_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); gettimeofday(&pnat->timestamp_arrival, NULL); if (chptr->plugin->cfg.timestamps_secs) pnat->timestamp_arrival.tv_usec = 0; } void NF_timestamp_export_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); switch(hdr->version) { case 10: case 9: if (hdr->version == 10) { struct struct_header_ipfix *hdr_ipfix = (struct struct_header_ipfix *) pptrs->f_header; pnat->timestamp_export.tv_sec = ntohl(hdr_ipfix->unix_secs); } else if (hdr->version == 9) { struct struct_header_v9 *hdr_v9 = (struct struct_header_v9 *) pptrs->f_header; pnat->timestamp_export.tv_sec = ntohl(hdr_v9->unix_secs); } break; case 5: pnat->timestamp_export.tv_sec = ntohl(hdr->unix_secs); break; default: break; } } void NF_sequence_number_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; switch(hdr->version) { case 10: pdata->primitives.export_proto_seqno = ntohl(((struct struct_header_ipfix *) pptrs->f_header)->flow_sequence); break; case 9: pdata->primitives.export_proto_seqno = ntohl(((struct struct_header_v9 *) pptrs->f_header)->flow_sequence); break; case 5: pdata->primitives.export_proto_seqno = ntohl(((struct struct_header_v5 *) pptrs->f_header)->flow_sequence); break; default: break; } } void NF_version_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; pdata->primitives.export_proto_version = hdr->version; } void NF_sysid_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; switch(hdr->version) { case 10: pdata->primitives.export_proto_sysid = ntohl(((struct struct_header_ipfix *) pptrs->f_header)->source_id); break; case 9: pdata->primitives.export_proto_sysid = ntohl(((struct struct_header_v9 *) pptrs->f_header)->source_id); break; case 5: pdata->primitives.export_proto_sysid = ((struct struct_header_v5 *) pptrs->f_header)->engine_id; /* XXX: engine type? */ break; default: break; } } void NF_custom_primitives_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct otpl_field *otpl = NULL; struct utpl_field *utpl = NULL; u_char *pcust = (u_char *)((*data) + chptr->extras.off_custom_primitives); struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); struct custom_primitive_entry *cpe; int cpptrs_idx; switch(hdr->version) { case 10: case 9: for (cpptrs_idx = 0; cpptrs_idx < chptr->plugin->cfg.cpptrs.num; cpptrs_idx++) { if (chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].ptr) { cpe = chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].ptr; if (cpe->field_type < NF9_MAX_DEFINED_FIELD && !cpe->pen) { if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { unsigned char hexbuf[cpe->alloc_len]; int hexbuflen = 0; hexbuflen = serialize_hex(pptrs->f_data+tpl->tpl[cpe->field_type].off, hexbuf, tpl->tpl[cpe->field_type].len); if (cpe->alloc_len < hexbuflen) hexbuf[cpe->alloc_len-1] = '\0'; memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, hexbuf, MIN(hexbuflen, cpe->alloc_len)); } else { if (tpl->tpl[cpe->field_type].len == cpe->len) { memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, pptrs->f_data+tpl->tpl[cpe->field_type].off, cpe->len); } else { if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_STRING && cpe->len == PM_VARIABLE_LENGTH) { otpl = &tpl->tpl[cpe->field_type]; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + otpl->len + 1 /* terminating zero */)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, cpe->type, otpl->len, pptrs->f_data+otpl->off, PM_MSG_STR_COPY_ZERO); } } } } else { if ((utpl = (*get_ext_db_ie_by_type)(tpl, cpe->pen, cpe->field_type, cpe->repeat_id))) { if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { unsigned char hexbuf[cpe->alloc_len]; int hexbuflen = 0; hexbuflen = serialize_hex(pptrs->f_data+utpl->off, hexbuf, utpl->len); if (cpe->alloc_len < hexbuflen) hexbuf[cpe->alloc_len-1] = '\0'; if (cpe->len == PM_VARIABLE_LENGTH) { if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + hexbuflen)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, cpe->type, hexbuflen, hexbuf, PM_MSG_BIN_COPY); } else memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, hexbuf, MIN(hexbuflen, cpe->alloc_len)); } else { if (utpl->len == cpe->len) { memcpy(pcust+chptr->plugin->cfg.cpptrs.primitive[cpptrs_idx].off, pptrs->f_data+utpl->off, cpe->len); } else { if (cpe->semantics == CUSTOM_PRIMITIVE_TYPE_STRING && cpe->len == PM_VARIABLE_LENGTH) { if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + utpl->len + 1 /* terminating zero */)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, cpe->type, utpl->len, pptrs->f_data+utpl->off, PM_MSG_STR_COPY_ZERO); } } } } } } } if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) custom_primitives_handler(chptr, pptrs, data); break; default: break; } } void NF_post_nat_src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP) { if (tpl->tpl[NF9_POST_NAT_IPV4_SRC_ADDR].len) { memcpy(&pnat->post_nat_src_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_POST_NAT_IPV4_SRC_ADDR].off, MIN(tpl->tpl[NF9_POST_NAT_IPV4_SRC_ADDR].len, 4)); pnat->post_nat_src_ip.family = AF_INET; } else if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_ASA_XLATE_IPV4_SRC_ADDR, FALSE))) { memcpy(&pnat->post_nat_src_ip.address.ipv4, pptrs->f_data+utpl->off, MIN(utpl->len, 4)); pnat->post_nat_src_ip.family = AF_INET; } } break; default: break; } } void NF_post_nat_dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP) { if (tpl->tpl[NF9_POST_NAT_IPV4_DST_ADDR].len) { memcpy(&pnat->post_nat_dst_ip.address.ipv4, pptrs->f_data+tpl->tpl[NF9_POST_NAT_IPV4_DST_ADDR].off, MIN(tpl->tpl[NF9_POST_NAT_IPV4_DST_ADDR].len, 4)); pnat->post_nat_dst_ip.family = AF_INET; } else if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_ASA_XLATE_IPV4_DST_ADDR, FALSE))) { memcpy(&pnat->post_nat_dst_ip.address.ipv4, pptrs->f_data+utpl->off, MIN(utpl->len, 4)); pnat->post_nat_dst_ip.family = AF_INET; } } break; default: break; } } void NF_post_nat_src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct utpl_field *utpl = NULL; u_int8_t l4_proto = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_L4_PROTOCOL].len == 1) memcpy(&l4_proto, pptrs->f_data+tpl->tpl[NF9_L4_PROTOCOL].off, 1); if (tpl->tpl[NF9_POST_NAT_IPV4_SRC_PORT].len) memcpy(&pnat->post_nat_src_port, pptrs->f_data+tpl->tpl[NF9_POST_NAT_IPV4_SRC_PORT].off, MIN(tpl->tpl[NF9_POST_NAT_IPV4_SRC_PORT].len, 2)); else if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_ASA_XLATE_L4_SRC_PORT, FALSE))) memcpy(&pnat->post_nat_src_port, pptrs->f_data+utpl->off, MIN(utpl->len, 2)); pnat->post_nat_src_port = ntohs(pnat->post_nat_src_port); break; default: break; } } void NF_post_nat_dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct utpl_field *utpl = NULL; u_int8_t l4_proto = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_L4_PROTOCOL].len == 1) memcpy(&l4_proto, pptrs->f_data+tpl->tpl[NF9_L4_PROTOCOL].off, 1); if (tpl->tpl[NF9_POST_NAT_IPV4_DST_PORT].len) memcpy(&pnat->post_nat_dst_port, pptrs->f_data+tpl->tpl[NF9_POST_NAT_IPV4_DST_PORT].off, MIN(tpl->tpl[NF9_POST_NAT_IPV4_DST_PORT].len, 2)); else if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_ASA_XLATE_L4_DST_PORT, FALSE))) memcpy(&pnat->post_nat_dst_port, pptrs->f_data+utpl->off, MIN(utpl->len, 2)); pnat->post_nat_dst_port = ntohs(pnat->post_nat_dst_port); break; default: break; } } void NF_nat_event_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_NAT_EVENT].len) { memcpy(&pnat->nat_event, pptrs->f_data+tpl->tpl[NF9_NAT_EVENT].off, MIN(tpl->tpl[NF9_NAT_EVENT].len, 1)); } else if ((utpl = (*get_ext_db_ie_by_type)(tpl, 0, NF9_ASA_XLATE_EVENT, FALSE))) { memcpy(&pnat->nat_event, pptrs->f_data+utpl->off, MIN(utpl->len, 1)); } break; default: break; } } void NF_fw_event_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FW_EVENT].len) { memcpy(&pnat->fw_event, pptrs->f_data+tpl->tpl[NF9_FW_EVENT].off, MIN(tpl->tpl[NF9_FW_EVENT].len, 1)); } break; default: break; } } void NF_mpls_label_stack_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); u_int32_t label_stack[MAX_MPLS_LABELS], label_lookahead = 0; u_int8_t label_stack_depth = 0, label_stack_len = 0, label_idx; memset(&label_stack, 0, sizeof(label_stack)); switch(hdr->version) { case 10: case 9: for (label_idx = NF9_MPLS_LABEL_1; label_idx <= NF9_MPLS_LABEL_10; label_idx++) { if (tpl->tpl[label_idx].len == 3) { label_stack[label_stack_depth] = decode_mpls_label(pptrs->f_data+tpl->tpl[label_idx].off); if (label_stack[label_stack_depth]) { label_stack_len += 4; label_stack_depth++; if (check_bosbit(pptrs->f_data+tpl->tpl[label_idx].off)) { break; } } else { /* handling case of Explicit Null */ if (label_idx == NF9_MPLS_LABEL_1) { if (check_bosbit(pptrs->f_data+tpl->tpl[label_idx].off)) { label_stack_len += 4; label_stack_depth++; break; } /* looking ahead */ else { if (tpl->tpl[label_idx + 1].len == 3) { label_lookahead = decode_mpls_label(pptrs->f_data+tpl->tpl[label_idx + 1].off); if (label_lookahead) { label_stack_len += 4; label_stack_depth++; } } } } else { break; } } } } if (!label_stack_depth) { if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) { mpls_label_stack_handler(chptr, pptrs, data); } } break; default: break; } if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + label_stack_len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_MPLS_LABEL_STACK, label_stack_len, (u_char *) label_stack, PM_MSG_BIN_COPY); } void NF_mpls_label_top_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_MPLS_LABEL_1].len == 3) pmpls->mpls_label_top = decode_mpls_label(pptrs->f_data+tpl->tpl[NF9_MPLS_LABEL_1].off); else if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) mpls_label_top_handler(chptr, pptrs, data); break; default: break; } } void NF_mpls_label_bottom_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); int label_idx; switch(hdr->version) { case 10: case 9: for (label_idx = NF9_MPLS_LABEL_1; label_idx <= NF9_MPLS_LABEL_9; label_idx++) { if (tpl->tpl[label_idx].len == 3 && check_bosbit(pptrs->f_data+tpl->tpl[label_idx].off)) { pmpls->mpls_label_bottom = decode_mpls_label(pptrs->f_data+tpl->tpl[label_idx].off); break; } } if (!pmpls->mpls_label_bottom) { if (tpl->tpl[NF9_DATALINK_FRAME_SECTION].len || tpl->tpl[NF9_LAYER2_PKT_SECTION_DATA].len) mpls_label_bottom_handler(chptr, pptrs, data); } break; default: break; } } void NF_mpls_vpn_id_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status_g; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int32_t ingress_vrfid = 0, egress_vrfid = 0; u_int8_t direction = 0; rd_t *rd = NULL; int ret; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DIRECTION].len) { memcpy(&direction, pptrs->f_data+tpl->tpl[NF9_DIRECTION].off, MIN(tpl->tpl[NF9_DIRECTION].len, 1)); } if (!pbgp->mpls_vpn_rd.val) { if (tpl->tpl[NF9_INGRESS_VRFID].len) { memcpy(&ingress_vrfid, pptrs->f_data+tpl->tpl[NF9_INGRESS_VRFID].off, MIN(tpl->tpl[NF9_INGRESS_VRFID].len, 4)); ingress_vrfid = ntohl(ingress_vrfid); } if (tpl->tpl[NF9_EGRESS_VRFID].len) { memcpy(&egress_vrfid, pptrs->f_data+tpl->tpl[NF9_EGRESS_VRFID].off, MIN(tpl->tpl[NF9_EGRESS_VRFID].len, 4)); egress_vrfid = ntohl(egress_vrfid); } } if (ingress_vrfid && (!direction /* 0 = ingress */ || !egress_vrfid)) { if (entry->in_rd_map) { ret = cdada_map_find(entry->in_rd_map, &ingress_vrfid, (void **) &rd); if (ret == CDADA_SUCCESS) { memcpy(&pbgp->mpls_vpn_rd, rd, 8); bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } } else { pbgp->mpls_vpn_rd.val = ingress_vrfid; if (pbgp->mpls_vpn_rd.val) { pbgp->mpls_vpn_rd.type = RD_TYPE_VRFID; bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } } } if (egress_vrfid && (direction /* 1 = egress */ || !ingress_vrfid)) { if (entry->out_rd_map) { ret = cdada_map_find(entry->out_rd_map, &egress_vrfid, (void **) &rd); if (ret == CDADA_SUCCESS) { memcpy(&pbgp->mpls_vpn_rd, rd, 8); bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } } else { pbgp->mpls_vpn_rd.val = egress_vrfid; if (pbgp->mpls_vpn_rd.val) { pbgp->mpls_vpn_rd.type = RD_TYPE_VRFID; bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } } } break; default: break; } } void NF_mpls_vpn_rd_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_MPLS_VPN_RD].len && !pbgp->mpls_vpn_rd.val) { memcpy(&pbgp->mpls_vpn_rd, pptrs->f_data+tpl->tpl[NF9_MPLS_VPN_RD].off, MIN(tpl->tpl[NF9_MPLS_VPN_RD].len, 8)); bgp_rd_ntoh(&pbgp->mpls_vpn_rd); bgp_rd_origin_set(&pbgp->mpls_vpn_rd, RD_ORIGIN_FLOW); } break; default: break; } } void NF_mpls_pw_id_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); u_int32_t tmp32; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PSEUDOWIREID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_PSEUDOWIREID].off, 4); pbgp->mpls_pw_id = ntohl(tmp32); } break; default: break; } } void NF_vxlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); u_char *vni_ptr = NULL, tmp64[8]; u_int8_t *type = NULL; //Make compiler happy memset(tmp64, 0, sizeof(tmp64)); switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_LAYER2_SEGMENT_ID].len == 8) { memcpy(tmp64, pptrs->f_data+tpl->tpl[NF9_LAYER2_SEGMENT_ID].off, 8); type = (u_int8_t *) &tmp64[0]; if ((*type) == NF9_L2_SID_VXLAN) { vni_ptr = &tmp64[5]; ptun->tunnel_id = *vni_ptr++; ptun->tunnel_id <<= 8; ptun->tunnel_id += *vni_ptr++; ptun->tunnel_id <<= 8; ptun->tunnel_id += *vni_ptr++; } } break; default: break; } } void NF_class_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_APPLICATION_ID].len) { pdata->primitives.class = pptrs->class; } break; default: break; } } #if defined (WITH_NDPI) void NF_ndpi_class_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; memcpy(&pdata->primitives.ndpi_class, &pptrs->ndpi_class, sizeof(pm_class2_t)); } #endif void NF_cust_tag_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: if ((utpl = (*get_ext_db_ie_by_type)(tpl, PMACCT_PEN, NF9_CUST_TAG, FALSE))) { memcpy(&pdata->primitives.tag, pptrs->f_data+utpl->off, MIN(utpl->len, 8)); pdata->primitives.tag = pm_ntohll(pdata->primitives.tag); } break; default: break; } } void NF_cust_tag2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: if ((utpl = (*get_ext_db_ie_by_type)(tpl, PMACCT_PEN, NF9_CUST_TAG2, FALSE))) { memcpy(&pdata->primitives.tag2, pptrs->f_data+utpl->off, MIN(utpl->len, 8)); pdata->primitives.tag2 = pm_ntohll(pdata->primitives.tag2); } break; default: break; } } void NF_cust_label_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct utpl_field *utpl = NULL; switch(hdr->version) { case 10: if ((utpl = (*get_ext_db_ie_by_type)(tpl, PMACCT_PEN, NF9_CUST_LABEL, FALSE))) { return_pipe_buffer_space(chptr, vlen_prims_delete(pvlen, COUNT_INT_LABEL)); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + utpl->len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_LABEL, utpl->len, pptrs->f_data+utpl->off, PM_MSG_STR_COPY); } break; default: break; } } void NF_counters_renormalize_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status; struct xflow_status_entry_sampling *sentry = NULL; struct pkt_data *pdata = (struct pkt_data *) *data; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t srate = 0, is_sampled = 0; u_int16_t t16 = 0; u_int32_t sampler_id = 0, sample_pool = 0, t32 = 0; u_int8_t t8 = 0; u_int64_t t64 = 0; if (pptrs->renormalized) return; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len || tpl->tpl[NF9_SELECTOR_ID].len == 8) { if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 1) { memcpy(&t8, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 1); sampler_id = t8; } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 2); sampler_id = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_ID].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_ID].off, 4); sampler_id = ntohl(t32); } else if (tpl->tpl[NF9_SELECTOR_ID].len == 8) { memcpy(&t64, pptrs->f_data+tpl->tpl[NF9_SELECTOR_ID].off, 8); sampler_id = pm_ntohll(t64); /* XXX: sampler_id to be moved to 64 bit */ } if (entry) { sentry = search_smp_id_status_table(entry->sampling, sampler_id, TRUE); if (!sentry && pptrs->f_status_g) { entry = (struct xflow_status_entry *) pptrs->f_status_g; sentry = search_smp_id_status_table(entry->sampling, sampler_id, FALSE); } } if (sentry) { pdata->pkt_len = pdata->pkt_len * sentry->sample_pool; pdata->pkt_num = pdata->pkt_num * sentry->sample_pool; pptrs->renormalized = TRUE; } } /* SAMPLING_INTERVAL part of the NetFlow v9/IPFIX record seems to be reality, ie. FlowMon by Invea-Tech */ else if (tpl->tpl[NF9_SAMPLING_INTERVAL].len || tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len) { if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 2); sample_pool = ntohs(t16); } else if (tpl->tpl[NF9_SAMPLING_INTERVAL].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_SAMPLING_INTERVAL].off, 4); sample_pool = ntohl(t32); } if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 2) { memcpy(&t16, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 2); sample_pool = ntohs(t16); } else if (tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].len == 4) { memcpy(&t32, pptrs->f_data+tpl->tpl[NF9_FLOW_SAMPLER_INTERVAL].off, 4); sample_pool = ntohl(t32); } pdata->pkt_len = pdata->pkt_len * sample_pool; pdata->pkt_num = pdata->pkt_num * sample_pool; pptrs->renormalized = TRUE; } /* case of no SAMPLER_ID, ALU & IPFIX */ else { if (entry) { sentry = search_smp_id_status_table(entry->sampling, 0, TRUE); if (!sentry && pptrs->f_status_g) { entry = (struct xflow_status_entry *) pptrs->f_status_g; sentry = search_smp_id_status_table(entry->sampling, 0, FALSE); } if (!sentry) sentry = search_smp_id_status_table(entry->sampling, ntohs(tpl->template_id), FALSE); } if (sentry) { pdata->pkt_len = pdata->pkt_len * sentry->sample_pool; pdata->pkt_num = pdata->pkt_num * sentry->sample_pool; pptrs->renormalized = TRUE; } } break; case 5: is_sampled = ( ntohs(hdr->sampling) & 0xC000 ); (void)is_sampled; srate = ( ntohs(hdr->sampling) & 0x3FFF ); /* XXX: checking srate value instead of is_sampled as Sampling Mode seems not to be a mandatory field. */ if (srate) { pdata->pkt_len = pdata->pkt_len * srate; pdata->pkt_num = pdata->pkt_num * srate; pptrs->renormalized = TRUE; } break; default: break; } } void NF_counters_map_renormalize_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status; if (pptrs->renormalized) return; if (sampling_map_caching && xsentry && timeval_cmp(&xsentry->st.stamp, &reload_map_tstamp) > 0) { pptrs->st = xsentry->st.tag; } else { find_id_func((struct id_table *)pptrs->sampling_table, pptrs, &pptrs->st, NULL); if (xsentry) { xsentry->st.tag = pptrs->st; gettimeofday(&xsentry->st.stamp, NULL); } } if (pptrs->st) { pdata->pkt_len = pdata->pkt_len * pptrs->st; pdata->pkt_num = pdata->pkt_num * pptrs->st; pptrs->renormalized = TRUE; } } void bgp_ext_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); struct pkt_legacy_bgp_primitives *plbgp = (struct pkt_legacy_bgp_primitives *) ((*data) + chptr->extras.off_pkt_lbgp_primitives); struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info = NULL; /* variables for vlen primitives */ char empty_str = '\0', *ptr = &empty_str; int len; if (src_ret && evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_SRC_AS && info->attr->aspath) { pdata->primitives.src_as = evaluate_last_asn(info->attr->aspath); if (!pdata->primitives.src_as && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &pdata->primitives.src_as, TRUE); } } if (!pdata->primitives.src_as && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &pdata->primitives.src_as, TRUE); } } } } if (chptr->aggregation & COUNT_SRC_AS_PATH && info->attr->aspath && info->attr->aspath->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->aspath->str); if (len && (config.bgp_daemon_src_as_path_type & BGP_SRC_PRIMITIVES_BGP)) { len++; if (config.bgp_daemon_aspath_radius) { ptr = strndup(info->attr->aspath->str, len); if (ptr) { evaluate_bgp_aspath_radius(ptr, len, config.bgp_daemon_aspath_radius); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->aspath->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_SRC_AS_PATH, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_aspath_radius && ptr && len) free(ptr); } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_src_as_path_type & BGP_SRC_PRIMITIVES_BGP) { strlcpy(plbgp->src_as_path, info->attr->aspath->str, MAX_BGP_ASPATH); if (strlen(info->attr->aspath->str) >= MAX_BGP_ASPATH) { plbgp->src_as_path[MAX_BGP_ASPATH-2] = '+'; plbgp->src_as_path[MAX_BGP_ASPATH-1] = '\0'; } if (config.bgp_daemon_aspath_radius) evaluate_bgp_aspath_radius(plbgp->src_as_path, MAX_BGP_ASPATH, config.bgp_daemon_aspath_radius); } else plbgp->src_as_path[0] = '\0'; } } if (chptr->aggregation & COUNT_SRC_STD_COMM && info->attr->community && info->attr->community->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->community->str); if (len && (config.bgp_daemon_src_std_comm_type & BGP_SRC_PRIMITIVES_BGP)) { len++; if (config.bgp_daemon_stdcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->community->str, std_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->community->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_SRC_STD_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_stdcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_src_std_comm_type & BGP_SRC_PRIMITIVES_BGP) { if (config.bgp_daemon_stdcomm_pattern) evaluate_comm_patterns(plbgp->src_std_comms, info->attr->community->str, std_comm_patterns, MAX_BGP_STD_COMMS); else { strlcpy(plbgp->src_std_comms, info->attr->community->str, MAX_BGP_STD_COMMS); if (strlen(info->attr->community->str) >= MAX_BGP_STD_COMMS) { plbgp->src_std_comms[MAX_BGP_STD_COMMS-2] = '+'; plbgp->src_std_comms[MAX_BGP_STD_COMMS-1] = '\0'; } } } else plbgp->src_std_comms[0] = '\0'; } } if (chptr->aggregation & COUNT_SRC_EXT_COMM && info->attr->ecommunity && info->attr->ecommunity->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->ecommunity->str); if (len && (config.bgp_daemon_src_ext_comm_type & BGP_SRC_PRIMITIVES_BGP)) { len++; if (config.bgp_daemon_extcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->ecommunity->str, ext_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->ecommunity->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_SRC_EXT_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_extcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_src_ext_comm_type & BGP_SRC_PRIMITIVES_BGP) { if (config.bgp_daemon_extcomm_pattern) evaluate_comm_patterns(plbgp->src_ext_comms, info->attr->ecommunity->str, ext_comm_patterns, MAX_BGP_EXT_COMMS); else { strlcpy(plbgp->src_ext_comms, info->attr->ecommunity->str, MAX_BGP_EXT_COMMS); if (strlen(info->attr->ecommunity->str) >= MAX_BGP_EXT_COMMS) { plbgp->src_ext_comms[MAX_BGP_EXT_COMMS-2] = '+'; plbgp->src_ext_comms[MAX_BGP_EXT_COMMS-1] = '\0'; } } } else plbgp->src_ext_comms[0] = '\0'; } } if (chptr->aggregation_2 & COUNT_SRC_LRG_COMM && info->attr->lcommunity && info->attr->lcommunity->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->lcommunity->str); if (len && (config.bgp_daemon_src_lrg_comm_type & BGP_SRC_PRIMITIVES_BGP)) { len++; if (config.bgp_daemon_lrgcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->lcommunity->str, lrg_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->lcommunity->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_SRC_LRG_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_lrgcomm_pattern && ptr && len) free(ptr); } } else { if (config.bgp_daemon_src_lrg_comm_type & BGP_SRC_PRIMITIVES_BGP) { if (config.bgp_daemon_lrgcomm_pattern) evaluate_comm_patterns(plbgp->src_lrg_comms, info->attr->lcommunity->str, lrg_comm_patterns, MAX_BGP_LRG_COMMS); else { strlcpy(plbgp->src_lrg_comms, info->attr->lcommunity->str, MAX_BGP_LRG_COMMS); if (strlen(info->attr->lcommunity->str) >= MAX_BGP_LRG_COMMS) { plbgp->src_lrg_comms[MAX_BGP_LRG_COMMS-2] = '+'; plbgp->src_lrg_comms[MAX_BGP_LRG_COMMS-1] = '\0'; } } } else plbgp->src_lrg_comms[0] = '\0'; } } if (chptr->aggregation & COUNT_SRC_LOCAL_PREF && config.bgp_daemon_src_local_pref_type & BGP_SRC_PRIMITIVES_BGP) pbgp->src_local_pref = info->attr->local_pref; if (chptr->aggregation & COUNT_SRC_MED && config.bgp_daemon_src_med_type & BGP_SRC_PRIMITIVES_BGP) pbgp->src_med = info->attr->med; if (chptr->aggregation_2 & COUNT_SRC_ROA && config.bgp_daemon_src_roa_type & BGP_SRC_PRIMITIVES_BGP) pbgp->src_roa = pptrs->src_roa; if (chptr->aggregation & COUNT_PEER_SRC_AS && config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_BGP && info->attr->aspath && info->attr->aspath->str) { pbgp->peer_src_as = evaluate_first_asn(info->attr->aspath->str); if (!pbgp->peer_src_as && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &pbgp->peer_src_as, FALSE); } } if (!pbgp->peer_src_as && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &pbgp->peer_src_as, FALSE); } } } } } /* take care of vlen primitives */ else { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { if (chptr->aggregation & COUNT_SRC_AS_PATH) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_SRC_AS_PATH, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation & COUNT_SRC_STD_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_SRC_STD_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation & COUNT_SRC_EXT_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_SRC_EXT_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation_2 & COUNT_SRC_LRG_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_SRC_LRG_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } } } if (dst_ret && evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (chptr->aggregation & COUNT_STD_COMM && info->attr->community && info->attr->community->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->community->str); if (len) { len++; if (config.bgp_daemon_stdcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->community->str, std_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->community->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_STD_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_stdcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_stdcomm_pattern) evaluate_comm_patterns(plbgp->std_comms, info->attr->community->str, std_comm_patterns, MAX_BGP_STD_COMMS); else { strlcpy(plbgp->std_comms, info->attr->community->str, MAX_BGP_STD_COMMS); if (strlen(info->attr->community->str) >= MAX_BGP_STD_COMMS) { plbgp->std_comms[MAX_BGP_STD_COMMS-2] = '+'; plbgp->std_comms[MAX_BGP_STD_COMMS-1] = '\0'; } } } } if (chptr->aggregation & COUNT_EXT_COMM && info->attr->ecommunity && info->attr->ecommunity->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->ecommunity->str); if (len) { len++; if (config.bgp_daemon_extcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->ecommunity->str, ext_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->ecommunity->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_EXT_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_extcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_extcomm_pattern) evaluate_comm_patterns(plbgp->ext_comms, info->attr->ecommunity->str, ext_comm_patterns, MAX_BGP_EXT_COMMS); else { strlcpy(plbgp->ext_comms, info->attr->ecommunity->str, MAX_BGP_EXT_COMMS); if (strlen(info->attr->ecommunity->str) >= MAX_BGP_EXT_COMMS) { plbgp->ext_comms[MAX_BGP_EXT_COMMS-2] = '+'; plbgp->ext_comms[MAX_BGP_EXT_COMMS-1] = '\0'; } } } } if (chptr->aggregation_2 & COUNT_LRG_COMM && info->attr->lcommunity && info->attr->lcommunity->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->lcommunity->str); if (len) { len++; if (config.bgp_daemon_lrgcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, info->attr->lcommunity->str, lrg_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->lcommunity->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_LRG_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_lrgcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (config.bgp_daemon_lrgcomm_pattern) evaluate_comm_patterns(plbgp->lrg_comms, info->attr->lcommunity->str, lrg_comm_patterns, MAX_BGP_LRG_COMMS); else { strlcpy(plbgp->lrg_comms, info->attr->lcommunity->str, MAX_BGP_LRG_COMMS); if (strlen(info->attr->lcommunity->str) >= MAX_BGP_LRG_COMMS) { plbgp->lrg_comms[MAX_BGP_LRG_COMMS-2] = '+'; plbgp->lrg_comms[MAX_BGP_LRG_COMMS-1] = '\0'; } } } } if (chptr->aggregation & COUNT_AS_PATH && info->attr->aspath && info->attr->aspath->str) { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(info->attr->aspath->str); if (len) { len++; if (config.bgp_daemon_aspath_radius) { ptr = strndup(info->attr->aspath->str, len); if (ptr) { evaluate_bgp_aspath_radius(ptr, len, config.bgp_daemon_aspath_radius); len = strlen(ptr); len++; } else len = 0; } else ptr = info->attr->aspath->str; } else ptr = &empty_str; if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_AS_PATH, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_aspath_radius && ptr && len) free(ptr); } /* fallback to legacy fixed length behaviour */ else { strlcpy(plbgp->as_path, info->attr->aspath->str, MAX_BGP_ASPATH); if (strlen(info->attr->aspath->str) >= MAX_BGP_ASPATH) { plbgp->as_path[MAX_BGP_ASPATH-2] = '+'; plbgp->as_path[MAX_BGP_ASPATH-1] = '\0'; } if (config.bgp_daemon_aspath_radius) evaluate_bgp_aspath_radius(plbgp->as_path, MAX_BGP_ASPATH, config.bgp_daemon_aspath_radius); } } if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_DST_AS && info->attr->aspath) { pdata->primitives.dst_as = evaluate_last_asn(info->attr->aspath); if (!pdata->primitives.dst_as && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &pdata->primitives.dst_as, TRUE); } } if (!pdata->primitives.dst_as && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &pdata->primitives.dst_as, TRUE); } } } } if (chptr->aggregation & COUNT_LOCAL_PREF) pbgp->local_pref = info->attr->local_pref; if (chptr->aggregation & COUNT_MED) pbgp->med = info->attr->med; if (chptr->aggregation_2 & COUNT_DST_ROA) pbgp->dst_roa = pptrs->dst_roa; if (chptr->aggregation & COUNT_PEER_DST_AS && info->attr->aspath && info->attr->aspath->str) { pbgp->peer_dst_as = evaluate_first_asn(info->attr->aspath->str); if (!pbgp->peer_dst_as && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &pbgp->peer_dst_as, FALSE); } } if (!pbgp->peer_dst_as && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &pbgp->peer_dst_as, FALSE); } } } } } /* take care of vlen primitives */ else { if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { if (chptr->aggregation & COUNT_AS_PATH) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_AS_PATH, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation & COUNT_STD_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_STD_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation & COUNT_EXT_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_EXT_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } if (chptr->aggregation_2 & COUNT_LRG_COMM) { ptr = &empty_str; len = strlen(ptr); if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_LRG_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); } } } } void sfprobe_bgp_ext_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_payload *payload = (struct pkt_payload *) *data; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info = NULL; if (src_ret && evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_SRC_AS && info->attr->aspath) { if (!chptr->plugin->cfg.nfprobe_peer_as) payload->src_as = evaluate_last_asn(info->attr->aspath); else payload->src_as = evaluate_first_asn(info->attr->aspath->str); } } } } if (dst_ret && evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_DST_AS && info->attr->aspath) { if (!chptr->plugin->cfg.nfprobe_peer_as) payload->dst_as = evaluate_last_asn(info->attr->aspath); else payload->dst_as = evaluate_first_asn(info->attr->aspath->str); } } } } } void nfprobe_bgp_ext_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info = NULL; if (src_ret && evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_SRC_AS && info->attr->aspath) { if (!chptr->plugin->cfg.nfprobe_peer_as) pdata->primitives.src_as = evaluate_last_asn(info->attr->aspath); else pdata->primitives.src_as = evaluate_first_asn(info->attr->aspath->str); } } } } if (dst_ret && evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (config.nfacctd_as & NF_AS_BGP) { if (chptr->aggregation & COUNT_DST_AS && info->attr->aspath) { if (!chptr->plugin->cfg.nfprobe_peer_as) pdata->primitives.dst_as = evaluate_last_asn(info->attr->aspath); else pdata->primitives.dst_as = evaluate_first_asn(info->attr->aspath->str); } } } } } void bgp_peer_src_as_frommap_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info = NULL; pbgp->peer_src_as = pptrs->bpas; /* XXX: extra check: was src_as written by copy_stdcomm_to_asn() ? */ if (!pbgp->peer_src_as && config.bgp_daemon_stdcomm_pattern_to_asn) { if (src_ret) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr && info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &pbgp->peer_src_as, FALSE); } } } if (!pbgp->peer_src_as && config.bgp_daemon_lrgcomm_pattern_to_asn) { if (src_ret) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr && info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &pbgp->peer_src_as, FALSE); } } } } void bgp_src_local_pref_frommap_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); pbgp->src_local_pref = pptrs->blp; } void bgp_src_med_frommap_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); pbgp->src_med = pptrs->bmed; } #if defined (HAVE_L2) void SF_src_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; memcpy(pdata->primitives.eth_shost, sample->eth_src, ETH_ADDR_LEN); } void SF_dst_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; memcpy(pdata->primitives.eth_dhost, sample->eth_dst, ETH_ADDR_LEN); } void SF_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.vlan_id = sample->in_vlan; if (!pdata->primitives.vlan_id) pdata->primitives.vlan_id = sample->out_vlan; } void SF_in_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.vlan_id = sample->in_vlan; } void SF_out_vlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.out_vlan_id = sample->out_vlan; } void SF_cos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.cos = sample->in_priority; if (!pdata->primitives.cos) pdata->primitives.cos = sample->out_priority; } void SF_etype_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.etype = sample->eth_type; } #endif void SF_src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *addr = &sample->ipsrc; if (sample->gotIPV4) { pdata->primitives.src_ip.address.ipv4.s_addr = sample->dcd_srcIP.s_addr; pdata->primitives.src_ip.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&pdata->primitives.src_ip.address.ipv6, &addr->address.ip_v6, IP6AddrSz); pdata->primitives.src_ip.family = AF_INET6; } } void SF_dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *addr = &sample->ipdst; if (sample->gotIPV4) { pdata->primitives.dst_ip.address.ipv4.s_addr = sample->dcd_dstIP.s_addr; pdata->primitives.dst_ip.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&pdata->primitives.dst_ip.address.ipv6, &addr->address.ip_v6, IP6AddrSz); pdata->primitives.dst_ip.family = AF_INET6; } } void SF_src_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; pdata->primitives.src_nmask = sample->srcMask; } void SF_dst_nmask_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; pdata->primitives.dst_nmask = sample->dstMask; } void SF_src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; if (sample->dcd_ipProtocol == IPPROTO_UDP || sample->dcd_ipProtocol == IPPROTO_TCP) { pdata->primitives.src_port = sample->dcd_sport; } else pdata->primitives.src_port = 0; } void SF_dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; if (sample->dcd_ipProtocol == IPPROTO_UDP || sample->dcd_ipProtocol == IPPROTO_TCP) { pdata->primitives.dst_port = sample->dcd_dport; } else pdata->primitives.dst_port = 0; } void SF_ip_tos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.tos = sample->dcd_ipTos; if (chptr->plugin->cfg.tos_encode_as_dscp) { pdata->primitives.tos = pdata->primitives.tos >> 2; } } void SF_ip_proto_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.proto = sample->dcd_ipProtocol; } void SF_tcp_flags_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; if (sample->dcd_ipProtocol == IPPROTO_TCP) { pdata->tcp_flags = sample->dcd_tcpFlags; } } void SF_flows_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pdata->flo_num = 1; } void SF_counters_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->pkt_len = sample->sampledPacketSize; pdata->pkt_num = 1; if (!config.nfacctd_time_new && sample->ts) { pdata->time_start.tv_sec = sample->ts->tv_sec; pdata->time_start.tv_usec = sample->ts->tv_usec; } else { pdata->time_start.tv_sec = 0; pdata->time_start.tv_usec = 0; } pdata->time_end.tv_sec = 0; pdata->time_end.tv_usec = 0; pdata->flow_type = pptrs->flow_type.traffic_type; /* XXX: fragment handling */ } void SF_counters_renormalize_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *entry = (struct xflow_status_entry *) pptrs->f_status; struct xflow_status_entry_sampling *sentry = NULL; struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; u_int32_t eff_srate = 0; if (pptrs->renormalized) return; if (entry) sentry = search_smp_if_status_table(entry->sampling, (sample->ds_class << 24 | sample->ds_index)); if (sentry) { /* flow sequence number is strictly increasing; however we need a) to avoid a division-by-zero by checking the last value and the new one and b) to deal with out-of-order datagrams */ if (sample->samplesGenerated > sentry->seqno && sample->samplePool > sentry->sample_pool) { eff_srate = (sample->samplePool-sentry->sample_pool) / (sample->samplesGenerated-sentry->seqno); pdata->pkt_len = pdata->pkt_len * eff_srate; pdata->pkt_num = pdata->pkt_num * eff_srate; sentry->sample_pool = sample->samplePool; sentry->seqno = sample->samplesGenerated; return; } /* Let's handle long positive/negative jumps as resets */ else if (MAX(sample->samplesGenerated, sentry->seqno) > (MIN(sample->samplesGenerated, sentry->seqno)+XFLOW_RESET_BOUNDARY)) { sentry->sample_pool = sample->samplePool; sentry->seqno = sample->samplesGenerated; } } else { if (entry) sentry = create_smp_entry_status_table(&xflow_status_table, entry); if (sentry) { sentry->interface = (sample->ds_class << 24 | sample->ds_index); sentry->sample_pool = sample->samplePool; sentry->seqno = sample->samplesGenerated; } } pdata->pkt_len = pdata->pkt_len * sample->meanSkipCount; pdata->pkt_num = pdata->pkt_num * sample->meanSkipCount; pptrs->renormalized = TRUE; } void SF_counters_map_renormalize_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status; if (pptrs->renormalized) return; if (sampling_map_caching && xsentry && timeval_cmp(&xsentry->st.stamp, &reload_map_tstamp) > 0) { pptrs->st = xsentry->st.tag; } else { find_id_func((struct id_table *)pptrs->sampling_table, pptrs, &pptrs->st, NULL); if (xsentry) { xsentry->st.tag = pptrs->st; gettimeofday(&xsentry->st.stamp, NULL); } } if (pptrs->st) { pdata->pkt_len = pdata->pkt_len * pptrs->st; pdata->pkt_num = pdata->pkt_num * pptrs->st; pptrs->renormalized = TRUE; } } void SF_src_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; pdata->primitives.src_as = sample->src_as; if (chptr->plugin->cfg.nfprobe_peer_as) { if (chptr->aggregation & COUNT_PEER_SRC_AS) pbgp->peer_src_as = pdata->primitives.src_as; pdata->primitives.src_as = 0; } } void SF_dst_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; pdata->primitives.dst_as = sample->dst_as; if (chptr->plugin->cfg.nfprobe_peer_as) { if (chptr->aggregation & COUNT_PEER_DST_AS) pbgp->peer_dst_as = pdata->primitives.dst_as; pdata->primitives.dst_as = 0; } } void SF_as_path_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_legacy_bgp_primitives *plbgp = (struct pkt_legacy_bgp_primitives *) ((*data) + chptr->extras.off_pkt_lbgp_primitives); struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); /* variables for vlen primitives */ char empty_str = '\0', *ptr = &empty_str; int len; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(sample->dst_as_path); if (len) { len++; if (config.bgp_daemon_aspath_radius) { ptr = strndup(sample->dst_as_path, len); if (ptr) { evaluate_bgp_aspath_radius(ptr, len, config.bgp_daemon_aspath_radius); len = strlen(ptr); len++; } else len = 0; } else ptr = sample->dst_as_path; } if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_AS_PATH, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_aspath_radius && ptr && len) free(ptr); } /* fallback to legacy fixed length behaviour */ else { if (sample->dst_as_path_len) { strlcpy(plbgp->as_path, sample->dst_as_path, MAX_BGP_ASPATH); if (strlen(sample->dst_as_path)) { plbgp->as_path[MAX_BGP_ASPATH-2] = '+'; plbgp->as_path[MAX_BGP_ASPATH-1] = '\0'; } if (config.bgp_daemon_aspath_radius) evaluate_bgp_aspath_radius(plbgp->as_path, MAX_BGP_ASPATH, config.bgp_daemon_aspath_radius); } } } void SF_peer_src_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, FALSE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; pbgp->peer_src_as = sample->src_peer_as; } void SF_peer_dst_as_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; pbgp->peer_dst_as = sample->dst_peer_as; } void SF_local_pref_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; pbgp->local_pref = sample->localpref; } void SF_std_comms_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_legacy_bgp_primitives *plbgp = (struct pkt_legacy_bgp_primitives *) ((*data) + chptr->extras.off_pkt_lbgp_primitives); struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); /* variables for vlen primitives */ char empty_str = '\0', *ptr = &empty_str; int len; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_as, NF_AS_KEEP)) return; if (chptr->plugin->type.id != PLUGIN_ID_MEMORY) { len = strlen(sample->comms); if (len) { len++; if (config.bgp_daemon_stdcomm_pattern) { ptr = malloc(len); if (ptr) { evaluate_comm_patterns(ptr, sample->comms, std_comm_patterns, len); len = strlen(ptr); len++; } else len = 0; } else ptr = sample->comms; } if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + len)) { vlen_prims_init(pvlen, 0); return; } else { vlen_prims_insert(pvlen, COUNT_INT_STD_COMM, len, (u_char *) ptr, PM_MSG_STR_COPY); if (config.bgp_daemon_stdcomm_pattern && ptr && len) free(ptr); } } /* fallback to legacy fixed length behaviour */ else { if (sample->communities_len) { if (config.bgp_daemon_stdcomm_pattern) evaluate_comm_patterns(plbgp->std_comms, sample->comms, std_comm_patterns, MAX_BGP_STD_COMMS); else { strlcpy(plbgp->std_comms, sample->comms, MAX_BGP_STD_COMMS); if (strlen(sample->comms)) { plbgp->std_comms[MAX_BGP_STD_COMMS-2] = '+'; plbgp->std_comms[MAX_BGP_STD_COMMS-1] = '\0'; } } } } } void SF_peer_src_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); SFSample *sample = (SFSample *) pptrs->f_data; if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V4) { pbgp->peer_src_ip.address.ipv4.s_addr = sample->agent_addr.address.ip_v4.s_addr; pbgp->peer_src_ip.family = AF_INET; } else if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V6) { memcpy(&pbgp->peer_src_ip.address.ipv6, &sample->agent_addr.address.ip_v6, IP6AddrSz); pbgp->peer_src_ip.family = AF_INET6; } } void SF_peer_dst_ip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; struct pkt_bgp_primitives *pbgp; int use_ip_next_hop = FALSE; /* we determine if this is called by exec_plugins() or bgp_srcdst_lookup() */ if (chptr) { pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); use_ip_next_hop = chptr->plugin->cfg.use_ip_next_hop; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, chptr->plugin->cfg.nfacctd_net, NF_NET_KEEP)) return; } else { pbgp = (struct pkt_bgp_primitives *) (*data); use_ip_next_hop = config.use_ip_next_hop; } if (sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V4) { pbgp->peer_dst_ip.address.ipv4.s_addr = sample->bgp_nextHop.address.ip_v4.s_addr; pbgp->peer_dst_ip.family = AF_INET; } else if (sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V6) { memcpy(&pbgp->peer_dst_ip.address.ipv6, &sample->bgp_nextHop.address.ip_v6, IP6AddrSz); pbgp->peer_dst_ip.family = AF_INET6; } else if (sample->nextHop.type == SFLADDRESSTYPE_IP_V4) { if (use_ip_next_hop) { pbgp->peer_dst_ip.address.ipv4.s_addr = sample->nextHop.address.ip_v4.s_addr; pbgp->peer_dst_ip.family = AF_INET; } } else if (sample->nextHop.type == SFLADDRESSTYPE_IP_V6) { memcpy(&pbgp->peer_dst_ip.address.ipv6, &sample->nextHop.address.ip_v6, IP6AddrSz); pbgp->peer_dst_ip.family = AF_INET6; } } void SF_in_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.ifindex_in = sample->inputPort; } void SF_out_iface_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.ifindex_out = sample->outputPort; } void SF_sampling_rate_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status; struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.sampling_rate = 0; if (config.sampling_map) { if (sampling_map_caching && xsentry && timeval_cmp(&xsentry->st.stamp, &reload_map_tstamp) > 0) { pdata->primitives.sampling_rate = xsentry->st.tag; } else { find_id_func((struct id_table *)pptrs->sampling_table, pptrs, (pm_id_t *) &pdata->primitives.sampling_rate, NULL); if (xsentry) { xsentry->st.tag = pdata->primitives.sampling_rate; gettimeofday(&xsentry->st.stamp, NULL); } } } if (pdata->primitives.sampling_rate == 0) { /* 0 = still unknown */ pdata->primitives.sampling_rate = sample->meanSkipCount; } if (config.sfacctd_renormalize && pdata->primitives.sampling_rate) { pdata->primitives.sampling_rate = 1; /* already renormalized */ } } void SF_sampling_direction_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; /* dummy */ pdata->primitives.sampling_direction = SAMPLING_DIRECTION_UNKNOWN; } void SF_timestamp_arrival_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_nat_primitives *pnat = (struct pkt_nat_primitives *) ((*data) + chptr->extras.off_pkt_nat_primitives); gettimeofday(&pnat->timestamp_arrival, NULL); if (chptr->plugin->cfg.timestamps_secs) pnat->timestamp_arrival.tv_usec = 0; } void SF_sequence_number_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.export_proto_seqno = sample->sequenceNo; } void SF_version_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.export_proto_version = sample->datagramVersion; } void SF_sysid_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; pdata->primitives.export_proto_sysid = sample->agentSubId; } #if defined (WITH_NDPI) void SF_ndpi_class_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; memcpy(&pdata->primitives.ndpi_class, &sample->ndpi_class, sizeof(pm_class2_t)); } #endif void SF_tag_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; if (!pptrs->have_tag) pdata->primitives.tag = sample->tag; } void SF_tag2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data; if (!pptrs->have_tag2) pdata->primitives.tag2 = sample->tag2; } void sampling_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pm_counter_t sample_pool = 0; evaluate_sampling(&chptr->s, &pdata->pkt_len, &pdata->pkt_num, &sample_pool); } void sfprobe_sampling_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_payload *payload = (struct pkt_payload *) *data; evaluate_sampling(&chptr->s, &payload->pkt_len, &payload->pkt_num, &payload->sample_pool); } void SF_bgp_peer_src_as_fromstd_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); pbgp->peer_src_as = 0; // XXX: fill this in } void SF_bgp_peer_src_as_fromext_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); pbgp->peer_src_as = 0; // XXX: fill this in } void SF_tunnel_src_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) memcpy(ptun->tunnel_eth_shost, sppi->eth_src, ETH_ADDR_LEN); } void SF_tunnel_dst_mac_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) memcpy(ptun->tunnel_eth_dhost, sppi->eth_dst, ETH_ADDR_LEN); } void SF_tunnel_src_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) { SFLAddress *addr = &sppi->ipsrc; if (sppi->gotIPV4) { ptun->tunnel_src_ip.address.ipv4.s_addr = sppi->dcd_srcIP.s_addr; ptun->tunnel_src_ip.family = AF_INET; } else if (sppi->gotIPV6) { memcpy(&ptun->tunnel_src_ip.address.ipv6, &addr->address.ip_v6, IP6AddrSz); ptun->tunnel_src_ip.family = AF_INET6; } } } void SF_tunnel_dst_host_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) { SFLAddress *addr = &sppi->ipdst; if (sppi->gotIPV4) { ptun->tunnel_dst_ip.address.ipv4.s_addr = sppi->dcd_dstIP.s_addr; ptun->tunnel_dst_ip.family = AF_INET; } else if (sppi->gotIPV6) { memcpy(&ptun->tunnel_dst_ip.address.ipv6, &addr->address.ip_v6, IP6AddrSz); ptun->tunnel_dst_ip.family = AF_INET6; } } } void SF_tunnel_ip_proto_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) ptun->tunnel_proto = sppi->dcd_ipProtocol; } void SF_tunnel_ip_tos_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) { ptun->tunnel_tos = sppi->dcd_ipTos; if (chptr->plugin->cfg.tos_encode_as_dscp) { ptun->tunnel_tos = ptun->tunnel_tos >> 2; } } } void SF_tunnel_src_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; ptun->tunnel_src_port = 0; if (sppi) { if (sppi->dcd_ipProtocol == IPPROTO_UDP || sppi->dcd_ipProtocol == IPPROTO_TCP) { ptun->tunnel_src_port = sppi->dcd_sport; } } } void SF_tunnel_dst_port_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; ptun->tunnel_dst_port = 0; if (sppi) { if (sppi->dcd_ipProtocol == IPPROTO_UDP || sppi->dcd_ipProtocol == IPPROTO_TCP) { ptun->tunnel_dst_port = sppi->dcd_dport; } } } void SF_tunnel_tcp_flags_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; SFSample *sample = (SFSample *) pptrs->f_data, *sppi = (SFSample *) sample->sppi; if (sppi) { if (sppi->dcd_ipProtocol == IPPROTO_TCP) { pdata->tunnel_tcp_flags = sppi->dcd_tcpFlags; } } } void SF_vxlan_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_tunnel_primitives *ptun = (struct pkt_tunnel_primitives *) ((*data) + chptr->extras.off_pkt_tun_primitives); SFSample *sample = (SFSample *) pptrs->f_data; ptun->tunnel_id = sample->vni; } void SF_mpls_pw_id_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_bgp_primitives *pbgp = (struct pkt_bgp_primitives *) ((*data) + chptr->extras.off_pkt_bgp_primitives); SFSample *sample = (SFSample *) pptrs->f_data; pbgp->mpls_pw_id = sample->mpls_vll_vc_id; } void SF_mpls_label_top_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); SFSample *sample = (SFSample *) pptrs->f_data; u_int32_t *label = (u_int32_t *) sample->lstk.stack; if (label) pmpls->mpls_label_top = MPLS_LABEL(ntohl(*label)); } void SF_mpls_label_bottom_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_mpls_primitives *pmpls = (struct pkt_mpls_primitives *) ((*data) + chptr->extras.off_pkt_mpls_primitives); SFSample *sample = (SFSample *) pptrs->f_data; u_int32_t lvalue = 0, *label = (u_int32_t *) sample->lstk.stack; if (label) { do { lvalue = ntohl(*label); label += 4; } while (!MPLS_STACK(lvalue)); pmpls->mpls_label_bottom = MPLS_LABEL(lvalue); } } void SF_mpls_label_stack_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_vlen_hdr_primitives *pvlen = (struct pkt_vlen_hdr_primitives *) ((*data) + chptr->extras.off_pkt_vlen_hdr_primitives); SFSample *sample = (SFSample *) pptrs->f_data; u_int32_t lvalue = 0, *label = (u_int32_t *) sample->lstk.stack, idx = 0; u_int32_t label_stack[MAX_MPLS_LABELS]; u_int8_t label_stack_len = 0; memset(&label_stack, 0, sizeof(label_stack)); if (label) { do { lvalue = ntohl(*label); if (idx < MAX_MPLS_LABELS) { label_stack[idx] = MPLS_LABEL(lvalue); label_stack_len += 4; idx++; } label += 4; } while (!MPLS_STACK(lvalue)); } if (check_pipe_buffer_space(chptr, pvlen, PmLabelTSz + label_stack_len)) { vlen_prims_init(pvlen, 0); return; } else vlen_prims_insert(pvlen, COUNT_INT_MPLS_LABEL_STACK, label_stack_len, (u_char *) label_stack, PM_MSG_BIN_COPY); } void SF_custom_primitives_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { SFSample *sample = (SFSample *) pptrs->f_data; custom_primitives_handler(chptr, &sample->hdr_ptrs, data); } #if defined WITH_GEOIP void pm_geoip_init() { if (config.geoip_ipv4_file && !config.geoip_ipv4) { config.geoip_ipv4 = GeoIP_open(config.geoip_ipv4_file, (GEOIP_MEMORY_CACHE|GEOIP_CHECK_CACHE)); if (!config.geoip_ipv4 && !log_notification_isset(&log_notifications.geoip_ipv4_file_null, FALSE)) { Log(LOG_WARNING, "WARN ( %s/%s ): geoip_ipv4_file database can't be loaded.\n", config.name, config.type); log_notification_set(&log_notifications.geoip_ipv4_file_null, FALSE, FALSE); } } if (config.geoip_ipv6_file && !config.geoip_ipv6) { config.geoip_ipv6 = GeoIP_open(config.geoip_ipv6_file, (GEOIP_MEMORY_CACHE|GEOIP_CHECK_CACHE)); if (!config.geoip_ipv6 && !log_notification_isset(&log_notifications.geoip_ipv6_file_null, FALSE)) { Log(LOG_WARNING, "WARN ( %s/%s ): geoip_ipv6_file database can't be loaded.\n", config.name, config.type); log_notification_set(&log_notifications.geoip_ipv6_file_null, FALSE, FALSE); } } } void src_host_country_geoip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pm_geoip_init(); pdata->primitives.src_ip_country.id = 0; if (config.geoip_ipv4) { if (pptrs->l3_proto == ETHERTYPE_IP) pdata->primitives.src_ip_country.id = GeoIP_id_by_ipnum(config.geoip_ipv4, ntohl(((struct pm_iphdr *) pptrs->iph_ptr)->ip_src.s_addr)); } if (config.geoip_ipv6) { if (pptrs->l3_proto == ETHERTYPE_IPV6) pdata->primitives.src_ip_country.id = GeoIP_id_by_ipnum_v6(config.geoip_ipv6, ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src); } } void dst_host_country_geoip_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; pm_geoip_init(); pdata->primitives.dst_ip_country.id = 0; if (config.geoip_ipv4) { if (pptrs->l3_proto == ETHERTYPE_IP) pdata->primitives.dst_ip_country.id = GeoIP_id_by_ipnum(config.geoip_ipv4, ntohl(((struct pm_iphdr *) pptrs->iph_ptr)->ip_dst.s_addr)); } if (config.geoip_ipv6) { if (pptrs->l3_proto == ETHERTYPE_IPV6) pdata->primitives.dst_ip_country.id = GeoIP_id_by_ipnum_v6(config.geoip_ipv6, ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst); } } #endif #if defined WITH_GEOIPV2 void pm_geoipv2_init() { int status; memset(&config.geoipv2_db, 0, sizeof(config.geoipv2_db)); if (config.geoipv2_file) { status = MMDB_open(config.geoipv2_file, MMDB_MODE_MMAP, &config.geoipv2_db); if (status != MMDB_SUCCESS) { Log(LOG_WARNING, "WARN ( %s/%s ): geoipv2_file database can't be loaded (%s).\n", config.name, config.type, MMDB_strerror(status)); log_notification_set(&log_notifications.geoip_ipv4_file_null, FALSE, FALSE); memset(&config.geoipv2_db, 0, sizeof(config.geoipv2_db)); } else Log(LOG_INFO, "INFO ( %s/%s ): geoipv2_file database %s loaded\n", config.name, config.type, config.geoipv2_file); } } void pm_geoipv2_close() { if (config.geoipv2_file) MMDB_close(&config.geoipv2_db); } void src_host_geoipv2_lookup_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *) &ss; int mmdb_error; memset(&pptrs->geoipv2_src, 0, sizeof(pptrs->geoipv2_src)); if (pptrs->l3_proto == ETHERTYPE_IP) { raw_to_sa(sa, (u_char *) &((struct pm_iphdr *)pptrs->iph_ptr)->ip_src.s_addr, 0, AF_INET); } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { raw_to_sa(sa, (u_char *) &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, 0, AF_INET6); } if (config.geoipv2_db.filename) { pptrs->geoipv2_src = MMDB_lookup_sockaddr(&config.geoipv2_db, sa, &mmdb_error); if (mmdb_error != MMDB_SUCCESS) { Log(LOG_WARNING, "WARN ( %s/%s ): src_host_geoipv2_lookup_handler(): %s\n", config.name, config.type, MMDB_strerror(mmdb_error)); } } else { pptrs->geoipv2_src.found_entry = NULL; } } void dst_host_geoipv2_lookup_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *) &ss; int mmdb_error; memset(&pptrs->geoipv2_dst, 0, sizeof(pptrs->geoipv2_dst)); if (pptrs->l3_proto == ETHERTYPE_IP) { raw_to_sa(sa, (u_char *) &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst.s_addr, 0, AF_INET); } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { raw_to_sa(sa, (u_char *) &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, 0, AF_INET6); } if (config.geoipv2_db.filename) { pptrs->geoipv2_dst = MMDB_lookup_sockaddr(&config.geoipv2_db, sa, &mmdb_error); if (mmdb_error != MMDB_SUCCESS) { Log(LOG_WARNING, "WARN ( %s/%s ): dst_host_geoipv2_lookup_handler(): %s\n", config.name, config.type, MMDB_strerror(mmdb_error)); } } else { pptrs->geoipv2_dst.found_entry = NULL; } } void src_host_country_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; char other_country[] = "O1"; int status; if (pptrs->geoipv2_src.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_src.entry, &entry_data, "country", "iso_code", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): src_host_country_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { int size = (entry_data_list->entry_data.data_size < (PM_COUNTRY_T_STRLEN-1)) ? entry_data_list->entry_data.data_size : (PM_COUNTRY_T_STRLEN-1); memcpy(pdata->primitives.src_ip_country.str, entry_data_list->entry_data.utf8_string, size); pdata->primitives.src_ip_country.str[size] = '\0'; } } MMDB_free_entry_data_list(entry_data_list); } } else { /* return O1/Other Country: https://dev.maxmind.com/geoip/legacy/codes/iso3166/ */ strncpy(pdata->primitives.src_ip_country.str, other_country, strlen(pdata->primitives.src_ip_country.str)); } } void dst_host_country_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; char other_country[] = "O1"; int status; if (pptrs->geoipv2_dst.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_dst.entry, &entry_data, "country", "iso_code", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): dst_host_country_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { int size = (entry_data_list->entry_data.data_size < (PM_COUNTRY_T_STRLEN-1)) ? entry_data_list->entry_data.data_size : (PM_COUNTRY_T_STRLEN-1); memcpy(pdata->primitives.dst_ip_country.str, entry_data_list->entry_data.utf8_string, size); pdata->primitives.dst_ip_country.str[size] = '\0'; } } MMDB_free_entry_data_list(entry_data_list); } } else { /* return O1/Other Country: https://dev.maxmind.com/geoip/legacy/codes/iso3166/ */ strncpy(pdata->primitives.dst_ip_country.str, other_country, strlen(pdata->primitives.dst_ip_country.str)); } } void src_host_pocode_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; int status; if (pptrs->geoipv2_src.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_src.entry, &entry_data, "postal", "code", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): src_host_pocode_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { int size = (entry_data_list->entry_data.data_size < (PM_POCODE_T_STRLEN-1)) ? entry_data_list->entry_data.data_size : (PM_POCODE_T_STRLEN-1); memcpy(pdata->primitives.src_ip_pocode.str, entry_data_list->entry_data.utf8_string, size); pdata->primitives.src_ip_pocode.str[size] = '\0'; } } MMDB_free_entry_data_list(entry_data_list); } } } void dst_host_pocode_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; int status; if (pptrs->geoipv2_dst.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_dst.entry, &entry_data, "postal", "code", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): dst_host_pocode_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { int size = (entry_data_list->entry_data.data_size < (PM_POCODE_T_STRLEN-1)) ? entry_data_list->entry_data.data_size : (PM_POCODE_T_STRLEN-1); memcpy(pdata->primitives.dst_ip_pocode.str, entry_data_list->entry_data.utf8_string, size); pdata->primitives.dst_ip_pocode.str[size] = '\0'; } } MMDB_free_entry_data_list(entry_data_list); } } } void src_host_coords_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; int status; if (pptrs->geoipv2_src.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_src.entry, &entry_data, "location", "latitude", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): src_host_coords_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_DOUBLE) { pdata->primitives.src_ip_lat = entry_data_list->entry_data.double_value; } } MMDB_free_entry_data_list(entry_data_list); } status = MMDB_get_value(&pptrs->geoipv2_src.entry, &entry_data, "location", "longitude", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): src_host_coords_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_DOUBLE) { pdata->primitives.src_ip_lon = entry_data_list->entry_data.double_value; } } MMDB_free_entry_data_list(entry_data_list); } } } void dst_host_coords_geoipv2_handler(struct channels_list_entry *chptr, struct packet_ptrs *pptrs, char **data) { struct pkt_data *pdata = (struct pkt_data *) *data; MMDB_entry_data_list_s *entry_data_list = NULL; int status; if (pptrs->geoipv2_dst.found_entry) { MMDB_entry_data_s entry_data; status = MMDB_get_value(&pptrs->geoipv2_dst.entry, &entry_data, "location", "latitude", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): dst_host_coords_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_DOUBLE) { pdata->primitives.dst_ip_lat = entry_data_list->entry_data.double_value; } } MMDB_free_entry_data_list(entry_data_list); } status = MMDB_get_value(&pptrs->geoipv2_dst.entry, &entry_data, "location", "longitude", NULL); if (entry_data.offset) { MMDB_entry_s entry = { .mmdb = &config.geoipv2_db, .offset = entry_data.offset }; status = MMDB_get_entry_data_list(&entry, &entry_data_list); } if (status != MMDB_SUCCESS && status != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { Log(LOG_WARNING, "WARN ( %s/%s ): dst_host_coords_geoipv2_handler(): %s\n", config.name, config.type, MMDB_strerror(status)); } if (entry_data_list != NULL) { if (entry_data_list->entry_data.has_data) { if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_DOUBLE) { pdata->primitives.dst_ip_lon = entry_data_list->entry_data.double_value; } } MMDB_free_entry_data_list(entry_data_list); } } } #endif /* srcdst: 0 == src, 1 == dst */ int evaluate_lm_method(struct packet_ptrs *pptrs, u_int8_t srcdst, u_int32_t bitmap, u_int32_t method) { /* src */ if (srcdst == FALSE) { if (pptrs->lm_method_src == method || !(bitmap & NF_NET_FALLBACK)) return TRUE; else return FALSE; } /* dst */ else if (srcdst == TRUE) { if (pptrs->lm_method_dst == method || !(bitmap & NF_NET_FALLBACK)) return TRUE; else return FALSE; } return ERR; } char *lookup_tpl_ext_db(void *entry, u_int32_t pen, u_int16_t type) { struct template_cache_entry *tpl = (struct template_cache_entry *) entry; u_int16_t ie_idx, ext_db_modulo = (type%TPL_EXT_DB_ENTRIES); for (ie_idx = 0; ie_idx < IES_PER_TPL_EXT_DB_ENTRY; ie_idx++) { if (tpl->ext_db[ext_db_modulo].ie[ie_idx].type == type && tpl->ext_db[ext_db_modulo].ie[ie_idx].pen == pen) return (char *) &tpl->ext_db[ext_db_modulo].ie[ie_idx]; } return NULL; } pmacct-1.7.8/src/util-data.h0000644000175000017500000000277414354105275014650 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ const struct dynname_token_dict_registry_line dynname_token_dict_registry[] = { {DYN_STR_KAFKA_TOPIC, "kafka_topic", NULL}, {DYN_STR_KAFKA_PART, "kafka_parttion", NULL}, {DYN_STR_RABBITMQ_RK, "amqp_routing_key", NULL}, {DYN_STR_MONGODB_TABLE, "mongodb_table", NULL}, {DYN_STR_SQL_TABLE, "sql_table", NULL}, {DYN_STR_PRINT_FILE, "print_output_file", NULL}, {DYN_STR_WRITER_ID, "writer_id", dtdr_writer_id}, {DYN_STR_UNKNOWN, "unknown", dtdr_unknown} }; const struct dynname_type_dictionary_line dynname_writer_id_dictionary[] = { {"proc_name", dwi_proc_name_handler}, {"writer_pid", dwi_writer_pid_handler}, {"pmacct_build", dwi_pmacct_build_handler}, {"", NULL} }; pmacct-1.7.8/src/plugin_cmn_json.c0000644000175000017500000012212214354105275016131 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_common.h" #include "plugin_cmn_json.h" #include "ip_flow.h" #include "classifier.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif #ifdef WITH_JANSSON /* Global variables */ compose_json_handler cjhandler[N_PRIMITIVES]; /* Functions */ void compose_json(u_int64_t wtc, u_int64_t wtc_2) { int idx = 0; Log(LOG_INFO, "INFO ( %s/%s ): JSON: setting object handlers.\n", config.name, config.type); memset(&cjhandler, 0, sizeof(cjhandler)); cjhandler[idx] = compose_json_event_type; idx++; if (wtc & COUNT_TAG) { cjhandler[idx] = compose_json_tag; idx++; } if (wtc & COUNT_TAG2) { cjhandler[idx] = compose_json_tag2; idx++; } if (wtc_2 & COUNT_LABEL) { if (config.pretag_label_encode_as_map) { cjhandler[idx] = compose_json_map_label; } else { cjhandler[idx] = compose_json_label; } idx++; } if (wtc & COUNT_CLASS) { cjhandler[idx] = compose_json_class; idx++; } #if defined (WITH_NDPI) if (wtc_2 & COUNT_NDPI_CLASS) { cjhandler[idx] = compose_json_ndpi_class; idx++; } #endif #if defined (HAVE_L2) if (wtc & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { cjhandler[idx] = compose_json_src_mac; idx++; } if (wtc & COUNT_DST_MAC) { cjhandler[idx] = compose_json_dst_mac; idx++; } if (wtc & COUNT_VLAN) { cjhandler[idx] = compose_json_vlan; idx++; } if (wtc_2 & COUNT_OUT_VLAN) { cjhandler[idx] = compose_json_out_vlan; idx++; } if (wtc & COUNT_COS) { cjhandler[idx] = compose_json_cos; idx++; } if (wtc & COUNT_ETHERTYPE) { cjhandler[idx] = compose_json_etype; idx++; } #endif if (wtc & (COUNT_SRC_AS|COUNT_SUM_AS)) { cjhandler[idx] = compose_json_src_as; idx++; } if (wtc & COUNT_DST_AS) { cjhandler[idx] = compose_json_dst_as; idx++; } if (wtc & COUNT_STD_COMM) { cjhandler[idx] = compose_json_std_comm; idx++; } if (wtc & COUNT_EXT_COMM) { cjhandler[idx] = compose_json_ext_comm; idx++; } if (wtc_2 & COUNT_LRG_COMM) { cjhandler[idx] = compose_json_lrg_comm; idx++; } if (wtc & COUNT_AS_PATH) { cjhandler[idx] = compose_json_as_path; idx++; } if (wtc & COUNT_LOCAL_PREF) { cjhandler[idx] = compose_json_local_pref; idx++; } if (wtc & COUNT_MED) { cjhandler[idx] = compose_json_med; idx++; } if (wtc_2 & COUNT_DST_ROA) { cjhandler[idx] = compose_json_dst_roa; idx++; } if (wtc & COUNT_PEER_SRC_AS) { cjhandler[idx] = compose_json_peer_src_as; idx++; } if (wtc & COUNT_PEER_DST_AS) { cjhandler[idx] = compose_json_peer_dst_as; idx++; } if (wtc & COUNT_PEER_SRC_IP) { cjhandler[idx] = compose_json_peer_src_ip; idx++; } if (wtc & COUNT_PEER_DST_IP) { cjhandler[idx] = compose_json_peer_dst_ip; idx++; } if (wtc & COUNT_SRC_STD_COMM) { cjhandler[idx] = compose_json_src_std_comm; idx++; } if (wtc & COUNT_SRC_EXT_COMM) { cjhandler[idx] = compose_json_src_ext_comm; idx++; } if (wtc_2 & COUNT_SRC_LRG_COMM) { cjhandler[idx] = compose_json_src_lrg_comm; idx++; } if (wtc & COUNT_SRC_AS_PATH) { cjhandler[idx] = compose_json_src_as_path; idx++; } if (wtc & COUNT_SRC_LOCAL_PREF) { cjhandler[idx] = compose_json_src_local_pref; idx++; } if (wtc & COUNT_SRC_MED) { cjhandler[idx] = compose_json_src_med; idx++; } if (wtc_2 & COUNT_SRC_ROA) { cjhandler[idx] = compose_json_src_roa; idx++; } if (wtc & COUNT_IN_IFACE) { cjhandler[idx] = compose_json_in_iface; idx++; } if (wtc & COUNT_OUT_IFACE) { cjhandler[idx] = compose_json_out_iface; idx++; } if (wtc & COUNT_MPLS_VPN_RD) { cjhandler[idx] = compose_json_mpls_vpn_rd; idx++; } if (wtc_2 & COUNT_MPLS_PW_ID) { cjhandler[idx] = compose_json_mpls_pw_id; idx++; } if (wtc & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { cjhandler[idx] = compose_json_src_host; idx++; } if (wtc & (COUNT_SRC_NET|COUNT_SUM_NET)) { cjhandler[idx] = compose_json_src_net; idx++; } if (wtc & COUNT_DST_HOST) { cjhandler[idx] = compose_json_dst_host; idx++; } if (wtc & COUNT_DST_NET) { cjhandler[idx] = compose_json_dst_net; idx++; } if (wtc & COUNT_SRC_NMASK) { cjhandler[idx] = compose_json_src_mask; idx++; } if (wtc & COUNT_DST_NMASK) { cjhandler[idx] = compose_json_dst_mask; idx++; } if (wtc & (COUNT_SRC_PORT|COUNT_SUM_PORT)) { cjhandler[idx] = compose_json_src_port; idx++; } if (wtc & COUNT_DST_PORT) { cjhandler[idx] = compose_json_dst_port; idx++; } #if defined (WITH_GEOIP) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { cjhandler[idx] = compose_json_src_host_country; idx++; } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { cjhandler[idx] = compose_json_dst_host_country; idx++; } #endif #if defined (WITH_GEOIPV2) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { cjhandler[idx] = compose_json_src_host_country; idx++; } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { cjhandler[idx] = compose_json_dst_host_country; idx++; } if (wtc_2 & COUNT_SRC_HOST_POCODE) { cjhandler[idx] = compose_json_src_host_pocode; idx++; } if (wtc_2 & COUNT_DST_HOST_POCODE) { cjhandler[idx] = compose_json_dst_host_pocode; idx++; } if (wtc_2 & COUNT_SRC_HOST_COORDS) { cjhandler[idx] = compose_json_src_host_coords; idx++; } if (wtc_2 & COUNT_DST_HOST_COORDS) { cjhandler[idx] = compose_json_dst_host_coords; idx++; } #endif if (wtc & COUNT_TCPFLAGS) { if (config.tcpflags_encode_as_array) { cjhandler[idx] = compose_json_array_tcpflags; } else { cjhandler[idx] = compose_json_tcp_flags; } idx++; } if (wtc_2 & COUNT_FWD_STATUS) { if (config.fwd_status_encode_as_string) { cjhandler[idx] = compose_json_string_fwd_status; } else { cjhandler[idx] = compose_json_fwd_status; } idx++; } if (wtc_2 & COUNT_MPLS_LABEL_STACK) { if (config.mpls_label_stack_encode_as_array) { cjhandler[idx] = compose_json_array_mpls_label_stack; } else { cjhandler[idx] = compose_json_mpls_label_stack; } idx++; } if (wtc & COUNT_IP_PROTO) { cjhandler[idx] = compose_json_proto; idx++; } if (wtc & COUNT_IP_TOS) { cjhandler[idx] = compose_json_tos; idx++; } if (wtc_2 & COUNT_SAMPLING_RATE) { cjhandler[idx] = compose_json_sampling_rate; idx++; } if (wtc_2 & COUNT_SAMPLING_DIRECTION) { cjhandler[idx] = compose_json_sampling_direction; idx++; } if (wtc_2 & COUNT_POST_NAT_SRC_HOST) { cjhandler[idx] = compose_json_post_nat_src_host; idx++; } if (wtc_2 & COUNT_POST_NAT_DST_HOST) { cjhandler[idx] = compose_json_post_nat_dst_host; idx++; } if (wtc_2 & COUNT_POST_NAT_SRC_PORT) { cjhandler[idx] = compose_json_post_nat_src_port; idx++; } if (wtc_2 & COUNT_POST_NAT_DST_PORT) { cjhandler[idx] = compose_json_post_nat_dst_port; idx++; } if (wtc_2 & COUNT_NAT_EVENT) { cjhandler[idx] = compose_json_nat_event; idx++; } if (wtc_2 & COUNT_FW_EVENT) { cjhandler[idx] = compose_json_fw_event; idx++; } if (wtc_2 & COUNT_MPLS_LABEL_TOP) { cjhandler[idx] = compose_json_mpls_label_top; idx++; } if (wtc_2 & COUNT_MPLS_LABEL_BOTTOM) { cjhandler[idx] = compose_json_mpls_label_bottom; idx++; } if (wtc_2 & COUNT_TUNNEL_SRC_MAC) { cjhandler[idx] = compose_json_tunnel_src_mac; idx++; } if (wtc_2 & COUNT_TUNNEL_DST_MAC) { cjhandler[idx] = compose_json_tunnel_dst_mac; idx++; } if (wtc_2 & COUNT_TUNNEL_SRC_HOST) { cjhandler[idx] = compose_json_tunnel_src_host; idx++; } if (wtc_2 & COUNT_TUNNEL_DST_HOST) { cjhandler[idx] = compose_json_tunnel_dst_host; idx++; } if (wtc_2 & COUNT_TUNNEL_IP_PROTO) { cjhandler[idx] = compose_json_tunnel_proto; idx++; } if (wtc_2 & COUNT_TUNNEL_IP_TOS) { cjhandler[idx] = compose_json_tunnel_tos; idx++; } if (wtc_2 & COUNT_TUNNEL_SRC_PORT) { cjhandler[idx] = compose_json_tunnel_src_port; idx++; } if (wtc_2 & COUNT_TUNNEL_DST_PORT) { cjhandler[idx] = compose_json_tunnel_dst_port; idx++; } if (wtc_2 & COUNT_TUNNEL_TCPFLAGS) { if (config.tcpflags_encode_as_array) { cjhandler[idx] = compose_json_array_tunnel_tcp_flags; } else { cjhandler[idx] = compose_json_tunnel_tcp_flags; } idx++; } if (wtc_2 & COUNT_VXLAN) { cjhandler[idx] = compose_json_vxlan; idx++; } if (wtc_2 & COUNT_TIMESTAMP_START) { cjhandler[idx] = compose_json_timestamp_start; idx++; } if (wtc_2 & COUNT_TIMESTAMP_END) { cjhandler[idx] = compose_json_timestamp_end; idx++; } if (wtc_2 & COUNT_TIMESTAMP_ARRIVAL) { cjhandler[idx] = compose_json_timestamp_arrival; idx++; } if (config.nfacctd_stitching) { cjhandler[idx] = compose_json_timestamp_stitching; idx++; } if (wtc_2 & COUNT_EXPORT_PROTO_SEQNO) { cjhandler[idx] = compose_json_export_proto_seqno; idx++; } if (wtc_2 & COUNT_EXPORT_PROTO_VERSION) { cjhandler[idx] = compose_json_export_proto_version; idx++; } if (wtc_2 & COUNT_EXPORT_PROTO_SYSID) { cjhandler[idx] = compose_json_export_proto_sysid; idx++; } if (wtc_2 & COUNT_EXPORT_PROTO_TIME) { cjhandler[idx] = compose_json_timestamp_export; idx++; } if (config.cpptrs.num) { cjhandler[idx] = compose_json_custom_primitives; idx++; } if (config.sql_history) { cjhandler[idx] = compose_json_history; idx++; } if (wtc & COUNT_FLOWS) { cjhandler[idx] = compose_json_flows; idx++; } cjhandler[idx] = compose_json_counters; } void compose_json_event_type(json_t *obj, struct chained_cache *null) { char event_type[] = "purge"; json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); } void compose_json_tag(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tag", json_integer((json_int_t)cc->primitives.tag)); } void compose_json_tag2(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tag2", json_integer((json_int_t)cc->primitives.tag2)); } void compose_json_label(json_t *obj, struct chained_cache *cc) { char empty_string[] = "", *str_ptr; vlen_prims_get(cc->pvlen, COUNT_INT_LABEL, &str_ptr); if (!str_ptr) str_ptr = empty_string; json_object_set_new_nocheck(obj, "label", json_string(str_ptr)); } void compose_json_class(json_t *obj, struct chained_cache *cc) { struct pkt_primitives *pbase = &cc->primitives; json_object_set_new_nocheck(obj, "class", json_string((pbase->class && class[(pbase->class)-1].id) ? class[(pbase->class)-1].protocol : "unknown")); } #if defined (WITH_NDPI) void compose_json_ndpi_class(json_t *obj, struct chained_cache *cc) { char ndpi_class[SUPERSHORTBUFLEN]; struct pkt_primitives *pbase = &cc->primitives; snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, pbase->ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, pbase->ndpi_class.app_protocol)); json_object_set_new_nocheck(obj, "class", json_string(ndpi_class)); } #endif #if defined (HAVE_L2) void compose_json_src_mac(json_t *obj, struct chained_cache *cc) { char mac[18]; etheraddr_string(cc->primitives.eth_shost, mac); json_object_set_new_nocheck(obj, "mac_src", json_string(mac)); } void compose_json_dst_mac(json_t *obj, struct chained_cache *cc) { char mac[18]; etheraddr_string(cc->primitives.eth_dhost, mac); json_object_set_new_nocheck(obj, "mac_dst", json_string(mac)); } void compose_json_vlan(json_t *obj, struct chained_cache *cc) { if (config.tmp_vlan_legacy) { json_object_set_new_nocheck(obj, "vlan", json_integer((json_int_t)cc->primitives.vlan_id)); } else { json_object_set_new_nocheck(obj, "vlan_in", json_integer((json_int_t)cc->primitives.vlan_id)); } } void compose_json_out_vlan(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "vlan_out", json_integer((json_int_t)cc->primitives.out_vlan_id)); } void compose_json_cos(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "cos", json_integer((json_int_t)cc->primitives.cos)); } void compose_json_etype(json_t *obj, struct chained_cache *cc) { char misc_str[VERYSHORTBUFLEN]; sprintf(misc_str, "%x", cc->primitives.etype); json_object_set_new_nocheck(obj, "etype", json_string(misc_str)); } #endif void compose_json_src_as(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "as_src", json_integer((json_int_t)cc->primitives.src_as)); } void compose_json_dst_as(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "as_dst", json_integer((json_int_t)cc->primitives.dst_as)); } void compose_json_std_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "comms", json_string(str_ptr)); } void compose_json_ext_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "ecomms", json_string(str_ptr)); } void compose_json_lrg_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "lcomms", json_string(str_ptr)); } void compose_json_as_path(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *as_path, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "as_path", json_string(str_ptr)); } void compose_json_local_pref(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "local_pref", json_integer((json_int_t)cc->pbgp->local_pref)); } void compose_json_med(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "med", json_integer((json_int_t)cc->pbgp->med)); } void compose_json_dst_roa(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "roa_dst", json_string(rpki_roa_print(cc->pbgp->dst_roa))); } void compose_json_peer_src_as(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "peer_as_src", json_integer((json_int_t)cc->pbgp->peer_src_as)); } void compose_json_peer_dst_as(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "peer_as_dst", json_integer((json_int_t)cc->pbgp->peer_dst_as)); } void compose_json_peer_src_ip(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->pbgp->peer_src_ip); json_object_set_new_nocheck(obj, "peer_ip_src", json_string(ip_address)); } void compose_json_peer_dst_ip(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str2(ip_address, &cc->pbgp->peer_dst_ip, ft2af(cc->flow_type)); json_object_set_new_nocheck(obj, "peer_ip_dst", json_string(ip_address)); } void compose_json_src_std_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_SRC_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "comms_src", json_string(str_ptr)); } void compose_json_src_ext_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_SRC_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "ecomms_src", json_string(str_ptr)); } void compose_json_src_lrg_comm(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *bgp_comm, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_SRC_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "lcomms_src", json_string(str_ptr)); } void compose_json_src_as_path(json_t *obj, struct chained_cache *cc) { char *str_ptr = NULL, *as_path, empty_string[] = ""; vlen_prims_get(cc->pvlen, COUNT_INT_SRC_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } else str_ptr = empty_string; json_object_set_new_nocheck(obj, "as_path_src", json_string(str_ptr)); } void compose_json_src_local_pref(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "local_pref_src", json_integer((json_int_t)cc->pbgp->src_local_pref)); } void compose_json_src_med(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "med_src", json_integer((json_int_t)cc->pbgp->src_med)); } void compose_json_src_roa(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "roa_src", json_string(rpki_roa_print(cc->pbgp->src_roa))); } void compose_json_in_iface(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "iface_in", json_integer((json_int_t)cc->primitives.ifindex_in)); } void compose_json_out_iface(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "iface_out", json_integer((json_int_t)cc->primitives.ifindex_out)); } void compose_json_mpls_vpn_rd(json_t *obj, struct chained_cache *cc) { char rd_str[VERYSHORTBUFLEN]; bgp_rd2str(rd_str, &cc->pbgp->mpls_vpn_rd); json_object_set_new_nocheck(obj, "mpls_vpn_rd", json_string(rd_str)); } void compose_json_mpls_pw_id(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "mpls_pw_id", json_integer((json_int_t)cc->pbgp->mpls_pw_id)); } void compose_json_src_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->primitives.src_ip); json_object_set_new_nocheck(obj, "ip_src", json_string(ip_address)); } void compose_json_src_net(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->primitives.src_net); json_object_set_new_nocheck(obj, "net_src", json_string(ip_address)); } void compose_json_dst_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->primitives.dst_ip); json_object_set_new_nocheck(obj, "ip_dst", json_string(ip_address)); } void compose_json_dst_net(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->primitives.dst_net); json_object_set_new_nocheck(obj, "net_dst", json_string(ip_address)); } void compose_json_src_mask(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "mask_src", json_integer((json_int_t)cc->primitives.src_nmask)); } void compose_json_dst_mask(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "mask_dst", json_integer((json_int_t)cc->primitives.dst_nmask)); } void compose_json_src_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "port_src", json_integer((json_int_t)cc->primitives.src_port)); } void compose_json_dst_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "port_dst", json_integer((json_int_t)cc->primitives.dst_port)); } #if defined (WITH_GEOIP) void compose_json_src_host_country(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (cc->primitives.src_ip_country.id > 0) json_object_set_new_nocheck(obj, "country_ip_src", json_string(GeoIP_code_by_id(cc->primitives.src_ip_country.id))); else json_object_set_new_nocheck(obj, "country_ip_src", json_string(empty_string)); } void compose_json_dst_host_country(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (cc->primitives.dst_ip_country.id > 0) json_object_set_new_nocheck(obj, "country_ip_dst", json_string(GeoIP_code_by_id(cc->primitives.dst_ip_country.id))); else json_object_set_new_nocheck(obj, "country_ip_dst", json_string(empty_string)); } #endif #if defined (WITH_GEOIPV2) void compose_json_src_host_country(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (strlen(cc->primitives.src_ip_country.str)) json_object_set_new_nocheck(obj, "country_ip_src", json_string(cc->primitives.src_ip_country.str)); else json_object_set_new_nocheck(obj, "country_ip_src", json_string(empty_string)); } void compose_json_dst_host_country(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (strlen(cc->primitives.dst_ip_country.str)) json_object_set_new_nocheck(obj, "country_ip_dst", json_string(cc->primitives.dst_ip_country.str)); else json_object_set_new_nocheck(obj, "country_ip_dst", json_string(empty_string)); } void compose_json_src_host_pocode(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (strlen(cc->primitives.src_ip_pocode.str)) json_object_set_new_nocheck(obj, "pocode_ip_src", json_string(cc->primitives.src_ip_pocode.str)); else json_object_set_new_nocheck(obj, "pocode_ip_src", json_string(empty_string)); } void compose_json_dst_host_pocode(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; if (strlen(cc->primitives.dst_ip_pocode.str)) json_object_set_new_nocheck(obj, "pocode_ip_dst", json_string(cc->primitives.dst_ip_pocode.str)); else json_object_set_new_nocheck(obj, "pocode_ip_dst", json_string(empty_string)); } void compose_json_src_host_coords(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "lat_ip_src", json_real(cc->primitives.src_ip_lat)); json_object_set_new_nocheck(obj, "lon_ip_src", json_real(cc->primitives.src_ip_lon)); } void compose_json_dst_host_coords(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "lat_ip_dst", json_real(cc->primitives.dst_ip_lat)); json_object_set_new_nocheck(obj, "lon_ip_dst", json_real(cc->primitives.dst_ip_lon)); } #endif void compose_json_tcp_flags(json_t *obj, struct chained_cache *cc) { char misc_str[VERYSHORTBUFLEN]; sprintf(misc_str, "%u", cc->tcp_flags); json_object_set_new_nocheck(obj, "tcp_flags", json_string(misc_str)); } void compose_json_fwd_status(json_t *obj, struct chained_cache *cc) { char misc_str[VERYSHORTBUFLEN]; sprintf(misc_str, "%u", cc->pnat->fwd_status); json_object_set_new_nocheck(obj, "fwd_status", json_string(misc_str)); } void compose_json_mpls_label_stack(json_t *obj, struct chained_cache *cc) { char label_stack[MAX_MPLS_LABEL_STACK]; char *label_stack_ptr = NULL; int label_stack_len = 0; memset(label_stack, 0, MAX_MPLS_LABEL_STACK); label_stack_len = vlen_prims_get(cc->pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); if (label_stack_ptr) { mpls_label_stack_to_str(label_stack, sizeof(label_stack), (u_int32_t *)label_stack_ptr, label_stack_len); } json_object_set_new_nocheck(obj, "mpls_label_stack", json_string(label_stack)); } void compose_json_proto(json_t *obj, struct chained_cache *cc) { char proto[PROTO_NUM_STRLEN]; json_object_set_new_nocheck(obj, "ip_proto", json_string(ip_proto_print(cc->primitives.proto, proto, PROTO_NUM_STRLEN))); } void compose_json_tos(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tos", json_integer((json_int_t)cc->primitives.tos)); } void compose_json_sampling_rate(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "sampling_rate", json_integer((json_int_t)cc->primitives.sampling_rate)); } void compose_json_sampling_direction(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "sampling_direction", json_string(sampling_direction_print(cc->primitives.sampling_direction))); } void compose_json_post_nat_src_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->pnat->post_nat_src_ip); json_object_set_new_nocheck(obj, "post_nat_ip_src", json_string(ip_address)); } void compose_json_post_nat_dst_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->pnat->post_nat_dst_ip); json_object_set_new_nocheck(obj, "post_nat_ip_dst", json_string(ip_address)); } void compose_json_post_nat_src_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "post_nat_port_src", json_integer((json_int_t)cc->pnat->post_nat_src_port)); } void compose_json_post_nat_dst_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "post_nat_port_dst", json_integer((json_int_t)cc->pnat->post_nat_dst_port)); } void compose_json_nat_event(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "nat_event", json_integer((json_int_t)cc->pnat->nat_event)); } void compose_json_fw_event(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "fw_event", json_integer((json_int_t)cc->pnat->fw_event)); } void compose_json_mpls_label_top(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "mpls_label_top", json_integer((json_int_t)cc->pmpls->mpls_label_top)); } void compose_json_mpls_label_bottom(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "mpls_label_bottom", json_integer((json_int_t)cc->pmpls->mpls_label_bottom)); } void compose_json_tunnel_src_mac(json_t *obj, struct chained_cache *cc) { char mac[18]; etheraddr_string(cc->ptun->tunnel_eth_shost, mac); json_object_set_new_nocheck(obj, "tunnel_mac_src", json_string(mac)); } void compose_json_tunnel_dst_mac(json_t *obj, struct chained_cache *cc) { char mac[18]; etheraddr_string(cc->ptun->tunnel_eth_dhost, mac); json_object_set_new_nocheck(obj, "tunnel_mac_dst", json_string(mac)); } void compose_json_tunnel_src_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->ptun->tunnel_src_ip); json_object_set_new_nocheck(obj, "tunnel_ip_src", json_string(ip_address)); } void compose_json_tunnel_dst_host(json_t *obj, struct chained_cache *cc) { char ip_address[INET6_ADDRSTRLEN]; addr_to_str(ip_address, &cc->ptun->tunnel_dst_ip); json_object_set_new_nocheck(obj, "tunnel_ip_dst", json_string(ip_address)); } void compose_json_tunnel_proto(json_t *obj, struct chained_cache *cc) { char proto[PROTO_NUM_STRLEN]; json_object_set_new_nocheck(obj, "tunnel_ip_proto", json_string(ip_proto_print(cc->ptun->tunnel_proto, proto, PROTO_NUM_STRLEN))); } void compose_json_tunnel_tos(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tunnel_tos", json_integer((json_int_t)cc->ptun->tunnel_tos)); } void compose_json_tunnel_src_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tunnel_port_src", json_integer((json_int_t)cc->ptun->tunnel_src_port)); } void compose_json_tunnel_dst_port(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "tunnel_port_dst", json_integer((json_int_t)cc->ptun->tunnel_dst_port)); } void compose_json_tunnel_tcp_flags(json_t *obj, struct chained_cache *cc) { char misc_str[VERYSHORTBUFLEN]; sprintf(misc_str, "%u", cc->tunnel_tcp_flags); json_object_set_new_nocheck(obj, "tunnel_tcp_flags", json_string(misc_str)); } void compose_json_array_tunnel_tcp_flags(json_t *obj, struct chained_cache *cc) { /* linked-list creation */ cdada_list_t *ll = tcpflags_to_linked_list(cc->tunnel_tcp_flags); size_t ll_size = cdada_list_size(ll); json_t *root_l1 = compose_tcpflags_json_data(ll, ll_size); json_object_set_new_nocheck(obj, "tunnel_tcp_flags", root_l1); cdada_list_destroy(ll); } void compose_json_vxlan(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "vxlan", json_integer((json_int_t)cc->ptun->tunnel_id)); } void compose_json_timestamp_start(json_t *obj, struct chained_cache *cc) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->pnat->timestamp_start, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_start", json_string(tstamp_str)); } void compose_json_timestamp_end(json_t *obj, struct chained_cache *cc) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->pnat->timestamp_end, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_end", json_string(tstamp_str)); } void compose_json_timestamp_arrival(json_t *obj, struct chained_cache *cc) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->pnat->timestamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_arrival", json_string(tstamp_str)); } void compose_json_timestamp_export(json_t *obj, struct chained_cache *cc) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->pnat->timestamp_export, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_export", json_string(tstamp_str)); } void compose_json_timestamp_stitching(json_t *obj, struct chained_cache *cc) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->stitch->timestamp_min, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_min", json_string(tstamp_str)); compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &cc->stitch->timestamp_max, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "timestamp_max", json_string(tstamp_str)); } void compose_json_export_proto_seqno(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "export_proto_seqno", json_integer((json_int_t)cc->primitives.export_proto_seqno)); } void compose_json_export_proto_version(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "export_proto_version", json_integer((json_int_t)cc->primitives.export_proto_version)); } void compose_json_export_proto_sysid(json_t *obj, struct chained_cache *cc) { json_object_set_new_nocheck(obj, "export_proto_sysid", json_integer((json_int_t)cc->primitives.export_proto_sysid)); } void compose_json_custom_primitives(json_t *obj, struct chained_cache *cc) { char empty_string[] = ""; int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cp_str[VERYSHORTBUFLEN]; custom_primitive_value_print(cp_str, VERYSHORTBUFLEN, cc->pcust, &config.cpptrs.primitive[cp_idx], FALSE); json_object_set_new_nocheck(obj, config.cpptrs.primitive[cp_idx].name, json_string(cp_str)); } else { char *label_ptr = NULL; vlen_prims_get(cc->pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; json_object_set_new_nocheck(obj, config.cpptrs.primitive[cp_idx].name, json_string(label_ptr)); } } } void compose_json_history(json_t *obj, struct chained_cache *cc) { if (cc->basetime.tv_sec) { char tstamp_str[VERYSHORTBUFLEN]; struct timeval tv; tv.tv_sec = cc->basetime.tv_sec; tv.tv_usec = 0; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &tv, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "stamp_inserted", json_string(tstamp_str)); tv.tv_sec = time(NULL); tv.tv_usec = 0; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &tv, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); json_object_set_new_nocheck(obj, "stamp_updated", json_string(tstamp_str)); } } void compose_json_flows(json_t *obj, struct chained_cache *cc) { if (cc->flow_type != NF9_FTYPE_EVENT && cc->flow_type != NF9_FTYPE_OPTION) json_object_set_new_nocheck(obj, "flows", json_integer((json_int_t)cc->flow_counter)); } void compose_json_counters(json_t *obj, struct chained_cache *cc) { if (cc->flow_type != NF9_FTYPE_EVENT && cc->flow_type != NF9_FTYPE_OPTION) { json_object_set_new_nocheck(obj, "packets", json_integer((json_int_t)cc->packet_counter)); json_object_set_new_nocheck(obj, "bytes", json_integer((json_int_t)cc->bytes_counter)); } } void *compose_purge_init_json(char *writer_name, pid_t writer_pid) { char event_type[] = "purge_init", wid[SHORTSHORTBUFLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", writer_name, writer_pid); json_object_set_new_nocheck(obj, "writer_id", json_string(wid)); return obj; } void *compose_purge_close_json(char *writer_name, pid_t writer_pid, int purged_entries, int total_entries, int duration) { char event_type[] = "purge_close", wid[SHORTSHORTBUFLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", writer_name, writer_pid); json_object_set_new_nocheck(obj, "writer_id", json_string(wid)); json_object_set_new_nocheck(obj, "purged_entries", json_integer((json_int_t)purged_entries)); json_object_set_new_nocheck(obj, "total_entries", json_integer((json_int_t)total_entries)); json_object_set_new_nocheck(obj, "duration", json_integer((json_int_t)duration)); return obj; } #else void compose_json(u_int64_t wtc, u_int64_t wtc_2) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); } void *compose_purge_init_json(char *writer_name, pid_t writer_pid) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_purge_init_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); return NULL; } void *compose_purge_close_json(char *writer_name, pid_t writer_pid, int purged_entries, int total_entries, int duration) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_purge_close_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); return NULL; } #endif void compose_json_map_label(json_t *obj, struct chained_cache *cc) { char empty_string[] = "", *str_ptr; vlen_prims_get(cc->pvlen, COUNT_INT_LABEL, &str_ptr); if (!str_ptr) str_ptr = empty_string; /* labels normalization */ cdada_str_t *lbls_cdada = cdada_str_create(str_ptr); cdada_str_replace_all(lbls_cdada, PRETAG_LABEL_KV_SEP, DEFAULT_SEP); const char *lbls_norm = cdada_str(lbls_cdada); /* linked-list creation */ cdada_list_t *ptm_ll = ptm_labels_to_linked_list(lbls_norm); size_t ll_size = cdada_list_size(ptm_ll); json_t *root_l1 = compose_label_json_data(ptm_ll, ll_size); json_object_set_new_nocheck(obj, "label", root_l1); cdada_str_destroy(lbls_cdada); cdada_list_destroy(ptm_ll); } void compose_json_array_tcpflags(json_t *obj, struct chained_cache *cc) { /* linked-list creation */ cdada_list_t *ll = tcpflags_to_linked_list(cc->tcp_flags); size_t ll_size = cdada_list_size(ll); json_t *root_l1 = compose_tcpflags_json_data(ll, ll_size); json_object_set_new_nocheck(obj, "tcp_flags", root_l1); cdada_list_destroy(ll); } void compose_json_string_fwd_status(json_t *obj, struct chained_cache *cc) { /* linked-list creation */ cdada_list_t *fwd_status_ll = fwd_status_to_linked_list(); size_t ll_size = cdada_list_size(fwd_status_ll); json_t *root_l1 = compose_fwd_status_json_data(cc->pnat->fwd_status, fwd_status_ll, ll_size); json_object_set_new_nocheck(obj, "fwd_status", root_l1); cdada_list_destroy(fwd_status_ll); } void compose_json_array_mpls_label_stack(json_t *obj, struct chained_cache *cc) { char *label_stack_ptr = NULL; int label_stack_len = 0; label_stack_len = vlen_prims_get(cc->pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); json_t *root_l1 = compose_mpls_label_stack_json_data((u_int32_t *)label_stack_ptr, label_stack_len); json_object_set_new_nocheck(obj, "mpls_label_stack", root_l1); } json_t *compose_label_json_data(cdada_list_t *ll, int ll_size) { ptm_label lbl; json_t *root = json_object(); json_t *j_str_tmp = NULL; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&lbl, 0, sizeof(lbl)); cdada_list_get(ll, idx_0, &lbl); j_str_tmp = json_string(lbl.value); json_object_set_new_nocheck(root, lbl.key, j_str_tmp); } return root; } json_t *compose_tcpflags_json_data(cdada_list_t *ll, int ll_size) { tcpflag tcpstate; json_t *root = json_array(); json_t *j_str_tmp = NULL; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&tcpstate, 0, sizeof(tcpstate)); cdada_list_get(ll, idx_0, &tcpstate); if (strncmp(tcpstate.flag, "NULL", (TCP_FLAG_LEN - 1)) != 0) { j_str_tmp = json_string(tcpstate.flag); json_array_append(root, j_str_tmp); } } return root; } json_t *compose_fwd_status_json_data(size_t fwdstatus_decimal, cdada_list_t *ll, int ll_size) { fwd_status fwdstate; json_t *root = NULL; /* default fwdstatus */ if ((fwdstatus_decimal >= 0) && (fwdstatus_decimal <= 63)) { root = json_string("UNKNOWN Unclassified"); } else if ((fwdstatus_decimal >= 64) && (fwdstatus_decimal <= 127)) { root = json_string("FORWARDED Unclassified"); } else if ((fwdstatus_decimal >= 128) && (fwdstatus_decimal <= 191)) { root = json_string("DROPPED Unclassified"); } else if ((fwdstatus_decimal >= 192) && (fwdstatus_decimal <= 255)) { root = json_string("CONSUMED Unclassified"); } else { root = json_string("RFC-7270 Misinterpreted"); } size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&fwdstate, 0, sizeof(fwdstate)); cdada_list_get(ll, idx_0, &fwdstate); if (fwdstate.decimal == fwdstatus_decimal) { json_string_set(root, fwdstate.description); } } return root; } json_t *compose_mpls_label_stack_json_data(u_int32_t *label_stack, int ls_len) { const int MAX_IDX_LEN = 4; const int MAX_MPLS_LABEL_IDX_LEN = (MAX_IDX_LEN + MAX_MPLS_LABEL_LEN); int max_mpls_label_idx_len_dec = 0; char label_buf[MAX_MPLS_LABEL_LEN]; char label_idx_buf[MAX_MPLS_LABEL_IDX_LEN]; char idx_buf[MAX_IDX_LEN]; u_int8_t ls_depth = 0; if (!(ls_len % 4)) { ls_depth = (ls_len / 4); } else { return NULL; } json_t *root = json_array(); json_t *j_str_tmp = NULL; size_t idx_0; for (idx_0 = 0; idx_0 < ls_depth; idx_0++) { memset(&label_buf, 0, sizeof(label_buf)); snprintf(label_buf, MAX_MPLS_LABEL_LEN, "%u", *(label_stack + idx_0)); memset(&idx_buf, 0, sizeof(idx_buf)); memset(&label_idx_buf, 0, sizeof(label_idx_buf)); snprintf(idx_buf, MAX_IDX_LEN, "%zu", idx_0); strncat(label_idx_buf, idx_buf, (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); strncat(label_idx_buf, "-", (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); strncat(label_idx_buf, label_buf, (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); max_mpls_label_idx_len_dec = (strlen(idx_buf) + strlen("-") + strlen(label_buf) + 3); j_str_tmp = json_string(label_idx_buf); json_array_append(root, j_str_tmp); } return root; } pmacct-1.7.8/src/pmbmpd.c0000644000175000017500000002515114354105275014230 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp/bmp.h" #include "pmbmpd.h" #include "pretag_handlers.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_flow.h" #include "net_aggr.h" /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", PMBMPD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -L IP address ] [ -l port ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -L \tBind to the specified IP address\n"); printf(" -l \tListen on the specified TCP port\n"); printf(" -I \tRead packets from the specified savefile\n"); printf(" -Z \tReading from a savefile, sleep the given amount of seconds at startup and between replays\n"); printf(" -Y \tReading from a savefile, replay the number of times specified\n"); printf(" -T \tReading from a savefile, apply the filter specified with tcpdump syntax, ie. \"dst port 1790\"\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -D \tDaemonize\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -o \tOutput file to log real-time BMP messages\n"); printf(" -O \tOutput file to dump BMP data and generated RIBs at regular time intervals\n"); printf(" -i \tInterval, in secs, to write to the dump output file (supplied by -O)\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { struct plugins_list_entry *list; char config_file[SRVBUFLEN]; int logf; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); log_notifications_init(&log_notifications); config.acct_type = ACCT_PMBMP; config.progname = pmbmpd_globstr; find_id_func = NULL; plugins_list = NULL; errflag = 0; rows = 0; /* needed for pre_tag_map support */ PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_PMBMPD)) != -1)) { cfg_cmdline[rows] = malloc(SRVBUFLEN); switch (cp) { case 'L': strlcpy(cfg_cmdline[rows], "bmp_daemon_ip: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'l': strlcpy(cfg_cmdline[rows], "bmp_daemon_port: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'I': strlcpy(cfg_cmdline[rows], "pcap_savefile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Z': strlcpy(cfg_cmdline[rows], "pcap_savefile_delay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Y': strlcpy(cfg_cmdline[rows], "pcap_savefile_replay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'T': strlcpy(cfg_cmdline[rows], "pcap_filter: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "bmp_daemon_msglog_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "bmp_dump_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'i': strlcpy(cfg_cmdline[rows], "bmp_dump_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, PMBMPD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } list = plugins_list; while (list) { list->cfg.acct_type = ACCT_PMBMP; list->cfg.progname = pmbmpd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, PMBMPD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); if (!config.bmp_daemon_port) config.bmp_daemon_port = BMP_TCP_PORT; #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif bmp_prepare_daemon(); skinny_bmp_daemon(); return 0; } pmacct-1.7.8/src/mpls.h0000644000175000017500000000073714354105275013734 0ustar paolopaolo#define LABEL_MASK 0xfffff000 #define LABEL_SHIFT 12 #define EXP_MASK 0x00000e00 #define EXP_SHIFT 9 #define STACK_MASK 0x00000100 #define STACK_SHIFT 8 #define TTL_MASK 0x000000ff #define TTL_SHIFT 0 #define MPLS_LABEL(x) (((x) & LABEL_MASK) >> LABEL_SHIFT) #define MPLS_EXP(x) (((x) & EXP_MASK) >> EXP_SHIFT) #define MPLS_STACK(x) (((x) & STACK_MASK) >> STACK_SHIFT) #define MPLS_TTL(x) (((x) & TTL_MASK) >> TTL_SHIFT) pmacct-1.7.8/src/external_libs/0000755000175000017500000000000014354105415015430 5ustar paolopaolopmacct-1.7.8/src/external_libs/Makefile.in0000644000175000017500000004046014354105415017501 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/external_libs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ #Build all submodule deps BUILT_SOURCES = submodule_deps CLEANFILES = .libcdada_mark #Placed abnormally here, just because vim syntax highlighter has a bug MAKE_JOBS := `ps T | sed -n 's/.*$(MAKE_PID).*$(MAKE).* \(-j\|--jobs=\) *\([0-9][0-9]*\).*/-j \2/p'` all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/external_libs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/external_libs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check install install-am install-exec install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am .PRECIOUS: Makefile #NOTE some pmacct users _love_ vintage software, and they run versions of git # (like v1.8.3) which don't support initializing submodules from anywhere other # than the root.... sigh .PHONY: libcdada libcdada_maintainer_clean libcdada: @not_git=0; \ if [ -z "`git rev-parse HEAD 2> /dev/null`" ]; then \ if [ -f "$(abs_srcdir)/libcdada/include/cdada.h" ]; then \ not_git=1; \ PMACCT_EXT_LIBS_DONT_SYNC=1; \ cd $(abs_builddir); \ else \ echo "[dep: libcdada] Skipping, not a git repository and code not in tree!"; \ exit 0;\ fi;\ fi;\ echo "[dep: libcdada] Checking..."; \ if [ $$not_git -eq 0 ] && [ ! -f "$(abs_srcdir)/libcdada/.git" ]; then \ echo "[dep: libcdada] Cloning and checking out commit..";\ cd $(abs_top_srcdir); \ git submodule update --init --recursive src/external_libs/libcdada; \ if [ $$? != 0 ]; then exit 1; fi;\ cd $(abs_builddir); \ fi;\ if [ ! -f $(abs_builddir)/.libcdada_mark ] || \ [ "`cat $(abs_builddir)/.libcdada_mark 2> /dev/null`" != "`git ls-tree HEAD $(abs_srcdir)/libcdada/ | awk '{print $$3}' 2> /dev/null`" ] || \ [ "`cat $(abs_builddir)/.libcdada_mark 2> /dev/null`" != "`cd $(abs_srcdir)/libcdada && git rev-parse HEAD 2> /dev/null`" ]; then \ \ if [ -z "$$PMACCT_EXT_LIBS_DONT_SYNC" ]; then \ echo "[dep: libcdada] Syncing commit...";\ cd $(abs_top_srcdir); \ git submodule update --init --recursive src/external_libs/libcdada 2> /dev/null; \ if [ $$? != 0 ]; then exit 1; fi;\ cd $(abs_builddir); \ else\ echo "[dep: libcdada] Skipping commit sync..";\ fi;\ echo "[dep: libcdada] Building...";\ mkdir -p $(abs_builddir)/libcdada/build || true; \ cd $(abs_srcdir)/libcdada/ && \ ./autogen.sh &&\ cd $(abs_builddir)/libcdada/build && \ $(abs_srcdir)/libcdada/configure --disable-shared --host=$(host_alias) @configure_silent_rules_val@ \ --prefix=$(abs_builddir)/rootfs && make $(MAKE_JOBS) install;\ if [ $$? != 0 ]; then exit 1; fi; \ echo "`cd $(abs_srcdir)/libcdada && git rev-parse HEAD 2> /dev/null`" > $(abs_builddir)/.libcdada_mark;\ if [ $$? != 0 ]; then exit 1; fi; \ echo "[dep: libcdada] Done!";\ else\ echo "[dep: libcdada] Up-to-date!";\ fi libcdada_maintainer_clean: @rm -rf $(builddir)/libcdada/build/* submodule_prep: @mkdir -p $(builddir)/rootfs #List all of them here submodule_deps: submodule_prep libcdada #Deep cleanup maintainer-clean-local: libcdada_maintainer_clean rm -rf $(abs_builddir)/rootfs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/0000755000175000017500000000000014354105633017155 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/tools/0000755000175000017500000000000014354105430020310 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/tools/cdada-gen0000755000175000017500000005210514354105336022051 0ustar paolopaolo#!/usr/bin/env python3 """ libcdada code generator (custom types) Generate C++ wrappers to use with libcdada. https://github.com/msune/libcdada LICENSE: BSD 2-clause """ import sys MEMCMP_OP=""" inline bool operator<(const TT_TYPE_TT & a1, const TT_TYPE_TT & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( TT_TYPE_TT )) < 0; } inline bool operator==(const TT_TYPE_TT & a1, const TT_TYPE_TT & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( TT_TYPE_TT )) == 0; } """ LIST=""" //Operator void __cdada_list_autogen_create_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; s->list.custom = (void*)new std::list(); } void __cdada_list_autogen_destroy_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; delete p; } void __cdada_list_autogen_clear_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->clear(); } bool __cdada_list_autogen_empty_TT_TYPE_TT (const void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return p->empty(); } uint32_t __cdada_list_autogen_size_TT_TYPE_TT (const void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return p->size(); } int __cdada_list_autogen_insert_TT_TYPE_TT (void* m, const void* val, const uint32_t pos){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_insert_u (s, p, val, pos); } int __cdada_list_autogen_get_TT_TYPE_TT (const void* m, const uint32_t pos, void* val){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_get_u (s, p, pos, val); } int __cdada_list_autogen_first_last_TT_TYPE_TT (const void* m, bool first, void* key){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_first_last_u (s, p, first, key); } int __cdada_list_autogen_erase_TT_TYPE_TT (void* m, const uint32_t pos){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_erase_u (s, p, pos); } int __cdada_list_autogen_remove_TT_TYPE_TT (void* m, const void* val){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_remove_u (s, p, val); } int __cdada_list_autogen_push_TT_TYPE_TT (void* m, const void* val, bool front){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_push_u (s, p, val, front); } int __cdada_list_autogen_pop_TT_TYPE_TT (void* m, bool front){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_pop_u (s, p, front); } void __cdada_list_autogen_sort_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->sort(); } void __cdada_list_autogen_reverse_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->reverse(); } void __cdada_list_autogen_unique_TT_TYPE_TT (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->unique(); } void __cdada_list_autogen_traverse_TT_TYPE_TT (const void* m, cdada_list_it f, void* opaque){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_traverse_u (s, p, f, opaque); } void __cdada_list_autogen_rtraverse_TT_TYPE_TT (const void* m, cdada_list_it f, void* opaque){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_rtraverse_u (s, p, f, opaque); } void __cdada_list_autogen_dump_TT_TYPE_TT (const void* m, std::stringstream& ss){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_dump_u< TT_TYPE_TT > (s, p, ss); } __cdada_list_ops_t __cdada_list_autogen_TT_TYPE_TT = { __cdada_list_autogen_create_TT_TYPE_TT, __cdada_list_autogen_destroy_TT_TYPE_TT, __cdada_list_autogen_clear_TT_TYPE_TT, __cdada_list_autogen_empty_TT_TYPE_TT, __cdada_list_autogen_size_TT_TYPE_TT, __cdada_list_autogen_insert_TT_TYPE_TT, __cdada_list_autogen_get_TT_TYPE_TT, __cdada_list_autogen_first_last_TT_TYPE_TT, __cdada_list_autogen_erase_TT_TYPE_TT, __cdada_list_autogen_remove_TT_TYPE_TT, __cdada_list_autogen_push_TT_TYPE_TT, __cdada_list_autogen_pop_TT_TYPE_TT, __cdada_list_autogen_sort_TT_TYPE_TT, __cdada_list_autogen_reverse_TT_TYPE_TT, __cdada_list_autogen_unique_TT_TYPE_TT, __cdada_list_autogen_traverse_TT_TYPE_TT, __cdada_list_autogen_rtraverse_TT_TYPE_TT, __cdada_list_autogen_dump_TT_TYPE_TT, }; """ MAP =""" void __cdada_map_autogen_create_TT_TYPE_TT (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; s->map.custom = (void*)new std::map(); } void __cdada_map_autogen_destroy_TT_TYPE_TT (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; delete p; } void __cdada_map_autogen_clear_TT_TYPE_TT (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; p->clear(); } bool __cdada_map_autogen_empty_TT_TYPE_TT (const void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return p->empty(); } uint32_t __cdada_map_autogen_size_TT_TYPE_TT (const void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return p->size(); } int __cdada_map_autogen_insert_TT_TYPE_TT (void* m, const void* key, void* val, const bool replace){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_insert_u (s, p, key, val, replace); } int __cdada_map_autogen_erase_TT_TYPE_TT (void* m, const void* key){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_erase_u (s, p, key); } int __cdada_map_autogen_find_TT_TYPE_TT (const void* m, const void* key, void** val){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_find_u (s, p, key, val); } int __cdada_map_autogen_first_last_TT_TYPE_TT (const void* m, bool first, void* key, void** val){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_first_last_u (s, p, first, key, val); } void __cdada_map_autogen_traverse_TT_TYPE_TT (const void* m, cdada_map_it f, void* opaque){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_traverse_u (s, p, f, opaque); } void __cdada_map_autogen_rtraverse_TT_TYPE_TT (const void* m, cdada_map_it f, void* opaque){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_rtraverse_u (s, p, f, opaque); } void __cdada_map_autogen_dump_TT_TYPE_TT (const void* m, std::stringstream& ss){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_dump_u< TT_TYPE_TT > (s, p, ss); } __cdada_map_ops_t __cdada_map_autogen_TT_TYPE_TT = { __cdada_map_autogen_create_TT_TYPE_TT, __cdada_map_autogen_destroy_TT_TYPE_TT, __cdada_map_autogen_clear_TT_TYPE_TT, __cdada_map_autogen_empty_TT_TYPE_TT, __cdada_map_autogen_size_TT_TYPE_TT, __cdada_map_autogen_insert_TT_TYPE_TT, __cdada_map_autogen_erase_TT_TYPE_TT, __cdada_map_autogen_find_TT_TYPE_TT, __cdada_map_autogen_first_last_TT_TYPE_TT, __cdada_map_autogen_traverse_TT_TYPE_TT, __cdada_map_autogen_rtraverse_TT_TYPE_TT, __cdada_map_autogen_dump_TT_TYPE_TT, }; """ QUEUE=""" //Operator void __cdada_queue_autogen_create_TT_TYPE_TT (void* m){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; s->queue.custom = (void*)new std::queue(); } void __cdada_queue_autogen_destroy_TT_TYPE_TT (void* m){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; delete p; } bool __cdada_queue_autogen_empty_TT_TYPE_TT (const void* m){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return p->empty(); } uint32_t __cdada_queue_autogen_size_TT_TYPE_TT (const void* m){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return p->size(); } int __cdada_queue_autogen_push_TT_TYPE_TT (void* m, const void* val){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return cdada_queue_push_u (s, p, val); } int __cdada_queue_autogen_pop_TT_TYPE_TT (void* m){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return cdada_queue_pop_u (s, p); } int __cdada_queue_autogen_front_TT_TYPE_TT (const void* m, void* val){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return cdada_queue_front_u (s, p, val); } int __cdada_queue_autogen_back_TT_TYPE_TT (const void* m, void* val){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return cdada_queue_back_u (s, p, val); } void __cdada_queue_autogen_dump_TT_TYPE_TT (const void* m, std::stringstream& ss){ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; std::queue* p = (std::queue*)s->queue.custom; return cdada_queue_dump_u< TT_TYPE_TT > (s, p, ss); } __cdada_queue_ops_t __cdada_queue_autogen_TT_TYPE_TT = { __cdada_queue_autogen_create_TT_TYPE_TT, __cdada_queue_autogen_destroy_TT_TYPE_TT, __cdada_queue_autogen_empty_TT_TYPE_TT, __cdada_queue_autogen_size_TT_TYPE_TT, __cdada_queue_autogen_push_TT_TYPE_TT, __cdada_queue_autogen_pop_TT_TYPE_TT, __cdada_queue_autogen_front_TT_TYPE_TT, __cdada_queue_autogen_back_TT_TYPE_TT, __cdada_queue_autogen_dump_TT_TYPE_TT, }; """ SET =""" void __cdada_set_autogen_create_TT_TYPE_TT (void* m){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; s->set.custom = (void*)new std::set(); } void __cdada_set_autogen_destroy_TT_TYPE_TT (void* m){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; delete p; } void __cdada_set_autogen_clear_TT_TYPE_TT (void* m){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; p->clear(); } bool __cdada_set_autogen_empty_TT_TYPE_TT (const void* m){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return p->empty(); } uint32_t __cdada_set_autogen_size_TT_TYPE_TT (const void* m){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return p->size(); } int __cdada_set_autogen_insert_TT_TYPE_TT (void* m, const void* key){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_insert_u< TT_TYPE_TT > (s, p, key); } int __cdada_set_autogen_erase_TT_TYPE_TT (void* m, const void* key){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p =(std::set*)s->set.custom; return cdada_set_erase_u< TT_TYPE_TT > (s, p, key); } bool __cdada_set_autogen_find_TT_TYPE_TT (const void* m, const void* key){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_find_u< TT_TYPE_TT > (s, p, key); } int __cdada_set_autogen_first_last_TT_TYPE_TT (const void* m, bool first, void* key){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_first_last_u< TT_TYPE_TT > (s, p, first, key); } void __cdada_set_autogen_traverse_TT_TYPE_TT (const void* m, cdada_set_it f, void* opaque){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_traverse_u< TT_TYPE_TT > (s, p, f, opaque); } void __cdada_set_autogen_rtraverse_TT_TYPE_TT (const void* m, cdada_set_it f, void* opaque){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_rtraverse_u< TT_TYPE_TT > (s, p, f, opaque); } void __cdada_set_autogen_dump_TT_TYPE_TT (const void* m, std::stringstream& ss){ __cdada_set_int_t* s = (__cdada_set_int_t*)m; std::set* p = (std::set*)s->set.custom; return cdada_set_dump_u< TT_TYPE_TT > (s, p, ss); } __cdada_set_ops_t __cdada_set_autogen_TT_TYPE_TT = { __cdada_set_autogen_create_TT_TYPE_TT, __cdada_set_autogen_destroy_TT_TYPE_TT, __cdada_set_autogen_clear_TT_TYPE_TT, __cdada_set_autogen_empty_TT_TYPE_TT, __cdada_set_autogen_size_TT_TYPE_TT, __cdada_set_autogen_insert_TT_TYPE_TT, __cdada_set_autogen_erase_TT_TYPE_TT, __cdada_set_autogen_find_TT_TYPE_TT, __cdada_set_autogen_first_last_TT_TYPE_TT, __cdada_set_autogen_traverse_TT_TYPE_TT, __cdada_set_autogen_rtraverse_TT_TYPE_TT, __cdada_set_autogen_dump_TT_TYPE_TT, }; """ STACK=""" //Operator void __cdada_stack_autogen_create_TT_TYPE_TT (void* m){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; s->stack.custom = (void*)new std::stack(); } void __cdada_stack_autogen_destroy_TT_TYPE_TT (void* m){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; delete p; } bool __cdada_stack_autogen_empty_TT_TYPE_TT (const void* m){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return p->empty(); } uint32_t __cdada_stack_autogen_size_TT_TYPE_TT (const void* m){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return p->size(); } int __cdada_stack_autogen_push_TT_TYPE_TT (void* m, const void* val){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return cdada_stack_push_u (s, p, val); } int __cdada_stack_autogen_pop_TT_TYPE_TT (void* m){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return cdada_stack_pop_u (s, p); } int __cdada_stack_autogen_top_TT_TYPE_TT (const void* m, void* val){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return cdada_stack_top_u (s, p, val); } void __cdada_stack_autogen_dump_TT_TYPE_TT (const void* m, std::stringstream& ss){ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; std::stack* p = (std::stack*)s->stack.custom; return cdada_stack_dump_u< TT_TYPE_TT > (s, p, ss); } __cdada_stack_ops_t __cdada_stack_autogen_TT_TYPE_TT = { __cdada_stack_autogen_create_TT_TYPE_TT, __cdada_stack_autogen_destroy_TT_TYPE_TT, __cdada_stack_autogen_empty_TT_TYPE_TT, __cdada_stack_autogen_size_TT_TYPE_TT, __cdada_stack_autogen_push_TT_TYPE_TT, __cdada_stack_autogen_pop_TT_TYPE_TT, __cdada_stack_autogen_top_TT_TYPE_TT, __cdada_stack_autogen_dump_TT_TYPE_TT, }; """ def parse_input(types): t = [] valid_types = ["list", "map", "queue", "set", "stack"] for s in types: if ":" not in s: print("ERROR: invalid format. Types should be CONTAINER:USER_TYPE. E.g. set::my_struct_t") sys.exit(1) a = s.split(":")[0] b = s.split(":")[1] if a not in valid_types: print("ERROR: invalid container type. Types should be {}".format(valid_types)) sys.exit(1) t.append(dict({a: b})) return t def generate(container, user_type): if container == "set": s_u = SET elif container == "map": s_u = MAP elif container == "queue": s_u = QUEUE elif container == "list": s_u = LIST elif container == "stack": s_u = STACK s_u = "//BEGIN {} for {} (std::{}<{}>)\n".format(container, user_type, container, user_type) + s_u s_u = s_u.replace("TT_TYPE_TT", user_type) s_u = s_u+"\n//END {} for {} (std::{}<{}>)\n\n".format(container, user_type, container, user_type) print(" cdada_{} for type '{}' => std::{}<{}>".format(container, user_type, container, user_type)) return s_u DESCRIPTION="libcdada code generator (custom types)" EPILOG=""" Generate C++ wrappers to use with libcdada. 1. Invoke generator with the types you want to support ~/ cdada-gen set:foo_t map:bar_t 2. Add header includes for types 'foo_t', 'bar_t' in the place holder ~/ vi autogen_cdada.cc 3. Add to your build system ~/ g++ -c autogen_cdada.cc 4. Link your application; make sure to link against -lcdada: ~/ gcc autogen_cdada.o -o your_app -lcdada """ if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter, epilog=EPILOG) parser.add_argument('types', metavar='types', type=str, nargs='+', help='types to generate; CONTAINER1:USER_TYPE1 CONTAINER2:USER_TYPE2') parser.add_argument("-o", "--output", default="autogen_cdada.cc", help="Output file") args = parser.parse_args() f = open(args.output, "w") f.write("/*****************************************************************************/\n") f.write("/* BEGIN libcdada AUTOGENERATED C++ file */\n") f.write("/*****************************************************************************/\n") f.write("// File autogenerated from cmd: {}\n".format(str(sys.argv))) s="" types = parse_input(args.types) if len(types) == 0: print("ERROR: you have to specify at least one type") sys.exit(1) print("Generating...") user_types = [] for t_ in types: u, t = next(iter(t_.items())) s = s+generate(u, t) user_types.append(t) unique_user_types = set(user_types) f.write("// Add your header includes for types {} here\n\n\n\n".format(str(unique_user_types))) f.write("///////////////////////////////////////////////////////////////////////////////\n") f.write("/// DO NOT MODIFY AFTER THIS LINE ///\n") f.write("///////////////////////////////////////////////////////////////////////////////\n\n") f.write("#include \n") f.write("#include \n") f.write("#include \n") f.write("#include \n") f.write("#include \n") f.write("#include \n\n") f.write("//C++ comparison operators for user stypes (memcmp)\n") for user_type in unique_user_types: ut = MEMCMP_OP ut = ut.replace("TT_TYPE_TT", user_type) f.write(ut) f.write("\n") f.write("//Cdata wrappers\n\n") f.write(s) f.write("/*****************************************************************************/\n") f.write("/* END libcdada AUTOGENERATED C++ file */\n") f.write("/*****************************************************************************/\n") pmacct-1.7.8/src/external_libs/libcdada/tools/Makefile.in0000644000175000017500000004216114354105430022361 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tools ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/config_m4/debug.m4 \ $(top_srcdir)/config_m4/profiling.m4 \ $(top_srcdir)/config_m4/versioning.m4 \ $(top_srcdir)/config_m4/valgrind.m4 \ $(top_srcdir)/config_m4/rdtsc.m4 \ $(top_srcdir)/config_m4/tests.m4 \ $(top_srcdir)/config_m4/examples.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = check-valgrind-recursive \ check-valgrind-memcheck-recursive \ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ check-valgrind-sgcheck-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDADA_BRANCH = @CDADA_BRANCH@ CDADA_BUILD = @CDADA_BUILD@ CDADA_DESCRIBE = @CDADA_DESCRIBE@ CDADA_VERSION = @CDADA_VERSION@ CDADA_VERSION_MAJOR = @CDADA_VERSION_MAJOR@ CDADA_VERSION_MINOR = @CDADA_VERSION_MINOR@ CDADA_VERSION_NORMALIZED = @CDADA_VERSION_NORMALIZED@ CDADA_VERSION_PATCH = @CDADA_VERSION_PATCH@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VALGRIND_ENABLED = @VALGRIND_ENABLED@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ ff_git = @ff_git@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ MAINTAINERCLEANFILES = Makefile.in @HAVE_PYTHON_TRUE@bin_SCRIPTS = cdada-gen all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs check-valgrind-local: check-valgrind-memcheck-local: check-valgrind-helgrind-local: check-valgrind-drd-local: check-valgrind-sgcheck-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) check-valgrind: check-valgrind-am check-valgrind-am: check-valgrind-local check-valgrind-drd: check-valgrind-drd-am check-valgrind-drd-am: check-valgrind-drd-local check-valgrind-helgrind: check-valgrind-helgrind-am check-valgrind-helgrind-am: check-valgrind-helgrind-local check-valgrind-memcheck: check-valgrind-memcheck-am check-valgrind-memcheck-am: check-valgrind-memcheck-local check-valgrind-sgcheck: check-valgrind-sgcheck-am check-valgrind-sgcheck-am: check-valgrind-sgcheck-local clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am check-valgrind-am \ check-valgrind-drd-am check-valgrind-drd-local \ check-valgrind-helgrind-am check-valgrind-helgrind-local \ check-valgrind-local check-valgrind-memcheck-am \ check-valgrind-memcheck-local check-valgrind-sgcheck-am \ check-valgrind-sgcheck-local clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-binSCRIPTS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-binSCRIPTS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/tools/Makefile.am0000644000175000017500000000012314354105336022345 0ustar paolopaoloMAINTAINERCLEANFILES = Makefile.in if HAVE_PYTHON bin_SCRIPTS = cdada-gen endif pmacct-1.7.8/src/external_libs/libcdada/autogen.sh0000755000175000017500000000010414354105336021151 0ustar paolopaolo#!/bin/sh export AUTOMAKE="automake --foreign -a" autoreconf -f -i pmacct-1.7.8/src/external_libs/libcdada/build-aux/0000755000175000017500000000000014354105430021042 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/build-aux/depcomp0000755000175000017500000005602014354105430022422 0ustar paolopaolo#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # 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 2, 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. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/src/external_libs/libcdada/build-aux/install-sh0000755000175000017500000003577614354105430023070 0ustar paolopaolo#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # 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. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # 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_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly 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 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. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -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 By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " 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 *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi 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 if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi 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=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi 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. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # 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 # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # 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 oIFS=$IFS IFS=/ set -f set fnord $dstdir shift 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=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_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 && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $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` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # 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 "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$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 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/src/external_libs/libcdada/build-aux/ar-lib0000755000175000017500000001336314354105430022144 0ustar paolopaolo#! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2019-07-04.01; # UTC # Copyright (C) 2010-2020 Free Software Foundation, Inc. # Written by Peter Rosin . # # 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 2, 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 file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin | msys) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat <, 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 Debian-2.4.6-15" 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='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=2015-10-07.11; # 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 _G_rc_run_hooks=false 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 if eval $_G_hook '"$@"'; then # 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 _G_rc_run_hooks=: fi done $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, you may remove/edit # any options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. In this case you also must return $EXIT_SUCCESS to let the # hook's caller know that it should pay attention to # '_result'. Returning $EXIT_FAILURE signalizes that # arguments are left untouched by the hook and therefore caller will ignore the # result variable. # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). There is # # no need to do the equivalent (but slower) action: # # func_quote_for_eval ${1+"$@"} # # my_options_prep_result=$func_quote_for_eval_result # false # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # 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=: # args_changed=: # ;; # # 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 # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@", we could need that later # # if $args_changed is true. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # if $args_changed; then # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # fi # # $args_changed # } # 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." # # false # } # func_add_hook func_validate_options my_option_validation # # You'll also 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_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd _G_func_options_finish_exit=false if func_run_hooks func_options ${1+"$@"}; then func_options_finish_result=$func_run_hooks_result _G_func_options_finish_exit=: fi $_G_func_options_finish_exit } # 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 _G_rc_options=false for my_func in options_prep parse_options validate_options options_finish do if eval func_$my_func '${1+"$@"}'; then eval _G_res_var='$'"func_${my_func}_result" eval set dummy "$_G_res_var" ; shift _G_rc_options=: fi done # Save modified positional parameters for caller. As a top-level # options-parser function we always need to set the 'func_options_result' # variable (regardless the $_G_rc_options value). if $_G_rc_options; then func_options_result=$_G_res_var else func_quote_for_eval ${1+"$@"} func_options_result=$func_quote_for_eval_result fi $_G_rc_options } # 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 propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= _G_rc_options_prep=false if func_run_hooks func_options_prep ${1+"$@"}; then _G_rc_options_prep=: # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result fi $_G_rc_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= _G_rc_parse_options=false # 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. if func_run_hooks func_parse_options ${1+"$@"}; then eval set dummy "$func_run_hooks_result"; shift _G_rc_parse_options=: fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_match_parse_options=: _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) if test $# = 0 && func_missing_arg $_G_opt; then _G_rc_parse_options=: break fi 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 ;; --) _G_rc_parse_options=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac $_G_match_parse_options && _G_rc_parse_options=: done if $_G_rc_parse_options; then # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result fi $_G_rc_parse_options } # 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 _G_rc_validate_options=false # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" if func_run_hooks func_validate_options ${1+"$@"}; then # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result _G_rc_validate_options=: fi # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE $_G_rc_validate_options } ## ----------------- ## ## 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 $scriptversion Debian-2.4.6-15 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= _G_rc_lt_options_prep=: # 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 ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result fi $_G_rc_lt_options_prep } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _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 _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result fi $_G_rc_lt_parse_options } 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 # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC # -static-* direct GCC to link specific libraries statically # -fcilkplus Cilk Plus language extension features for C/C++ -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=*| \ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) 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%" test "X$link_all_deplibs" != Xno && libs="$libs $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" 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 elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi 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 ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; 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: pmacct-1.7.8/src/external_libs/libcdada/build-aux/config.guess0000755000175000017500000012637314354105430023376 0ustar paolopaolo#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-24' # 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: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # 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. Options: -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-2018 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'`" # If ldd exists, use it to detect musl libc. if command -v ldd >/dev/null && \ ldd --version 2>&1 | grep -q ^musl then LIBC=musl fi ;; 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) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|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/[-_].*//' | cut -d. -f1,2` ;; 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 ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$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 ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 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 ;; 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:4.4BSD:*) 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` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac 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*: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 ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-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 "[:upper:]" "[:lower:]"``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 ;; k1om: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; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-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 ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-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:*:*) if objdump -f /bin/sh | grep -q elf32-x86-64; then echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 else echo "$UNAME_MACHINE"-pc-linux-"$LIBC" fi 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.*:*) 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 configure 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 ;; SX-ACE:SUPER-UX:*:*) echo sxace-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 # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc 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 ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-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 ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&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-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pmacct-1.7.8/src/external_libs/libcdada/build-aux/config.sub0000755000175000017500000010645014354105430023033 0ustar paolopaolo#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-22' # 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: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # 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 or ALIAS Canonicalize a configuration name. Options: -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-2018 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* | cloudabi*-eabi* | \ 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/'` ;; -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 \ | ba \ | 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 | ia16 | 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 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]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 \ | wasm32 \ | 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) ;; 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]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | 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-* | ia16-* | 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-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | 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-* \ | wasm32-* \ | 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-pc 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 ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; 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*) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=$os"spe" ;; 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 ;; 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 ;; 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 ;; 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 ;; nsv-tandem) basic_machine=nsv-tandem ;; nsx-tandem) basic_machine=nsx-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) 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) 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 ;; sh5el) basic_machine=sh5le-unknown ;; 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 ;; x64) basic_machine=x86_64-pc ;; 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 ;; 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 ;; 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 ;; 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 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) -es1800*) os=-ose ;; # Now 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* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -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* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ | -midnightbsd*) # 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 | -xray | -os68k* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* \ | -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 ;; -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 ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. case $basic_machine in arm*) os=-eabi ;; *) os=-elf ;; esac ;; -nacl*) ;; -ios) ;; -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 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-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 ;; *-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-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pmacct-1.7.8/src/external_libs/libcdada/build-aux/compile0000755000175000017500000001635014354105430022425 0ustar paolopaolo#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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 2, 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 file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/src/external_libs/libcdada/build-aux/missing0000755000175000017500000001533614354105430022451 0ustar paolopaolo#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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 2, 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. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: pmacct-1.7.8/src/external_libs/libcdada/m4/0000755000175000017500000000000014354105424017473 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/m4/ltsugar.m40000644000175000017500000001044014354105424021415 0ustar paolopaolo# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) pmacct-1.7.8/src/external_libs/libcdada/m4/libtool.m40000644000175000017500000112677114354105424021420 0ustar paolopaolo# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 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 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 . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*|11.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cr} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* 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@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # 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). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS pmacct-1.7.8/src/external_libs/libcdada/m4/ltversion.m40000644000175000017500000000127314354105424021765 0ustar paolopaolo# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) pmacct-1.7.8/src/external_libs/libcdada/m4/ltoptions.m40000644000175000017500000003426214354105424021777 0ustar paolopaolo# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) pmacct-1.7.8/src/external_libs/libcdada/m4/lt~obsolete.m40000644000175000017500000001377414354105424022323 0ustar paolopaolo# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) pmacct-1.7.8/src/external_libs/libcdada/AUTHORS0000644000175000017500000000054314354105336020227 0ustar paolopaololibcdada - basic data structures in C (`libstdc++` wrapper) ----------------------------------------------------------- Author: Marc Sune Contributors, ordered by first contribution date: Paolo Lucente Peter Dobransky pmacct-1.7.8/src/external_libs/libcdada/CHANGELOG.md0000644000175000017500000000325214354105336020770 0ustar paolopaolo## Changelog ``` Legend: - [+] New/improved feature - [B] Bug fixed - [K] Known issue - [O] Other ``` ### v0.4.0 (12th March 2022) - [+] Add `cdada_map_insert_replace()` ### v0.3.5 (20th April 2021) - [+] Improved public API documentation - [+] build: add --without-tests --without-examples build options - [B] Fix `E_EMPTY` return codes set/map/list/stack/queue - [B] Fix `make check` when valgrind is not installed ### v0.3.4 (14th January 2021) - [B] Fix several build errors on old GCC versions (GCC4.2) - [O] Replace travis-ci.com/org with Github Actions ### v0.3.3 (27th November 2020) - [B] Fix several issues with documentation ### v0.3.2 (3d November 2020) - [+] Add version and build MACROs and API calls - [B] Fix build when Python3 is not present by disabling gen tests ### v0.3.1 (22th July 2020) - [B] Fix benchmark compilation error due to rdtsc for non x86/amd64 archs (e.g. PowerPC) ### v0.3.0 (17th July 2020) - [+] Support for `cdada_queue`, FIFO queue - [+] Add support for get/set `max_capacity()` for `cdada_queue` and `cdada_stack` ### v0.2.2 (4th July 2020) - [B] cdada.h: add missing cdada container includes. Added coverage. ### v0.2.1 (7th June 2020) - [B] cdada-gen: fix incorrect parsing of container list input - [B] cdada-gen: fix missing implementation for dump() leading to SEGFAULT - [O] cdada-gen: added full coverage for cdada-gen generated code ### v0.2.0 (6th June 2020) - [+] Support for `cdada_bbitmap`, big bitmaps - [+] Support for `cdada_str`, strings - [+] Support for `cdada_stack`, LIFO queue - [+] Add `dump()` and `print()` support for all containers ### v0.1.0 (23d May 2020) - [+] Support for `cdada_list`, `cdada_map`, `cdada_set` pmacct-1.7.8/src/external_libs/libcdada/build/0000755000175000017500000000000014354105336020254 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/build/.empty0000644000175000017500000000000014354105336021401 0ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/aclocal.m40000644000175000017500000017527214354105426021033 0ustar paolopaolo# generated automatically by aclocal 1.16.3 -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Copyright (C) 2011-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper # if it is needed. If the detection of archiver interface fails, run # ACT-IF-FAIL (default is to abort configure with a proper error message). AC_DEFUN([AM_PROG_AR], [AC_BEFORE([$0], [LT_INIT])dnl AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([ar-lib])dnl AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], [AC_LANG_PUSH([C]) am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a ]) AC_LANG_POP([C])]) case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) m4_default([$1], [AC_MSG_ERROR([could not determine $AR interface])]) ;; esac AC_SUBST([AR])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*- # Copyright (C) 2012-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_EXTRA_RECURSIVE_TARGETS # -------------------------- # Define the list of user recursive targets. This macro exists only to # be traced by Automake, which will ensure that a proper definition of # user-defined recursive targets (and associated rules) is propagated # into all the generated Makefiles. # TODO: We should really reject non-literal arguments here... AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], []) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 dnl python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl python3.2 python3.1 python3.0 dnl python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Although site.py simply uses dnl sys.version[:3], printing that failed with Python 3.10, since the dnl trailing zero was eliminated. So now we output just the major dnl and minor version numbers, as numbers. Apparently the tertiary dnl version is not of interest. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) pmacct-1.7.8/src/external_libs/libcdada/config_m4/0000755000175000017500000000000014354105336021022 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/config_m4/rdtsc.m40000644000175000017500000000070714354105336022407 0ustar paolopaoloAC_MSG_CHECKING(whether RDTSC support is available) AC_LINK_IFELSE([ AC_LANG_SOURCE( [[ #include int main(){ unsigned int hi, lo; __asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi)); printf("%u, %u\n", hi, lo); return 0; } ]] ) ], [have_rdtsc=yes], [have_rdtsc=no]) if test "$have_rdtsc" = "yes"; then AC_DEFINE([HAVE_RDTSC], [], [Define if RDTSC support is detected.]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi pmacct-1.7.8/src/external_libs/libcdada/config_m4/versioning.m40000644000175000017500000000255014354105336023451 0ustar paolopaolo# Set application version based on the git version #Default CDADA_VERSION="$PACKAGE_VERSION" #Unknown (no GIT repository detected)" FILE_VERSION=`cat $srcdir/VERSION` AC_CHECK_PROG(ff_git,git,yes,no) #Normalize CDADA_VERSION_NORMALIZED=`echo $CDADA_VERSION | sed s/dev//g | sed s/RC.*//g | tr -d v` #Substs AC_SUBST([CDADA_VERSION], ["$CDADA_VERSION"]) AC_SUBST([CDADA_VERSION_NORMALIZED], ["$CDADA_VERSION_NORMALIZED"]) AC_MSG_CHECKING([the build version]) AC_MSG_RESULT([$CDADA_VERSION ($CDADA_VERSION_NORMALIZED)]) AC_MSG_CHECKING([the build number]) if test $ff_git = no then AC_MSG_RESULT([git not found!]) else if test -d $srcdir/.git ; then #Try to retrieve the build number _CDADA_GIT_BUILD=`git log -1 --pretty=%H` _CDADA_GIT_BRANCH=`git rev-parse --abbrev-ref HEAD` _CDADA_GIT_DESCRIBE=`git describe --abbrev=40` AC_SUBST([CDADA_BUILD], ["$_CDADA_GIT_BUILD"]) AC_SUBST([CDADA_BRANCH], ["$_CDADA_GIT_BRANCH"]) AC_SUBST([CDADA_DESCRIBE], ["$_CDADA_GIT_DESCRIBE"]) fi AC_MSG_RESULT([$_CDADA_GIT_BUILD]) fi #File version always exists CDADA_VERSION_MAJOR=`echo $CDADA_VERSION | awk -F "." '{ print $1 }' | sed 's/v//'` CDADA_VERSION_MINOR=`echo $CDADA_VERSION | awk -F "." '{ print $2 }'` CDADA_VERSION_PATCH=`echo $CDADA_VERSION | awk -F "." '{ print $3 }'` AC_SUBST(CDADA_VERSION_MAJOR) AC_SUBST(CDADA_VERSION_MINOR) AC_SUBST(CDADA_VERSION_PATCH) pmacct-1.7.8/src/external_libs/libcdada/config_m4/valgrind.m40000644000175000017500000002137614354105336023103 0ustar paolopaolo# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html # =========================================================================== # # SYNOPSIS # # AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) # AX_VALGRIND_CHECK() # # DESCRIPTION # # AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows # running `make check` under a variety of Valgrind tools to check for # memory and threading errors. # # Defines VALGRIND_CHECK_RULES which should be substituted in your # Makefile; and $enable_valgrind which can be used in subsequent configure # output. VALGRIND_ENABLED is defined and substituted, and corresponds to # the value of the --enable-valgrind option, which defaults to being # enabled if Valgrind is installed and disabled otherwise. Individual # Valgrind tools can be disabled via --disable-valgrind-, the # default is configurable via the AX_VALGRIND_DFLT command or is to use # all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT # calls must be made before the call to AX_VALGRIND_CHECK. # # If unit tests are written using a shell script and automake's # LOG_COMPILER system, the $(VALGRIND) variable can be used within the # shell scripts to enable Valgrind, as described here: # # https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html # # Usage example: # # configure.ac: # # AX_VALGRIND_DFLT([sgcheck], [off]) # AX_VALGRIND_CHECK # # in each Makefile.am with tests: # # @VALGRIND_CHECK_RULES@ # VALGRIND_SUPPRESSIONS_FILES = my-project.supp # EXTRA_DIST = my-project.supp # # This results in a "check-valgrind" rule being added. Running `make # check-valgrind` in that directory will recursively run the module's test # suite (`make check`) once for each of the available Valgrind tools (out # of memcheck, helgrind and drd) while the sgcheck will be skipped unless # enabled again on the commandline with --enable-valgrind-sgcheck. The # results for each check will be output to test-suite-$toolname.log. The # target will succeed if there are zero errors and fail otherwise. # # Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in # memcheck, helgrind, drd and sgcheck. These are useful because often only # some of those tools can be ran cleanly on a codebase. # # The macro supports running with and without libtool. # # LICENSE # # Copyright (c) 2014, 2015, 2016 Philip Withnall # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 17 dnl Configured tools m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]]) m4_set_add_all([valgrind_exp_tool_set], [sgcheck]) m4_foreach([vgtool], [valgrind_tool_list], [m4_define([en_dflt_valgrind_]vgtool, [on])]) AC_DEFUN([AX_VALGRIND_DFLT],[ m4_define([en_dflt_valgrind_$1], [$2]) ])dnl AM_EXTRA_RECURSIVE_TARGETS([check-valgrind]) m4_foreach([vgtool], [valgrind_tool_list], [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)]) AC_DEFUN([AX_VALGRIND_CHECK],[ dnl Check for --enable-valgrind AC_ARG_ENABLE([valgrind], [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], [enable_valgrind=$enableval],[enable_valgrind=]) AS_IF([test "$enable_valgrind" != "no"],[ # Check for Valgrind. AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind]) AS_IF([test "$VALGRIND" = ""],[ AS_IF([test "$enable_valgrind" = "yes"],[ AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) ],[ enable_valgrind=no ]) ],[ enable_valgrind=yes ]) ]) AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) # Check for Valgrind tools we care about. [valgrind_enabled_tools=] m4_foreach([vgtool],[valgrind_tool_list],[ AC_ARG_ENABLE([valgrind-]vgtool, m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl [AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl [AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]), [enable_valgrind_]vgtool[=$enableval], [enable_valgrind_]vgtool[=]) AS_IF([test "$enable_valgrind" = "no"],[ enable_valgrind_]vgtool[=no], [test "$enable_valgrind_]vgtool[" ]dnl m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[ AC_CACHE_CHECK([for Valgrind tool ]vgtool, [ax_cv_valgrind_tool_]vgtool,[ ax_cv_valgrind_tool_]vgtool[=no m4_set_contains([valgrind_exp_tool_set],vgtool, [m4_define([vgtoolx],[exp-]vgtool)], [m4_define([vgtoolx],vgtool)]) AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[ ax_cv_valgrind_tool_]vgtool[=yes ]) ]) AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[ AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool) ],[ enable_valgrind_]vgtool[=no ]) ],[ enable_valgrind_]vgtool[=yes ]) ]) AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])[" ]) AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool) ]) AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["]) AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools]) [VALGRIND_CHECK_RULES=' # Valgrind check # # Optional: # - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions # files to load. (Default: empty) # - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. # (Default: --num-callers=30) # - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: # memcheck, helgrind, drd, sgcheck). (Default: various) # Optional variables VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) VALGRIND_FLAGS ?= --num-callers=30 VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no VALGRIND_helgrind_FLAGS ?= --history-level=approx VALGRIND_drd_FLAGS ?= VALGRIND_sgcheck_FLAGS ?= # Internal use valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) valgrind_quiet = $(valgrind_quiet_$(V)) valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) valgrind_quiet_0 = --quiet valgrind_v_use = $(valgrind_v_use_$(V)) valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; # Support running with and without libtool. ifneq ($(LIBTOOL),) valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute else valgrind_lt = endif # Use recursive makes in order to ignore errors during check check-valgrind-am: ifeq ($(VALGRIND_ENABLED),yes) $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) else @echo "Need to reconfigure with --enable-valgrind" endif # Valgrind running VALGRIND_TESTS_ENVIRONMENT = \ $(TESTS_ENVIRONMENT) \ env VALGRIND=$(VALGRIND) \ G_SLICE=always-malloc,debug-blocks \ G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly VALGRIND_LOG_COMPILER = \ $(valgrind_lt) \ $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) define valgrind_tool_rule check-valgrind-$(1)-am: ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) ifneq ($$(TESTS),) $$(valgrind_v_use)$$(MAKE) check-TESTS \ TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ LOG_FLAGS="$$(valgrind_$(1)_flags)" \ TEST_SUITE_LOG=test-suite-$(1).log endif else ifeq ($$(VALGRIND_ENABLED),yes) @echo "Need to reconfigure with --enable-valgrind-$(1)" else @echo "Need to reconfigure with --enable-valgrind" endif endef $(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) A''M_DISTCHECK_CONFIGURE_FLAGS ?= A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind MOSTLYCLEANFILES ?= MOSTLYCLEANFILES += $(valgrind_log_files) .PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) '] AC_SUBST([VALGRIND_CHECK_RULES]) m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) ]) #Now check AX_VALGRIND_CHECK pmacct-1.7.8/src/external_libs/libcdada/config_m4/tests.m40000644000175000017500000000061014354105336022423 0ustar paolopaoloWITH_TESTS_DEFAULT=yes AC_MSG_CHECKING([whether to compile and run tests]) AC_ARG_WITH(tests, AS_HELP_STRING([--without-tests], [Do not build and run tests [default=with]]), [WITH_TESTS="$withval"], [WITH_TESTS="$WITH_TESTS_DEFAULT"] ) if test x"$WITH_TESTS" = x"yes"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([WITH_TESTS], [test "x$WITH_TESTS" = "xyes"]) pmacct-1.7.8/src/external_libs/libcdada/config_m4/profiling.m40000644000175000017500000000100414354105336023250 0ustar paolopaolo# Check for profiling mode AC_MSG_CHECKING(whether to enable profiling mode) profile_default="no" AC_ARG_ENABLE(profile, AS_HELP_STRING([--enable-profile], [turn on profile mode [default=no]]) , , enable_profile=$profile_default) if test "$enable_profile" = "yes"; then CFLAGS="$( echo $CFLAGS | sed s/-fomit-frame-pointer//g )" CXXFLAGS="$( echo $CXXFLAGS | sed s/-fomit-frame-pointer//g )" CFLAGS="$CFLAGS -pg" CXXFLAGS="$CXXFLAGS -pg" LDFLAGS="$LDFLAGS -pg" AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi pmacct-1.7.8/src/external_libs/libcdada/config_m4/debug.m40000644000175000017500000000123014354105336022346 0ustar paolopaolo# Check for debug mode - MUST BE THE FIRST CHECK AC_MSG_CHECKING(whether to enable debug mode) debug_default="no" AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [turn on debug mode [default=no]]) , , enable_debug=$debug_default) if test "$enable_debug" = "yes"; then CFLAGS="$CFLAGS -g -O0" CXXFLAGS="$CXXFLAGS -g -O0 -fno-inline" AC_DEFINE([DEBUG], [], [Description]) AC_MSG_RESULT(yes) else CFLAGS="$CFLAGS -O3" #--compiler-options -fno-strict-aliasing --compiler-options -fno-inline CXXFLAGS="$CXXFLAGS -O3" #-fomit-frame-pointer" AC_DEFINE([NDEBUG], [], [Description]) AC_MSG_RESULT(no) fi AM_CONDITIONAL(DEBUG, test "$enable_debug" = yes) pmacct-1.7.8/src/external_libs/libcdada/config_m4/examples.m40000644000175000017500000000063114354105336023102 0ustar paolopaoloWITH_EXAMPLES_DEFAULT=yes AC_MSG_CHECKING([whether to compile examples]) AC_ARG_WITH(examples, AS_HELP_STRING([--without-examples], [Do not build examples [default=with]]), [WITH_EXAMPLES="$withval"], [WITH_EXAMPLES="$WITH_EXAMPLES_DEFAULT"] ) if test x"$WITH_EXAMPLES" = x"yes"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([WITH_EXAMPLES], [test "x$WITH_EXAMPLES" = "xyes"]) pmacct-1.7.8/src/external_libs/libcdada/VERSION0000644000175000017500000000000714354105336020222 0ustar paolopaolov0.4.0 pmacct-1.7.8/src/external_libs/libcdada/configure.ac0000644000175000017500000000242514354105354021446 0ustar paolopaolom4_include([VERSION]) #Force reconf on VERSION change AC_INIT(LIBCDADA, m4_esyscmd_s(cat VERSION), marcdevel@gmail.com, libcdada, http://github.com/msune/libcdada) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_GNU_SOURCE AC_PROG_INSTALL AC_PROG_CC AC_PROG_CXX AC_PROG_LD AM_PROG_CC_C_O m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) PKG_PROG_PKG_CONFIG AUTOCONF_ENV="SHELL=/bin/sh" LT_INIT AC_ENABLE_STATIC # Some useful default flags CFLAGS="-std=gnu89 -Werror -Wall $CFLAGS" CXXFLAGS="-Werror -Wall $CXXFLAGS" AC_DEFINE([__STDC_FORMAT_MACROS], [], [Description]) # Check for Python3 AM_PATH_PYTHON([3],, [:]) AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) # Debug m4_include([config_m4/debug.m4]) # Check for profiling mode m4_include([config_m4/profiling.m4]) # Checking version m4_include([config_m4/versioning.m4]) # Checking valgrind m4_include([config_m4/valgrind.m4]) # Checking RDTSC m4_include([config_m4/rdtsc.m4]) # Tests m4_include([config_m4/tests.m4]) # Examples m4_include([config_m4/examples.m4]) # Output files AC_CONFIG_FILES([ Makefile include/Makefile examples/Makefile src/Makefile tools/Makefile include/cdada/version.h ]) AC_OUTPUT pmacct-1.7.8/src/external_libs/libcdada/include/0000755000175000017500000000000014354105430020573 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/include/cdada.h0000644000175000017500000000341014354105336022003 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_H__ #define __CDADA_H__ /** * @file cdada.h * @author Marc Sune * * @brief libcdada meta header file. This header includes headers from _all_ * data structures. Prefer inclusion of individual ones. */ #include #include #include #include #include #include #include #include #include #endif //__CDADA_H__ pmacct-1.7.8/src/external_libs/libcdada/include/Makefile.in0000644000175000017500000004674314354105430022656 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/config_m4/debug.m4 \ $(top_srcdir)/config_m4/profiling.m4 \ $(top_srcdir)/config_m4/versioning.m4 \ $(top_srcdir)/config_m4/valgrind.m4 \ $(top_srcdir)/config_m4/rdtsc.m4 \ $(top_srcdir)/config_m4/tests.m4 \ $(top_srcdir)/config_m4/examples.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(nobase_include_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(includedir)" HEADERS = $(nobase_include_HEADERS) am__extra_recursive_targets = check-valgrind-recursive \ check-valgrind-memcheck-recursive \ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ check-valgrind-sgcheck-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDADA_BRANCH = @CDADA_BRANCH@ CDADA_BUILD = @CDADA_BUILD@ CDADA_DESCRIBE = @CDADA_DESCRIBE@ CDADA_VERSION = @CDADA_VERSION@ CDADA_VERSION_MAJOR = @CDADA_VERSION_MAJOR@ CDADA_VERSION_MINOR = @CDADA_VERSION_MINOR@ CDADA_VERSION_NORMALIZED = @CDADA_VERSION_NORMALIZED@ CDADA_VERSION_PATCH = @CDADA_VERSION_PATCH@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VALGRIND_ENABLED = @VALGRIND_ENABLED@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ ff_git = @ff_git@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ MAINTAINERCLEANFILES = Makefile.in nobase_include_HEADERS = cdada.h cdada/version.h \ cdada/bbitmap.h \ cdada/list.h \ cdada/list_custom_cc.h \ cdada/map.h \ cdada/map_custom_cc.h \ cdada/queue.h \ cdada/queue_custom_cc.h \ cdada/set.h \ cdada/set_custom_cc.h \ cdada/stack.h \ cdada/stack_custom_cc.h \ cdada/str.h \ cdada/utils.h \ cdada/__common_internal.h \ cdada/__list_internal.h \ cdada/__map_internal.h \ cdada/__queue_internal.h \ cdada/__set_internal.h \ cdada/__stack_internal.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_includeHEADERS: $(nobase_include_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) check-valgrind-local: check-valgrind-memcheck-local: check-valgrind-helgrind-local: check-valgrind-drd-local: check-valgrind-sgcheck-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) check-valgrind: check-valgrind-am check-valgrind-am: check-valgrind-local check-valgrind-drd: check-valgrind-drd-am check-valgrind-drd-am: check-valgrind-drd-local check-valgrind-helgrind: check-valgrind-helgrind-am check-valgrind-helgrind-am: check-valgrind-helgrind-local check-valgrind-memcheck: check-valgrind-memcheck-am check-valgrind-memcheck-am: check-valgrind-memcheck-local check-valgrind-sgcheck: check-valgrind-sgcheck-am check-valgrind-sgcheck-am: check-valgrind-sgcheck-local clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-valgrind-am \ check-valgrind-drd-am check-valgrind-drd-local \ check-valgrind-helgrind-am check-valgrind-helgrind-local \ check-valgrind-local check-valgrind-memcheck-am \ check-valgrind-memcheck-local check-valgrind-sgcheck-am \ check-valgrind-sgcheck-local clean clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-nobase_includeHEADERS \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-nobase_includeHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/include/cdada/0000755000175000017500000000000014354105336021634 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/include/cdada/map_custom_cc.h0000644000175000017500000001635014354105336024626 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_MAP_CUSTOM_CC_H__ #define __CDADA_MAP_CUSTOM_CC_H__ //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #define __CDADA_INTERNAL_INCLUDE #include #include #include #include #include #include /** * @file cdada/map_custom_cc.h * @author Marc Sune * * @brief This file needs to be included in a C++ file to autogenerate the * code necessary to use a custom type as a key/value for cdada structs. */ #define __CDADA_STD_MAP_TYPE(T) std::map< T , void* > /** * @internal Custom type create f */ #define __CDADA_MAP_CUSTOM_CREATE_F(TYPE) \ void __cdada_map_autogen_create_##TYPE (void* m){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ s->map.custom = (void*)new __CDADA_STD_MAP_TYPE(TYPE)(); \ } /** * @internal Custom type destroy f */ #define __CDADA_MAP_CUSTOM_DESTROY_F(TYPE) \ void __cdada_map_autogen_destroy_##TYPE (void* m){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ delete p; \ } /** * @internal Custom type clear f */ #define __CDADA_MAP_CUSTOM_CLEAR_F(TYPE) \ void __cdada_map_autogen_clear_##TYPE (void* m){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ p->clear(); \ } /** * @internal Custom type empty f */ #define __CDADA_MAP_CUSTOM_EMPTY_F(TYPE) \ bool __cdada_map_autogen_empty_##TYPE (const void* m){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return p->empty(); \ } /** * @internal Custom type size f */ #define __CDADA_MAP_CUSTOM_SIZE_F(TYPE) \ uint32_t __cdada_map_autogen_size_##TYPE (const void* m){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return p->size(); \ } /** * @internal Custom type insert f */ #define __CDADA_MAP_CUSTOM_INSERT_F(TYPE) \ int __cdada_map_autogen_insert_##TYPE (void* m, const void* key, \ void* val, \ const bool replace){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_insert_u< TYPE > (s, p, key, val, replace);\ } /** * @internal Custom type erase f */ #define __CDADA_MAP_CUSTOM_ERASE_F(TYPE) \ int __cdada_map_autogen_erase_##TYPE (void* m, const void* key){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_erase_u< TYPE > (s, p, key);\ } /** * @internal Custom type find f */ #define __CDADA_MAP_CUSTOM_FIND_F(TYPE) \ int __cdada_map_autogen_find_##TYPE (const void* m, const void* key, \ void** val){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_find_u< TYPE > (s, p, key, val);\ } /** * @internal Custom type first_last f */ #define __CDADA_MAP_CUSTOM_FIRST_LAST_F(TYPE) \ int __cdada_map_autogen_first_last_##TYPE (const void* m, bool first, \ void* key, \ void** val){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_first_last_u< TYPE > (s, p, first, key, val);\ } /** * @internal Custom type traverse f */ #define __CDADA_MAP_CUSTOM_TRAVERSE_F(TYPE) \ void __cdada_map_autogen_traverse_##TYPE (const void* m, \ cdada_map_it f, \ void* opaque){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_traverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type rtraverse f */ #define __CDADA_MAP_CUSTOM_RTRAVERSE_F(TYPE) \ void __cdada_map_autogen_rtraverse_##TYPE (const void* m, \ cdada_map_it f, \ void* opaque){ \ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_rtraverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type dump f */ #define __CDADA_MAP_CUSTOM_DUMP_F(TYPE) \ void __cdada_map_autogen_dump_##TYPE (const void* m, \ std::stringstream& ss){\ __cdada_map_int_t* s = (__cdada_map_int_t*)m; \ __CDADA_STD_MAP_TYPE(TYPE)* p = \ (__CDADA_STD_MAP_TYPE(TYPE)*)s->map.custom; \ return cdada_map_dump_u< TYPE > (s, p, ss);\ } /** * @internal Create ops func ptrs struct */ #define __CDADA_MAP_CUSTOM_OPS(TYPE) \ __cdada_map_ops_t __cdada_map_autogen_##TYPE = { \ __cdada_map_autogen_create_##TYPE, \ __cdada_map_autogen_destroy_##TYPE, \ __cdada_map_autogen_clear_##TYPE, \ __cdada_map_autogen_empty_##TYPE, \ __cdada_map_autogen_size_##TYPE, \ __cdada_map_autogen_insert_##TYPE, \ __cdada_map_autogen_erase_##TYPE, \ __cdada_map_autogen_find_##TYPE, \ __cdada_map_autogen_first_last_##TYPE, \ __cdada_map_autogen_traverse_##TYPE, \ __cdada_map_autogen_rtraverse_##TYPE, \ __cdada_map_autogen_dump_##TYPE, \ } /** * Auto-generate (instantiate) new custom type map, with TYPE */ #define CDADA_MAP_CUSTOM_GEN(TYPE) \ __CDADA_MAP_CUSTOM_CREATE_F(TYPE); \ __CDADA_MAP_CUSTOM_DESTROY_F(TYPE); \ __CDADA_MAP_CUSTOM_CLEAR_F(TYPE); \ __CDADA_MAP_CUSTOM_EMPTY_F(TYPE); \ __CDADA_MAP_CUSTOM_SIZE_F(TYPE); \ __CDADA_MAP_CUSTOM_INSERT_F(TYPE); \ __CDADA_MAP_CUSTOM_ERASE_F(TYPE); \ __CDADA_MAP_CUSTOM_FIND_F(TYPE); \ __CDADA_MAP_CUSTOM_FIRST_LAST_F(TYPE); \ __CDADA_MAP_CUSTOM_TRAVERSE_F(TYPE); \ __CDADA_MAP_CUSTOM_RTRAVERSE_F(TYPE); \ __CDADA_MAP_CUSTOM_DUMP_F(TYPE); \ __CDADA_MAP_CUSTOM_OPS(TYPE) #undef __CDADA_INTERNAL_INCLUDE #endif //__CDADA_MAP_CUSTOM_CC_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__stack_internal.h0000644000175000017500000001075614354105336025315 0ustar paolopaolo/* Copyright (c) 2020, Peter Dobransky All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_STACK_INT__ #define __CDADA_STACK_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include /** * @file cdada/__stack_internal.h * @author Peter Dobransky * * @brief Internals of the stack wrapper */ /** * @internal Function pointer struct for autogen types */ typedef struct __cdada_stack_ops{ void (*create)(cdada_stack_t* s); void (*destroy)(cdada_stack_t* s); bool (*empty)(const cdada_stack_t* s); uint32_t (*size)(const cdada_stack_t* s); int (*push)(cdada_stack_t* s, const void* val); int (*pop)(cdada_stack_t* s); int (*top)(const cdada_stack_t* s, void *val); void (*dump)(const cdada_stack_t* m, std::stringstream& ss); }__cdada_stack_ops_t; /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; uint32_t user_val_len; uint32_t val_len; uint64_t max_capacity; union { std::stack* u8; std::stack* u16; std::stack* u32; std::stack* u64; std::stack* u128; std::stack* u256; std::stack* u512; std::stack* u1024; std::stack* u2048; void* custom; }stack; __cdada_stack_ops_t* ops; }__cdada_stack_int_t; template int cdada_stack_push_u(__cdada_stack_int_t* m, std::stack* m_u, const void* val){ if(m->val_len == m->user_val_len){ T* __attribute((__may_alias__)) aux; aux = (T*)val; m_u->push(*aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, val, m->user_val_len); m_u->push(aux); return CDADA_SUCCESS; } template int cdada_stack_pop_u(__cdada_stack_int_t* m, std::stack* m_u){ int rv = CDADA_E_EMPTY; if(!m_u->empty()){ m_u->pop(); rv = CDADA_SUCCESS; } return rv; } template int cdada_stack_top_u(__cdada_stack_int_t* m, std::stack* m_u, void *val){ T* __attribute((__may_alias__)) aux = (T*)val; int rv = CDADA_E_EMPTY; if(!m_u->empty()){ if(m->val_len == m->user_val_len){ *aux = m_u->top(); return CDADA_SUCCESS; } //Avoid padding from the wrapper aux = &(m_u->top()); memcpy(val, aux, m->user_val_len); return CDADA_SUCCESS; } return rv; } template bool cdada_stack_empty_u(__cdada_stack_int_t* m, std::stack* m_u){ return m_u->empty(); } template void cdada_stack_dump_u(const __cdada_stack_int_t* stack, std::stack* m_u, std::stringstream& ss){ typename std::stack aux; //No iterators in stack, ephemeral copy //TODO use extended stack class to avoid extra copy instead aux = *m_u; while(!aux.empty()){ T& t = aux.top(); __cdada_str_obj(ss, t, stack->user_val_len); aux.pop(); if(!aux.empty()) ss << ", "; } } #endif //__CDADA_STACK_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/map.h0000644000175000017500000002264614354105336022574 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_MAP_H__ #define __CDADA_MAP_H__ #include #include #include #include /** * @file cdada/map.h * @author Marc Sune * * @brief Map (hashmap, hashtable) data structure * * `cdada_map` data structure is a collection of unique elements of type `TYPE` * which have associated a value {key, value}. * During insertions, a _copy_ of the key `key` and a copy of the pointer value * `val` will be sotred in the container. * During accesses (e.g. `cdada_map_find`), if found, a _copy_ of the key is * stored in the region of memory pointed by `key`, and the (double) pointer * of value `val` is set. * * Uses std::map as a backend */ /** * cdada map structure */ typedef void cdada_map_t; //In case it's included from C++ CDADA_BEGIN_DECLS //Fwd decl //See cdada_map_create() for return codes struct __cdada_map_ops; cdada_map_t* __cdada_map_create(const uint16_t key_size, struct __cdada_map_ops* ops); /** * cdada map structure iterator * * @param map Map ptr * @param key Key (immutable) * @param val Value * @param opaque A pointer to an opaque object tat will be passed to the callback */ typedef void (*cdada_map_it)(const cdada_map_t* map, const void* key, void* val, void* opaque); /** * @brief Create and initialize a map data structure * * Allocate and initialize a map structure. Containers will perform better when * TYPE has a size of {1,2,4,8,16,32,64,128,256} bytes * * For types > 256, use custom containers * * @returns Returns a cdada_map object or NULL, if some error is found */ #define cdada_map_create(TYPE) \ __cdada_map_create(sizeof( TYPE ), NULL) /** * Destroy a map structure * * @returns Return codes: * CDADA_SUCCESS: map is destroyed * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_destroy(cdada_map_t* map); /** * Clear the contents of the map * * @returns Return codes: * CDADA_SUCCESS: map is cleared * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_clear(cdada_map_t* map); /** * Traverse map * * @param map Map * @param func Traverse function for this specific map * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: map was successfully traversed * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_traverse(const cdada_map_t* map, cdada_map_it func, void* opaque); /** * Reverse traverse map * * @param map Map * @param func Traverse function for this specific map * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: map was successfully reverse traversed * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_rtraverse(const cdada_map_t* map, cdada_map_it func, void* opaque); //Map properties /** * Is the map empty * * @returns Returns true if map is empty else (including invalid) false */ bool cdada_map_empty(const cdada_map_t* map); /** * Return the size (number of elements) in the map * * @returns Returns number of elements. If map is NULL or corrupted, returns 0 */ uint32_t cdada_map_size(const cdada_map_t* map); //Element manipulation /** * Insert an element (a copy of `key` and pointer `val`) in the map * * @param map Map pointer * @param key Key. The key type _must_ have all bytes initialized * @param val Pointer to the value * * @returns Return codes: * CDADA_SUCCESS: element is inserted * CDADA_E_EXISTS: element exists * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_insert(cdada_map_t* map, const void* key, void* val); /** * Insert or replace an element (a copy of `key` and pointer `val`) in the map * * @param map Map pointer * @param key Key. The key type _must_ have all bytes initialized * @param val Pointer to the value * * @returns Return codes: * CDADA_SUCCESS: element is inserted * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_insert_replace(cdada_map_t* map, const void* key, void* val); /** * Erase an element in the map * * @param map Map pointer * @param key Key. The key type _must_ have all bytes initialized * * @returns Return codes: * CDADA_SUCCESS: element was successfully erased * CDADA_E_NOT_FOUND: no element `key` was found * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_erase(cdada_map_t* map, const void* key); /** * Find a key in the map * * @param map Map pointer * @param key Key to search * @param val If element is found, *val will be set to the value pointer * * @returns Return codes: * CDADA_SUCCESS: element was successfully erased * CDADA_E_NOT_FOUND: no element `key` was found * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted or val is NULL */ int cdada_map_find(const cdada_map_t* map, const void* key, void** val); /** * Get the first element in the map * @param map Map pointer * @param key If map has elements, a copy of the first element key will be stored * in *key * @param val If map has elements, *val will be set to the value pointer * * @returns Return codes: * CDADA_SUCCESS: first element was retrieved * CDADA_E_EMPTY: map has no elements * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_first(const cdada_map_t* map, void* key, void** val); /** * Get the last element in the map * @param map Map pointer * @param key If map has elements, a copy of the first element key will be stored * in *key * @param val If map has elements, *val will be set to the value pointer * * @returns Return codes: * CDADA_SUCCESS: last element was retrieved * CDADA_E_EMPTY: map has no elements * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_last(const cdada_map_t* map, void* key, void** val); /** * Dump to a string the contents of the map * * @param map Map object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be map in * 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: map was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_dump(cdada_map_t* map, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the map * * @param map Map object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: map was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted map or internal error (bug) * CDADA_E_INVALID: map is NULL or corrupted */ int cdada_map_print(cdada_map_t* map, FILE *stream); //Custom types /** * Forward declare custom time ops */ #define CDADA_MAP_CUSTOM_TYPE_DECL(TYPE) \ extern struct __cdada_map_ops __cdada_map_autogen_##TYPE /** * @brief Create a map with a custom type, with a dedicated std::map * * Requires instantiating CDADA_MAP_CUSTOM_GEN() or * CDADA_MAP_CUSTOM_GEN_NO_MEMCP() once in a C++ compilation unit */ #define cdada_map_create_custom(TYPE) \ __cdada_map_create(sizeof( TYPE ), & __cdada_map_autogen_##TYPE ) CDADA_END_DECLS #endif //__CDADA_MAP_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/queue_custom_cc.h0000644000175000017500000001364614354105336025202 0ustar paolopaolo/* Copyright (c) 2020, Peter Dobransky All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_QUEUE_CUSTOM_CC_H__ #define __CDADA_QUEUE_CUSTOM_CC_H__ //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #define __CDADA_INTERNAL_INCLUDE #include #include #include #include #include #include /** * @file cdada/queue_custom_cc.h * @author Peter Dobransky * * @brief This file needs to be included in a C++ file to autogenerate the * code necessary to use a custom type as a val/value for cdada structs. */ #define __CDADA_STD_QUEUE_TYPE(T) std::queue< T > /** * @internal Custom type create f */ #define __CDADA_QUEUE_CUSTOM_CREATE_F(TYPE) \ void __cdada_queue_autogen_create_##TYPE (void* m){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ s->queue.custom = (void*)new __CDADA_STD_QUEUE_TYPE(TYPE)(); \ } /** * @internal Custom type destroy f */ #define __CDADA_QUEUE_CUSTOM_DESTROY_F(TYPE) \ void __cdada_queue_autogen_destroy_##TYPE (void* m){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ delete p; \ } /** * @internal Custom type empty f */ #define __CDADA_QUEUE_CUSTOM_EMPTY_F(TYPE) \ bool __cdada_queue_autogen_empty_##TYPE (const void* m){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return p->empty(); \ } /** * @internal Custom type size f */ #define __CDADA_QUEUE_CUSTOM_SIZE_F(TYPE) \ uint32_t __cdada_queue_autogen_size_##TYPE (const void* m){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return p->size(); \ } /** * @internal Custom type push f */ #define __CDADA_QUEUE_CUSTOM_PUSH_F(TYPE) \ int __cdada_queue_autogen_push_##TYPE (void* m, const void* val){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return cdada_queue_push_u< TYPE > (s, p, val);\ } /** * @internal Custom type pop f */ #define __CDADA_QUEUE_CUSTOM_POP_F(TYPE) \ int __cdada_queue_autogen_pop_##TYPE (void* m){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return cdada_queue_pop_u< TYPE > (s, p);\ } /** * @internal Custom type front f */ #define __CDADA_QUEUE_CUSTOM_FRONT_F(TYPE) \ int __cdada_queue_autogen_front_##TYPE (const void* m, void* val){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return cdada_queue_front_u< TYPE > (s, p, val);\ } /** * @internal Custom type back f */ #define __CDADA_QUEUE_CUSTOM_BACK_F(TYPE) \ int __cdada_queue_autogen_back_##TYPE (const void* m, void* val){ \ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom; \ return cdada_queue_back_u< TYPE > (s, p, val);\ } /** * @internal Custom type dump f */ #define __CDADA_QUEUE_CUSTOM_DUMP_F(TYPE) \ void __cdada_queue_autogen_dump_##TYPE (const void* m, \ std::stringstream& ss){\ __cdada_queue_int_t* s = (__cdada_queue_int_t*)m; \ __CDADA_STD_QUEUE_TYPE(TYPE)* p = \ (__CDADA_STD_QUEUE_TYPE(TYPE)*)s->queue.custom;\ return cdada_queue_dump_u< TYPE > (s, p, ss);\ } /** * @internal Create ops func ptrs struct */ #define __CDADA_QUEUE_CUSTOM_OPS(TYPE) \ __cdada_queue_ops_t __cdada_queue_autogen_##TYPE = { \ __cdada_queue_autogen_create_##TYPE, \ __cdada_queue_autogen_destroy_##TYPE, \ __cdada_queue_autogen_empty_##TYPE, \ __cdada_queue_autogen_size_##TYPE, \ __cdada_queue_autogen_push_##TYPE, \ __cdada_queue_autogen_pop_##TYPE, \ __cdada_queue_autogen_front_##TYPE, \ __cdada_queue_autogen_back_##TYPE, \ __cdada_queue_autogen_dump_##TYPE, \ } /** * Auto-generate (instantiate) new custom type queue, with TYPE */ #define CDADA_QUEUE_CUSTOM_GEN(TYPE) \ __CDADA_QUEUE_CUSTOM_CREATE_F(TYPE); \ __CDADA_QUEUE_CUSTOM_DESTROY_F(TYPE); \ __CDADA_QUEUE_CUSTOM_EMPTY_F(TYPE); \ __CDADA_QUEUE_CUSTOM_SIZE_F(TYPE); \ __CDADA_QUEUE_CUSTOM_PUSH_F(TYPE); \ __CDADA_QUEUE_CUSTOM_POP_F(TYPE); \ __CDADA_QUEUE_CUSTOM_FRONT_F(TYPE); \ __CDADA_QUEUE_CUSTOM_BACK_F(TYPE); \ __CDADA_QUEUE_CUSTOM_DUMP_F(TYPE); \ __CDADA_QUEUE_CUSTOM_OPS(TYPE) #undef __CDADA_INTERNAL_INCLUDE #endif //__CDADA_QUEUE_CUSTOM_CC_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__set_internal.h0000644000175000017500000001445414354105336025002 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_SET_INT__ #define __CDADA_SET_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include #include /** * @file cdada/set_internal.h * @author Marc Sune * * @brief Internals of the set wrapper */ /** * @internal Function pointer struct for autogen types */ typedef struct __cdada_set_ops{ void (*create)(cdada_set_t* m); void (*destroy)(cdada_set_t* m); void (*clear)(cdada_set_t* m); bool (*empty)(const cdada_set_t* m); uint32_t (*size)(const cdada_set_t* m); int (*insert)(cdada_set_t* m, const void* key); int (*erase)(cdada_set_t* m, const void* key); bool (*find)(const cdada_set_t* m, const void* key); int (*first_last)(const cdada_set_t* map, bool first, void* key); void (*traverse)(const cdada_set_t* m, cdada_set_it f, void* opaque); void (*rtraverse)(const cdada_set_t* m, cdada_set_it f, void* opaque); void (*dump)(const cdada_set_t* m, std::stringstream& ss); }__cdada_set_ops_t; /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; uint32_t user_key_len; uint32_t key_len; union { std::set* u8; std::set* u16; std::set* u32; std::set* u64; std::set* u128; std::set* u256; std::set* u512; std::set* u1024; std::set* u2048; void* custom; }set; __cdada_set_ops_t* ops; }__cdada_set_int_t; template int cdada_set_insert_u(__cdada_set_int_t* m, std::set* m_u, const void* key){ typename std::set::iterator it; if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; it = m_u->find(*aux); if(it != m_u->end()) return CDADA_E_EXISTS; m_u->insert(it, *aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); it = m_u->find(aux); if(it != m_u->end()) return CDADA_E_EXISTS; m_u->insert(it, aux); return CDADA_SUCCESS; } template int cdada_set_erase_u(__cdada_set_int_t* m, std::set* m_u, const void* key){ typename std::set::iterator it; if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; it = m_u->find(*aux); if(it == m_u->end()) return CDADA_E_NOT_FOUND; m_u->erase(it); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); it = m_u->find(aux); if(it == m_u->end()) return CDADA_E_NOT_FOUND; m_u->erase(it); return CDADA_SUCCESS; } template bool cdada_set_find_u(const __cdada_set_int_t* m, std::set* m_u, const void* key){ if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; return m_u->find(*aux) != m_u->end(); } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); return m_u->find(aux) != m_u->end(); } template int cdada_set_first_last_u(const __cdada_set_int_t* m, std::set* m_u, bool first, void* key){ T* __attribute((__may_alias__)) aux; aux = (T*)key; if(first){ typename std::set::const_iterator it; it = m_u->begin(); if(it == m_u->end()) return CDADA_E_EMPTY; if(m->key_len == m->user_key_len) *aux = *it; else memcpy(aux, &(*it), m->user_key_len); }else{ typename std::set::const_reverse_iterator rit; rit = m_u->rbegin(); if(rit == m_u->rend()) return CDADA_E_EMPTY; if(m->key_len == m->user_key_len) *aux = *rit; else memcpy(aux, &(*rit), m->user_key_len); } return CDADA_SUCCESS; } template void cdada_set_traverse_u(const cdada_set_t* set, std::set* m_u, cdada_set_it f, void* opaque){ typename std::set::const_iterator it; for(it = m_u->begin(); it != m_u->end(); ++it){ const T& t = *it; (*f)(set, &t, opaque); } } template void cdada_set_rtraverse_u(const cdada_set_t* set, std::set* m_u, cdada_set_it f, void* opaque){ typename std::set::const_reverse_iterator it; for(it = m_u->rbegin(); it != m_u->rend(); ++it){ const T& t = *it; (*f)(set, &t, opaque); } } template void cdada_set_dump_u(const __cdada_set_int_t* set, std::set* m_u, std::stringstream& ss){ typename std::set::const_iterator it; for(it = m_u->begin(); it != m_u->end();){ __cdada_str_obj(ss, *it, set->user_key_len); ++it; if(it != m_u->end()) ss << ", "; } } #endif //__CDADA_SET_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/stack.h0000644000175000017500000001637514354105336023126 0ustar paolopaolo/* Copyright (c) 2020, Peter Dobransky All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_STACK_H__ #define __CDADA_STACK_H__ #include #include #include #include /** * @file cdada/stack.h * @author Peter Dobransky * * @brief Stack(LIFO) data structure. * * `cdada_stack` data structure is a stack(LIFO) of elements of type 'TYPE'. * During insertions, a _copy_ of the element `val` will be stored in the stack. * During accesses (e.g. `cdada_stack_top`), if found, a _copy_ of the value * will be stored in the region of memory pointed by `val`. * * Uses std::stack as a backend */ /** * cdada stack structure */ typedef void cdada_stack_t; //In case it's included from C++ CDADA_BEGIN_DECLS //Fwd decl //See cdada_stack_create() for return codes struct __cdada_stack_ops; cdada_stack_t* __cdada_stack_create(const uint16_t val_size, struct __cdada_stack_ops* ops); /** * @brief Create and initialize a stack(LIFO) data structure * * Allocate and initialize a stack structure (std::stack). Containers will * perform better when TYPE has a size of {1,2,4,8,16,32,64,128,256} bytes * * For types > 256, use custom containers * * @returns Returns a cdada_stack object or NULL, if some error is found */ #define cdada_stack_create(TYPE) \ __cdada_stack_create(sizeof( TYPE ), NULL) /** * Destroy a stack structure * * @param stack Stack pointer * * @returns Return codes: * CDADA_SUCCESS: stack was destroyed * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_destroy(cdada_stack_t* stack); //Stack properties /** * Is the stack empty * * @param stack Stack pointer * * @returns Returns true if stack is empty else (including invalid) false */ bool cdada_stack_empty(const cdada_stack_t* stack); /** * Return the size (number of elements) in the stack * * @param stack Stack pointer * * @returns Returns number of elements. If stack is NULL or corrupted, returns 0 */ uint32_t cdada_stack_size(const cdada_stack_t* stack); /** * Get the maximum capacity (0 if unlimited) * * @param stack Stack pointer * * @returns Will return the maximum capacity of the stack or 0 if unlimited */ uint64_t cdada_stack_get_max_capacity(const cdada_stack_t* stack); /** * @brief Set the maximum capacity * * This function sets the maximum capacity of the stack. It can be called * at any time. If called when the stack has more elements than `limit`, * exceeding elements won't be removed, but the stack won't be able to * grow until the size is under the new set limit. * * Use the value 0 to remove the limit * * @param stack Stack pointer * @param limit Limit of the capacity (set to 0 for unlimited) * * @returns Return codes: * CDADA_SUCCESS: max capacity was successfully set * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_set_max_capacity(const cdada_stack_t* stack, const uint64_t limit); //Element manipulation /** * Push an element (a copy) to the front of the stack * * @param stack Stack pointer * @param val Element to push * * @returns Return codes: * CDADA_SUCCESS: element is pushed * CDADA_E_FULL: stack is full * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_push(cdada_stack_t* stack, const void* val); /** * Pop (remove) an element from the top * * @param stack Stack pointer * * @returns Return codes: * CDADA_SUCCESS: element is popped * CDADA_E_EMPTY: stack is empty * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_pop(cdada_stack_t* stack); /** * Get the element (a copy) on the top of the stack. * * @param stack Stack pointer * @param val Value pointer * @param val If stack has elements, a copy of the top element will be stored * in *val * * @returns Return codes: * CDADA_SUCCESS: top element is retrieved * CDADA_E_EMPTY: stack is empty * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_top(const cdada_stack_t* stack, void *val); //Dumpers /** * Dump to a string the contents of the stack * * @param stack Stack object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be stack * in 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: stack was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_dump(cdada_stack_t* stack, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the stack * * @param stack Stack object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: stack was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted stack or internal error (bug) * CDADA_E_INVALID: stack is NULL or corrupted */ int cdada_stack_print(cdada_stack_t* stack, FILE *stream); //Custom types /** * Forward declare custom time ops */ #define CDADA_STACK_CUSTOM_TYPE_DECL(TYPE) \ extern struct __cdada_stack_ops __cdada_stack_autogen_##TYPE /** * @brief Create a stack with a custom type, with a dedicated std::stack * * Requires instantiating CDADA_STACK_CUSTOM_GEN() or * CDADA_STACK_CUSTOM_GEN_NO_MEMCP() once in a C++ compilation unit */ #define cdada_stack_create_custom(TYPE) \ __cdada_stack_create(sizeof( TYPE ), & __cdada_stack_autogen_##TYPE ) CDADA_END_DECLS #endif //__CDADA_STACK_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/list.h0000644000175000017500000002741514354105336022771 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_LIST_H__ #define __CDADA_LIST_H__ #include #include #include #include /** * @file cdada/list.h * @author Marc Sune * * @brief List data structure * * `cdada_list` data structure is an ordered list of elements of type 'TYPE'. * During insertions, a _copy_ of the element `val` will be stored in the list. * During accesses (e.g. `cdada_list_first`), if found, a _copy_ of the value * will be stored in the region of memory pointed by `val`. * * Uses std::list as a backend */ /** * cdada list structure */ typedef void cdada_list_t; //In case it's included from C++ CDADA_BEGIN_DECLS //Fwd decl //See cdada_list_create() for return codes struct __cdada_list_ops; cdada_list_t* __cdada_list_create(const uint16_t val_size, struct __cdada_list_ops* ops); /** * cdada list structure iterator * * @param list List ptr * @param val Val (immutable) * @param opaque A pointer to an opaque object tat will be passed to the callback */ typedef void (*cdada_list_it)(const cdada_list_t* list, const void* val, void* opaque); /** * @brief Create and initialize a list data structure * * Allocate and initialize a list structure. Containers will perform better when * TYPE has a size of {1,2,4,8,16,32,64,128,256} bytes * * For types > 256, use custom containers * * @param TYPE A typename (not a function parameter) * * @returns Returns a cdada_list object or NULL, if some error is found */ #define cdada_list_create(TYPE) \ __cdada_list_create(sizeof( TYPE ), NULL) /** * Destroy a list structure * * @returns Return codes: * CDADA_SUCCESS: list is destroyed * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_destroy(cdada_list_t* list); /** * Clear the contents of the list * * @returns Return codes: * CDADA_SUCCESS: list is cleared * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_clear(cdada_list_t* list); /** * Traverse list * * @param list List * @param func Traverse function for this specific list * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: list was successfully traversed * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_traverse(const cdada_list_t* list, cdada_list_it func, void* opaque); /** * Reverse traverse list * * @param list List * @param func Traverse function for this specific list * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: list was successfully reverse traversed * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_rtraverse(const cdada_list_t* list, cdada_list_it func, void* opaque); //List properties /** * Is the list empty * * @returns Returns true if list is empty else (including invalid) false */ bool cdada_list_empty(const cdada_list_t* list); /** * Return the size (number of elements) in the list * * @returns Returns number of elements. If list is NULL or corrupted, returns 0 */ uint32_t cdada_list_size(const cdada_list_t* list); //Element manipulation /** * Insert an element (a copy) in the list * * @param list List pointer * @param val Value * @param pos Position in the list * * @returns Return codes: * CDADA_SUCCESS: element is inserted * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_insert(cdada_list_t* list, const void* val, const uint32_t pos); /** * Get an element at a position * * @param list List pointer * @param pos Position in the list * @param val If an element in the position `pos` (starting from 0) exists, * a copy of the element will be stored in *val * * @returns Return codes: * CDADA_SUCCESS: element was retrieved * CDADA_E_NOT_FOUND: no element at position `pos` * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_get(const cdada_list_t* list, const uint32_t pos, void* val); /** * Get the first element (a copy) in the list * @param list Map pointer * @param val When the list has elements, a copy of the first element will * be stored in *val * * @returns Return codes: * CDADA_SUCCESS: first element was retrieved * CDADA_E_EMPTY: list has no elements * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_first(const cdada_list_t* list, void* val); /** * Get the last element (a copy) in the list * @param list Map pointer * @param val When the list has elements, a copy of the last element will * be stored in *val * * @returns Return codes: * CDADA_SUCCESS: last element was retrieved * CDADA_E_EMPTY: list has no elements * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_last(const cdada_list_t* list, void* val); /** * Erase an element from the list in a specific position * * @param list List pointer * @param pos Position in the list * * @returns Return codes: * CDADA_SUCCESS: element at position `pos` was successfully erased * CDADA_E_NOT_FOUND: no element at position `pos` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_erase(cdada_list_t* list, uint32_t pos); /** * Remove elements with a specific value * * @param list List pointer * @param val Element * * @returns Return codes: * CDADA_SUCCESS: at least one element was successfully removed * CDADA_E_NOT_FOUND: no elements match `val` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_remove(cdada_list_t* list, const void* val); /** * Push front (a copy) * * @param list List pointer * @param val Element * * @returns Return codes: * CDADA_SUCCESS: element was successfully pushed to the front * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_push_front(cdada_list_t* list, const void* val); /** * Push back (a copy) * * @param list List pointer * @param val Element * * @returns Return codes: * CDADA_SUCCESS: element was successfully pushed to the back * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_push_back(cdada_list_t* list, const void* val); /** * Pop (remove) from the front of the list * * @param list List pointer * * @returns Return codes: * CDADA_SUCCESS: element was successfully popped from the front * CDADA_E_EMPTY: list is empty * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_pop_front(cdada_list_t* list); /** * Pop (remove) from the back of the list * * @param list List pointer * * @returns Return codes: * CDADA_SUCCESS: element was successfully popped from the back * CDADA_E_EMPTY: list is empty * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_pop_back(cdada_list_t* list); /** * Sort * * @param list List pointer * * @returns Return codes: * CDADA_SUCCESS: list was sorted * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_sort(cdada_list_t* list); /** * Reverse order of elements * * @param list List pointer * * @returns Return codes: * CDADA_SUCCESS: list was reversed * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_reverse(cdada_list_t* list); /** * Remove duplicate values * * @param list List pointer * * @returns Return codes: * CDADA_SUCCESS: list had duplicate elements successfully removed * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_unique(cdada_list_t* list); //Dumpers /** * Dump to a string the contents of the list * * @param list List object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be list in * 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: list was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_dump(cdada_list_t* list, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the list * * @param list List object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: list was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted list or internal error (bug) * CDADA_E_INVALID: list is NULL or corrupted */ int cdada_list_print(cdada_list_t* list, FILE *stream); //Custom types /** * Forward declare custom time ops */ #define CDADA_LIST_CUSTOM_TYPE_DECL(TYPE) \ extern struct __cdada_list_ops __cdada_list_autogen_##TYPE /** * @brief Create a list with a custom type, with a dedicated std::list * * Requires instantiating CDADA_LIST_CUSTOM_GEN() or * CDADA_LIST_CUSTOM_GEN_NO_MEMCP() once in a C++ compilation unit */ #define cdada_list_create_custom(TYPE) \ __cdada_list_create(sizeof( TYPE ), & __cdada_list_autogen_##TYPE ) CDADA_END_DECLS #endif //__CDADA_LIST_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/set.h0000644000175000017500000002026714354105336022607 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_SET_H__ #define __CDADA_SET_H__ #include #include #include #include /** * @file cdada/set.h * @author Marc Sune * * @brief Set data structure. * * `cdada_set` data structure is a collection of unique elements of type 'TYPE'. * During insertions, a _copy_ of the element `key` will be stored in the set. * During accesses (e.g. `cdada_set_first`), if found, a _copy_ of the value * will be stored in the region of memory pointed by `key`. * * Uses std::set as a backend */ /** * cdada set structure */ typedef void cdada_set_t; //In case it's included from C++ CDADA_BEGIN_DECLS //Fwd decl //See cdada_set_create() for return codes struct __cdada_set_ops; cdada_set_t* __cdada_set_create(const uint16_t key_size, struct __cdada_set_ops* ops); /** * cdada set structure iterator * * @param set Set ptr * @param key Key (immutable) * @param opaque A pointer to an opaque object tat will be passed to the callback */ typedef void (*cdada_set_it)(const cdada_set_t* set, const void* key, void* opaque); /** * @brief Create and initialize a set data structure * * Allocate and initialize a set structure. Containers will perform * better when TYPE has a size of {1,2,4,8,16,32,64,128,256} bytes * * For types > 256, use custom containers * * @returns Returns a cdada_set object or NULL, if some error is found */ #define cdada_set_create(TYPE) \ __cdada_set_create(sizeof( TYPE ), NULL) /** * Destroy a set structure * * @returns Return codes: * CDADA_SUCCESS: set is destroyed * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_destroy(cdada_set_t* set); /** * Clear the contents of the set * * @returns Return codes: * CDADA_SUCCESS: set is cleared * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_clear(cdada_set_t* set); /** * Traverse set * * @param set Set * @param func Traverse function for this specific set * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: set was successfully traversed * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_traverse(const cdada_set_t* set, cdada_set_it func, void* opaque); /** * Reverse traverse set * * @param set Set * @param func Traverse function for this specific set * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: set was successfully reverse traversed * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_rtraverse(const cdada_set_t* set, cdada_set_it func, void* opaque); //Set properties /** * Is the set empty * * @returns Returns true if set is empty else (including invalid) false */ bool cdada_set_empty(const cdada_set_t* set); /** * Return the size (number of elements) in the set * * @returns Returns number of elements. If set is NULL or corrupted, returns 0 */ uint32_t cdada_set_size(const cdada_set_t* set); //Element manipulation /** * Insert an element (a copy) in the set * * @param set Set pointer * @param key Key. The key type _must_ have all bytes initialized * * @returns Return codes: * CDADA_SUCCESS: element is inserted * CDADA_E_EXISTS: element exists * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_insert(cdada_set_t* set, const void* key); /** * Erase an element in the set * * @param set Set pointer * @param key Key. The key type _must_ have all bytes initialized * * @returns Return codes: * CDADA_SUCCESS: element was successfully erased * CDADA_E_NOT_FOUND: no element `key` was found * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_erase(cdada_set_t* set, const void* key); /** * Find a key in the set * * @param set Set pointer * @param key Key to search * * @returns Returns true if set has element else (including invalid) false */ bool cdada_set_find(const cdada_set_t* set, const void* key); /** * Get the first element in the set * @param set Set pointer * @param key If set has elements, a copy of the first element will be stored * in *key * * @returns Return codes: * CDADA_SUCCESS: first element was retrieved * CDADA_E_EMPTY: set has no elements * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_first(const cdada_set_t* set, void* key); /** * Get the last element in the set * @param set Set pointer * @param key If set has elements, a copy of the last element will be stored * in *key * * @returns Return codes: * CDADA_SUCCESS: last element was retrieved * CDADA_E_EMPTY: set has no elements * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_last(const cdada_set_t* set, void* key); //Dumpers /** * Dump to a string the contents of the set * * @param set Set object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be set in * 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: set was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_dump(cdada_set_t* set, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the set * * @param set Set object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: set was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted set or internal error (bug) * CDADA_E_INVALID: set is NULL or corrupted */ int cdada_set_print(cdada_set_t* set, FILE *stream); //Custom types /** * Forward declare custom time ops */ #define CDADA_SET_CUSTOM_TYPE_DECL(TYPE) \ extern struct __cdada_set_ops __cdada_set_autogen_##TYPE /** * @brief Create a set with a custom type, with a dedicated std::set * * Requires instantiating CDADA_SET_CUSTOM_GEN() or * CDADA_SET_CUSTOM_GEN_NO_MEMCP() once in a C++ compilation unit */ #define cdada_set_create_custom(TYPE) \ __cdada_set_create(sizeof( TYPE ), & __cdada_set_autogen_##TYPE ) CDADA_END_DECLS #endif //__CDADA_SET_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/utils.h0000644000175000017500000000414114354105336023145 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_UTILS_H__ #define __CDADA_UTILS_H__ /** * @file cdada_utils.h * @author Marc Sune * * @brief Several misc. utilities */ //Eror codes #define CDADA_SUCCESS 0 #define CDADA_E_UNKNOWN 1 #define CDADA_E_INVALID 2 #define CDADA_E_NOT_FOUND 3 #define CDADA_E_EXISTS 4 #define CDADA_E_MEM 5 #define CDADA_E_UNSUPPORTED 6 #define CDADA_E_EMPTY 7 #define CDADA_E_INCOMPLETE 8 #define CDADA_E_FULL 9 #define CDADA_E_COUNT 10 #ifdef __cplusplus # define CDADA_BEGIN_DECLS extern "C" { # define CDADA_END_DECLS } #else # define CDADA_BEGIN_DECLS # define CDADA_END_DECLS #endif //__cplusplus CDADA_BEGIN_DECLS /** * Get a human-readable description for CDADA errors */ const char* cdada_strerr(int error); CDADA_END_DECLS #endif //__CDADA_UTILS_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__common_internal.h0000644000175000017500000001657114354105336025501 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_COMMON_INT__ #define __CDADA_COMMON_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include "cdada/utils.h" #include #include #include #include /** * @file cdada/common_int.h * @author Marc Sune * * @brief Common MACROs and utility functions */ //Magic num #define CDADA_MAGIC 0xCAFEBABE //Branch prediction #if defined(__GNUC__) || defined(__INTEL_COMPILER) #ifndef likely #define likely(x) __builtin_expect(((x)),1) #endif #ifndef unlikely #define unlikely(x) __builtin_expect(((x)),0) #endif #else #ifndef likely #define likely(x) x #endif #ifndef unlikely #define unlikely(x) x #endif #endif //GCC, ICC #define CDADA_ASSERT(COND) assert(COND) //Necessary types for key len rounding typedef struct{ uint64_t a[2]; } __attribute__((packed)) cdada_u128_t; typedef struct{ uint64_t a[4]; } __attribute__((packed)) cdada_u256_t; typedef struct{ uint64_t a[8]; } __attribute__((packed)) cdada_u512_t; typedef struct{ uint64_t a[16]; } __attribute__((packed)) cdada_u1024_t; typedef struct{ uint64_t a[32]; } __attribute__((packed)) cdada_u2048_t; #define CDADA_CHECK_MAGIC(MM) \ if(unlikely(!(MM) || (MM)->magic_num != CDADA_MAGIC)) \ return CDADA_E_INVALID //Comparing methods for extended types inline bool operator<(const cdada_u128_t& a1, const cdada_u128_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u128_t)) < 0; } inline bool operator<(const cdada_u256_t& a1, const cdada_u256_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u256_t)) < 0; } inline bool operator<(const cdada_u512_t& a1, const cdada_u512_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u512_t)) < 0; } inline bool operator<(const cdada_u1024_t& a1, const cdada_u1024_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u1024_t)) < 0; } inline bool operator<(const cdada_u2048_t& a1, const cdada_u2048_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u2048_t)) < 0; } //Comparing methods for extended types (std::list::unique) inline bool operator==(const cdada_u128_t& a1, const cdada_u128_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u128_t)) == 0; } inline bool operator==(const cdada_u256_t& a1, const cdada_u256_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u256_t)) == 0; } inline bool operator==(const cdada_u512_t& a1, const cdada_u512_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u512_t)) == 0; } inline bool operator==(const cdada_u1024_t& a1, const cdada_u1024_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u1024_t)) == 0; } inline bool operator==(const cdada_u2048_t& a1, const cdada_u2048_t& a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof(cdada_u2048_t)) == 0; } //For dumpers //Generic (hexdump) template inline void __cdada_str_obj(std::stringstream& ss, const T& o, const uint32_t len){ uint8_t* __attribute__((__may_alias__)) p = (uint8_t*)&o; for(uint32_t i=0;i inline void __cdada_str_obj(std::stringstream& ss, const uint8_t& o, const uint32_t len){ ss << (uint16_t)o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const int8_t& o, const uint32_t len){ ss << (int16_t)o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const uint16_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const int16_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const uint32_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const int32_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const uint64_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const int64_t& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const float& o, const uint32_t len){ ss << o; } template <> inline void __cdada_str_obj(std::stringstream& ss, const double& o, const uint32_t len){ ss << o; } //Generators for custom types /** * @internal Default memcp comparison operator */ #define __CDADA_CUSTOM_GEN_MEMCP_LESS_OP(TYPE) \ inline bool operator<(const TYPE & a1, const TYPE & a2){ \ return memcmp((const void*)&a1, (const void*)&a2, \ sizeof( TYPE )) < 0; \ } /** * @internal Default memcp comparison operator */ #define __CDADA_CUSTOM_GEN_MEMCP_EQ_OP(TYPE) \ inline bool operator==(const TYPE & a1, const TYPE & a2){ \ return memcmp((const void*)&a1, (const void*)&a2, \ sizeof( TYPE )) == 0; \ } /** * @internal Default dumper operator */ #define __CDADA_CUSTOM_GEN_DUMP_OP(TYPE) \ inline std::ostream& operator<<(std::ostream& os, const TYPE & a){ \ uint8_t* __attribute__((__may_alias__)) p = (uint8_t*)&a; \ os << std::hex << std::setfill('0') << std::setw(2); \ for(uint32_t i=0;i #include #include #include #include #include /** * @file cdada/list_internal.h * @author Marc Sune * * @brief Internals of the list wrapper */ /** * @internal Function pointer struct for autogen types */ typedef struct __cdada_list_ops{ void (*create)(cdada_list_t* l); void (*destroy)(cdada_list_t* l); void (*clear)(cdada_list_t* l); bool (*empty)(const cdada_list_t* l); uint32_t (*size)(const cdada_list_t* l); int (*insert)(cdada_list_t* l, const void* val, const uint32_t pos); int (*get)(const cdada_list_t* l, const uint32_t pos, void* val); int (*first_last)(const cdada_list_t* l, bool first, void* val); int (*erase)(cdada_list_t* l, const uint32_t pos); int (*remove)(cdada_list_t* l, const void* val); int (*push)(cdada_list_t* l, const void* val, bool front); int (*pop)(cdada_list_t* l, bool front); void (*sort)(cdada_list_t* l); void (*reverse)(cdada_list_t* l); void (*unique)(cdada_list_t* l); void (*traverse)(const cdada_list_t* l, cdada_list_it f, void* opaque); void (*rtraverse)(const cdada_list_t* l, cdada_list_it f, void* opaque); void (*dump)(const cdada_list_t* m, std::stringstream& ss); }__cdada_list_ops_t; /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; uint32_t user_val_len; uint32_t val_len; union { std::list* u8; std::list* u16; std::list* u32; std::list* u64; std::list* u128; std::list* u256; std::list* u512; std::list* u1024; std::list* u2048; void* custom; }list; __cdada_list_ops_t* ops; }__cdada_list_int_t; template int cdada_list_insert_u(__cdada_list_int_t* m, std::list* m_u, const void* val, const uint32_t pos){ int i = pos; typename std::list::iterator it; it = m_u->begin(); for(it = m_u->begin(); i>0; --i){ if(++it == m_u->end()) break; } if(m->val_len == m->user_val_len){ T* __attribute((__may_alias__)) aux; aux = (T*)val; m_u->insert(it, *aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, val, m->user_val_len); m_u->insert(it, aux); return CDADA_SUCCESS; } template int cdada_list_get_u(const __cdada_list_int_t* m, std::list* m_u, const uint32_t pos, void* val){ int i = pos; typename std::list::iterator it; T* __attribute((__may_alias__)) aux = (T*)val; it = m_u->begin(); for(it = m_u->begin(); i>0; --i){ if(++it == m_u->end()) return CDADA_E_NOT_FOUND; } if(m->val_len == m->user_val_len){ *aux = *it; return CDADA_SUCCESS; } //Avoid padding from the wrapper memcpy(aux, &(*it), m->user_val_len); return CDADA_SUCCESS; } template int cdada_list_first_last_u(const __cdada_list_int_t* m, std::list* m_u, bool first, void* key){ T* __attribute((__may_alias__)) aux; aux = (T*)key; if(first){ typename std::list::const_iterator it; it = m_u->begin(); if(it == m_u->end()) return CDADA_E_EMPTY; if(m->val_len == m->user_val_len) *aux = *it; else memcpy(aux, &(*it), m->user_val_len); }else{ typename std::list::const_reverse_iterator rit; rit = m_u->rbegin(); if(rit == m_u->rend()) return CDADA_E_EMPTY; if(m->val_len == m->user_val_len) *aux = *rit; else memcpy(aux, &(*rit), m->user_val_len); } return CDADA_SUCCESS; } template int cdada_list_erase_u(__cdada_list_int_t* m, std::list* m_u, const uint32_t pos){ int i = pos; typename std::list::iterator it; it = m_u->begin(); for(it = m_u->begin(); i>0; --i){ if(++it == m_u->end()) return CDADA_E_NOT_FOUND; } if(it == m_u->end()) return CDADA_E_NOT_FOUND; m_u->erase(it); return CDADA_SUCCESS; } template int cdada_list_remove_u(__cdada_list_int_t* m, std::list* m_u, const void* val){ if(m->val_len == m->user_val_len){ T* __attribute((__may_alias__)) aux; aux = (T*)val; m_u->remove(*aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, val, m->user_val_len); m_u->remove(aux); return CDADA_SUCCESS; } template int cdada_list_push_u(__cdada_list_int_t* m, std::list* m_u, const void* val, bool front){ if(m->val_len == m->user_val_len){ T* __attribute((__may_alias__)) aux; aux = (T*)val; if(front) m_u->push_front(*aux); else m_u->push_back(*aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, val, m->user_val_len); if(front) m_u->push_front(aux); else m_u->push_back(aux); return CDADA_SUCCESS; } template int cdada_list_pop_u(__cdada_list_int_t* m, std::list* m_u, bool front){ if(m_u->size() == 0) return CDADA_E_EMPTY; if(front) m_u->pop_front(); else m_u->pop_back(); return CDADA_SUCCESS; } template void cdada_list_traverse_u(const cdada_list_t* list, std::list* m_u, cdada_list_it f, void* opaque){ typename std::list::const_iterator it; for(it = m_u->begin(); it != m_u->end(); ++it){ const T& t = *it; (*f)(list, &t, opaque); } } template void cdada_list_rtraverse_u(const cdada_list_t* list, std::list* m_u, cdada_list_it f, void* opaque){ typename std::list::const_reverse_iterator it; for(it = m_u->rbegin(); it != m_u->rend(); ++it){ const T& t = *it; (*f)(list, &t, opaque); } } template void cdada_list_dump_u(const __cdada_list_int_t* list, std::list* m_u, std::stringstream& ss){ uint32_t i; typename std::list::const_iterator it; for(it = m_u->begin(), i=0; it != m_u->end(); ++i){ ss << "[" << i <<"]:"; __cdada_str_obj(ss, *it, list->user_val_len); ++it; if(it != m_u->end()) ss << ", "; } } #endif //__CDADA_LIST_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__str_internal.h0000644000175000017500000000406414354105336025013 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_STR_INT__ #define __CDADA_STR_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include /** * @file cdada/str_internal.h * @author Marc Sune * * @brief Internals of the str wrapper */ /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; std::string* str; }__cdada_str_int_t; #endif //__CDADA_STR_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__map_internal.h0000644000175000017500000001574314354105336024766 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_MAP_INT__ #define __CDADA_MAP_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include /** * @file map_internal.h * @author Marc Sune * * @brief Internals of the map wrapper */ /** * @internal Function pointer struct for autogen types */ typedef struct __cdada_map_ops{ void (*create)(cdada_map_t* map); void (*destroy)(cdada_map_t* map); void (*clear)(cdada_map_t* map); bool (*empty)(const cdada_map_t* map); uint32_t (*size)(const cdada_map_t* map); int (*insert)(cdada_map_t* map, const void* key, void* val, const bool replace); int (*erase)(cdada_map_t* map, const void* key); int (*find)(const cdada_map_t* map, const void* key, void** val); int (*first_last)(const cdada_map_t* map, bool first, void* key, void** val); void (*traverse)(const cdada_map_t* map, cdada_map_it f, void* opaque); void (*rtraverse)(const cdada_map_t* map, cdada_map_it f, void* opaque); void (*dump)(const cdada_map_t* m, std::stringstream& ss); }__cdada_map_ops_t; /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; uint32_t user_key_len; uint32_t key_len; union { std::map* u8; std::map* u16; std::map* u32; std::map* u64; std::map* u128; std::map* u256; std::map* u512; std::map* u1024; std::map* u2048; void* custom; }map; __cdada_map_ops_t* ops; }__cdada_map_int_t; template int cdada_map_insert_u(__cdada_map_int_t* m, std::map* m_u, const void* key, void* val, const bool replace){ typename std::map::iterator it; if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; it = m_u->find(*aux); if(!replace && unlikely(it != m_u->end())) return CDADA_E_EXISTS; (*m_u)[*aux] = val; return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); it = m_u->find(aux); if(!replace && unlikely(it != m_u->end())) return CDADA_E_EXISTS; (*m_u)[aux] = val; return CDADA_SUCCESS; } template int cdada_map_erase_u(__cdada_map_int_t* m, std::map* m_u, const void* key){ typename std::map::iterator it; if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; it = m_u->find(*aux); if(unlikely(it == m_u->end())) return CDADA_E_NOT_FOUND; m_u->erase(*aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); it = m_u->find(aux); if(unlikely(it == m_u->end())) return CDADA_E_NOT_FOUND; m_u->erase(aux); return CDADA_SUCCESS; } template int cdada_map_find_u(const __cdada_map_int_t* m, std::map* m_u, const void* key, void** val){ typename std::map::const_iterator it; if(m->key_len == m->user_key_len){ T* __attribute((__may_alias__)) aux; aux = (T*)key; it = m_u->find(*aux); if(unlikely(it == m_u->end())) return CDADA_E_NOT_FOUND; *val = it->second; return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, key, m->user_key_len); it = m_u->find(aux); if(unlikely(it == m_u->end())) return CDADA_E_NOT_FOUND; *val = it->second; return CDADA_SUCCESS; } template int cdada_map_first_last_u(const __cdada_map_int_t* m, std::map* m_u, bool first, void* key, void** val){ T* __attribute((__may_alias__)) aux; aux = (T*)key; if(first){ typename std::map::const_iterator it; it = m_u->begin(); if(it == m_u->end()) return CDADA_E_EMPTY; if(m->key_len == m->user_key_len) *aux = it->first; else memcpy(aux, &it->first, m->user_key_len); *val = it->second; }else{ typename std::map::const_reverse_iterator rit; rit = m_u->rbegin(); if(rit == m_u->rend()) return CDADA_E_EMPTY; if(m->key_len == m->user_key_len) *aux = rit->first; else memcpy(aux, &rit->first, m->user_key_len); *val = rit->second; } return CDADA_SUCCESS; } template void cdada_map_traverse_u(const cdada_map_t* map, std::map* m_u, cdada_map_it f, void* opaque){ typename std::map::const_iterator it; for(it = m_u->begin(); it != m_u->end(); ++it) (*f)(map, &it->first, it->second, opaque); } template void cdada_map_rtraverse_u(const cdada_map_t* map, std::map* m_u, cdada_map_it f, void* opaque){ typename std::map::const_reverse_iterator it; for(it = m_u->rbegin(); it != m_u->rend(); ++it) (*f)(map, &it->first, it->second, opaque); } template void cdada_map_dump_u(const __cdada_map_int_t* map, std::map* m_u, std::stringstream& ss){ typename std::map::const_iterator it; for(it = m_u->begin(); it != m_u->end();){ __cdada_str_obj(ss, it->first, map->user_key_len); ss << " -> @" << it->second; ++it; if(it != m_u->end()) ss << ", "; } } #endif //__CDADA_MAP_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/version.h.in0000644000175000017500000000414114354105336024077 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_VERSION_H__ #define __CDADA_VERSION_H__ #define CDADA_VERSION_MAJOR "@CDADA_VERSION_MAJOR@" #define CDADA_VERSION_MINOR "@CDADA_VERSION_MINOR@" #define CDADA_VERSION_PATCH "@CDADA_VERSION_PATCH@" #define CDADA_VERSION "@CDADA_VERSION_NORMALIZED@" #define CDADA_BUILD "@CDADA_BUILD@" /** * @brief Return libcdada's version * * The version has the format vX.Y.Z, where: * * X: major * Y: minor * Z: patch */ const char* cdada_get_ver(); /** * Return the MAJOR number of libcdada's version */ const char* cdada_get_ver_maj(); /** * Return the MINOR number of libcdada's version */ const char* cdada_get_ver_min(); /** * Return the PATCH number of libcdada's version */ const char* cdada_get_ver_patch(); /** * @brief Return libcdada's build (git hash) */ const char* cdada_get_build(); #endif /* __CDADA_VERSION_H__ */ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/stack_custom_cc.h0000644000175000017500000001275614354105336025164 0ustar paolopaolo/* Copyright (c) 2020, Peter Dobransky All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_STACK_CUSTOM_CC_H__ #define __CDADA_STACK_CUSTOM_CC_H__ //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #define __CDADA_INTERNAL_INCLUDE #include #include #include #include #include #include /** * @file cdada/stack_custom_cc.h * @author Peter Dobransky * * @brief This file needs to be included in a C++ file to autogenerate the * code necessary to use a custom type as a val/value for cdada structs. */ #define __CDADA_STD_STACK_TYPE(T) std::stack< T > /** * @internal Custom type create f */ #define __CDADA_STACK_CUSTOM_CREATE_F(TYPE) \ void __cdada_stack_autogen_create_##TYPE (void* m){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ s->stack.custom = (void*)new __CDADA_STD_STACK_TYPE(TYPE)(); \ } /** * @internal Custom type destroy f */ #define __CDADA_STACK_CUSTOM_DESTROY_F(TYPE) \ void __cdada_stack_autogen_destroy_##TYPE (void* m){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ delete p; \ } /** * @internal Custom type empty f */ #define __CDADA_STACK_CUSTOM_EMPTY_F(TYPE) \ bool __cdada_stack_autogen_empty_##TYPE (const void* m){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ return p->empty(); \ } /** * @internal Custom type size f */ #define __CDADA_STACK_CUSTOM_SIZE_F(TYPE) \ uint32_t __cdada_stack_autogen_size_##TYPE (const void* m){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ return p->size(); \ } /** * @internal Custom type push f */ #define __CDADA_STACK_CUSTOM_PUSH_F(TYPE) \ int __cdada_stack_autogen_push_##TYPE (void* m, const void* val){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ return cdada_stack_push_u< TYPE > (s, p, val);\ } /** * @internal Custom type pop f */ #define __CDADA_STACK_CUSTOM_POP_F(TYPE) \ int __cdada_stack_autogen_pop_##TYPE (void* m){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ return cdada_stack_pop_u< TYPE > (s, p);\ } /** * @internal Custom type top f */ #define __CDADA_STACK_CUSTOM_TOP_F(TYPE) \ int __cdada_stack_autogen_top_##TYPE (const void* m, void* val){ \ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom; \ return cdada_stack_top_u< TYPE > (s, p, val);\ } /** * @internal Custom type dump f */ #define __CDADA_STACK_CUSTOM_DUMP_F(TYPE) \ void __cdada_stack_autogen_dump_##TYPE (const void* m, \ std::stringstream& ss){\ __cdada_stack_int_t* s = (__cdada_stack_int_t*)m; \ __CDADA_STD_STACK_TYPE(TYPE)* p = \ (__CDADA_STD_STACK_TYPE(TYPE)*)s->stack.custom;\ return cdada_stack_dump_u< TYPE > (s, p, ss);\ } /** * @internal Create ops func ptrs struct */ #define __CDADA_STACK_CUSTOM_OPS(TYPE) \ __cdada_stack_ops_t __cdada_stack_autogen_##TYPE = { \ __cdada_stack_autogen_create_##TYPE, \ __cdada_stack_autogen_destroy_##TYPE, \ __cdada_stack_autogen_empty_##TYPE, \ __cdada_stack_autogen_size_##TYPE, \ __cdada_stack_autogen_push_##TYPE, \ __cdada_stack_autogen_pop_##TYPE, \ __cdada_stack_autogen_top_##TYPE, \ __cdada_stack_autogen_dump_##TYPE, \ } /** * Auto-generate (instantiate) new custom type stack, with TYPE */ #define CDADA_STACK_CUSTOM_GEN(TYPE) \ __CDADA_STACK_CUSTOM_CREATE_F(TYPE); \ __CDADA_STACK_CUSTOM_DESTROY_F(TYPE); \ __CDADA_STACK_CUSTOM_EMPTY_F(TYPE); \ __CDADA_STACK_CUSTOM_SIZE_F(TYPE); \ __CDADA_STACK_CUSTOM_PUSH_F(TYPE); \ __CDADA_STACK_CUSTOM_POP_F(TYPE); \ __CDADA_STACK_CUSTOM_TOP_F(TYPE); \ __CDADA_STACK_CUSTOM_DUMP_F(TYPE); \ __CDADA_STACK_CUSTOM_OPS(TYPE) #undef __CDADA_INTERNAL_INCLUDE #endif //__CDADA_STACK_CUSTOM_CC_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/queue.h0000644000175000017500000001733214354105336023137 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_QUEUE_H__ #define __CDADA_QUEUE_H__ #include #include #include #include /** * @file cdada/queue.h * @author Marc Sune * * @brief Queue(FIFO) data structure. * * `cdada_queue` data structure is a queue(FIFO) of elements of type 'TYPE'. * During insertions, a _copy_ of the element `val` will be stored in the queue. * During accesses (e.g. `cdada_queue_front`), if found, a _copy_ of the value * will be stored in the region of memory pointed by `val`. * * Uses std::queue as a backend */ /** * cdada queue structure */ typedef void cdada_queue_t; //In case it's included from C++ CDADA_BEGIN_DECLS //Fwd decl //See cdada_queue_create() for return codes struct __cdada_queue_ops; cdada_queue_t* __cdada_queue_create(const uint16_t val_size, struct __cdada_queue_ops* ops); /** * @brief Create and initialize a queue(FIFO) data structure * * Allocate and initialize a queue structure. Containers will perform better when * TYPE has a size of {1,2,4,8,16,32,64,128,256} bytes * * For types > 256, use custom containers * * @returns Returns a cdada_queue object or NULL, if some error is found */ #define cdada_queue_create(TYPE) \ __cdada_queue_create(sizeof( TYPE ), NULL) /** * Destroy a queue structure * * @param queue Queue pointer * * @returns Return codes: * CDADA_SUCCESS: queue was destroyed * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_destroy(cdada_queue_t* queue); //Queue properties /** * Is the queue empty * * @param queue Queue pointer * * @returns Returns true if queue is empty else (including invalid) false */ bool cdada_queue_empty(const cdada_queue_t* queue); /** * Return the size (number of elements) in the queue * * @param queue Queue pointer * * @returns Returns number of elements. If queue is NULL or corrupted, returns 0 */ uint32_t cdada_queue_size(const cdada_queue_t* queue); /** * Get the maximum capacity (0 if unlimited) * * @param queue Queue pointer * * @returns Will return the maximum capacity of the queue or 0 if unlimited */ uint64_t cdada_queue_get_max_capacity(const cdada_queue_t* queue); /** * @brief Set the maximum capacity * * This function sets the maximum capacity of the queue. It can be called * at any time. If called when the queue has more elements than `limit`, * exceeding elements won't be removed, but the queue won't be able to * grow until the size is under the new set limit. * * Use the value 0 to remove the limit * * @param queue Queue pointer * @param limit Limit of the capacity (set to 0 for unlimited) * * @returns Return codes: * CDADA_SUCCESS: max capacity was successfully set * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_set_max_capacity(const cdada_queue_t* queue, const uint64_t limit); //Element manipulation /** * Push an element (a copy) at the end of the queue * * @param queue Queue pointer * @param val Element to add * * @returns Return codes: * CDADA_SUCCESS: element is pushed * CDADA_E_FULL: queue is full * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_push(cdada_queue_t* queue, const void* val); /** * Remove an element from the front of the queue (oldest) * * @param queue Queue pointer * * @returns Return codes: * CDADA_SUCCESS: element is popped * CDADA_E_EMPTY: queue is empty * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_pop(cdada_queue_t* queue); /** * Get the first element (a copy) in the queue. * * @param queue Queue pointer * @param val When the queue has elements, a copy of the front element will * be stored in *val * * @returns Return codes: * CDADA_SUCCESS: front element is retrieved * CDADA_E_EMPTY: queue has no elements * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_front(const cdada_queue_t* queue, void *val); /** * Get the last element (a copy) in the queue. * * @param queue Queue pointer * @param val When the queue has elements, a copy of the back element will * be stored in *val * * @returns Return codes: * CDADA_SUCCESS: back element is retrieved * CDADA_E_EMPTY: queue has no elements * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_back(const cdada_queue_t* queue, void *val); //Dumpers /** * Dump to a string the contents of the queue * * @param queue Queue object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be queue * in 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: queue was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_dump(cdada_queue_t* queue, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the queue * * @param queue Queue object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: queue was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted queue or internal error (bug) * CDADA_E_INVALID: queue is NULL or corrupted */ int cdada_queue_print(cdada_queue_t* queue, FILE *stream); //Custom types /** * Forward declare custom time ops */ #define CDADA_QUEUE_CUSTOM_TYPE_DECL(TYPE) \ extern struct __cdada_queue_ops __cdada_queue_autogen_##TYPE /** * @brief Create a queue with a custom type, with a dedicated std::queue * * Requires instantiating CDADA_QUEUE_CUSTOM_GEN() or * CDADA_QUEUE_CUSTOM_GEN_NO_MEMCP() once in a C++ compilation unit */ #define cdada_queue_create_custom(TYPE) \ __cdada_queue_create(sizeof( TYPE ), & __cdada_queue_autogen_##TYPE ) CDADA_END_DECLS #endif //__CDADA_QUEUE_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/str.h0000644000175000017500000002721014354105336022617 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_STRING_H__ #define __CDADA_STRING_H__ #include #include #include /** * @file cdada/str.h * @author Marc Sune * * @brief String data structure * * Uses std::string as a backend */ /** * cdada str structure */ typedef void cdada_str_t; CDADA_BEGIN_DECLS /** * cdada str structure iterator * * @param str String ptr * @param key Key (immutable) * @param opaque A pointer to an opaque object tat will be passed to the callback */ typedef void (*cdada_str_it)(const cdada_str_t* str, const char it, uint32_t pos, void* opaque); /** * Create a string data structure (in heap) * * @returns Returns a cdada_string object or NULL, if some error is found */ cdada_str_t* cdada_str_create(const char* str); /** * Destroy a str structure * * @returns Return codes: * CDADA_SUCCESS: string is destroyed * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_destroy(cdada_str_t* str); /** * Traverse string, char by char * * @param str String * @param func Traverse function for this specific str * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: string was successfully traversed * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_traverse(const cdada_str_t* str, cdada_str_it func, void* opaque); /** * Reverse traverse str, char by char * * @param str String * @param func Traverse function for this specific str * @param opaque User data (opaque ptr) * * @returns Return codes: * CDADA_SUCCESS: string was successfully reverse traversed * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_rtraverse(const cdada_str_t* str, cdada_str_it func, void* opaque); //String properties /** * Is the str empty string ("") * * @returns Returns true if string is empty("") else (including invalid) false */ bool cdada_str_empty(const cdada_str_t* str); /** * Return the length, excluding '\0' * * @returns Returns length. If string is NULL or corrupted, returns 0 */ uint32_t cdada_str_length(const cdada_str_t* str); //Access /** * Get the C string * * @param str String pointer * * @returns Returns C string. If string is NULL or corrupted, returns NULL */ const char* cdada_str(const cdada_str_t* str); /** * Find the first positon of the substring * * @param str String pointer * @param substr Substring to match * @param pos Position where to substring was found * * @returns Return codes: * CDADA_SUCCESS: substring was found * CDADA_E_NOT_FOUND: substring not found * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, substr, pos is NULL */ int cdada_str_find_first(const cdada_str_t* str, const char* substr, uint32_t* pos); /** * Find the last positon of the substring * * @param str String pointer * @param substr Substring to match * @param pos Position where to substring was found * * @returns Return codes: * CDADA_SUCCESS: substring was found * CDADA_E_NOT_FOUND: substring not found * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, substr or n are NULL */ int cdada_str_find_last(const cdada_str_t* str, const char* substr, uint32_t* pos); /** * Get the number of times a substring is found in the str * * @param str String pointer * @param substr Substring to match * @param n Number of occurrences * * @returns Return codes: * CDADA_SUCCESS: substring was found * CDADA_E_NOT_FOUND: substring not found * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, substr or n are NULL */ int cdada_str_find_count(const cdada_str_t* str, const char* substr, uint32_t* n); /** * @brief Find all occurrences of substring * * This function will return all the occurences of a substring in the str * * If the number of occurrances > pos_len, the function will return E_INCOMPLETE * * @param str String pointer * @param substr Substring to match * @param size Size of the array of occurences * @param poss Array of positions * @param cnt Number of find() occurrences * * @returns Return codes: * CDADA_SUCCESS: substring was found * CDADA_E_NOT_FOUND: substring not found * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, substr, size=0, poss or * or cnt are NULL */ int cdada_str_find_all(const cdada_str_t* str, const char* substr, const uint32_t size, uint32_t* poss, uint32_t* cnt); /** * Get the first char in the str * @param str String pointer * @param c char * * @returns Return codes: * CDADA_SUCCESS: got first char * CDADA_E_EMPTY: string is empty * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, c is NULL */ int cdada_str_first_c(const cdada_str_t* str, char* c); /** * Get the a char in the str * @param str String pointer * @param pos Position of the char * @param c char * * @returns Return codes: * CDADA_SUCCESS: got char * CDADA_E_EMPTY: string is empty * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, c is NULL */ int cdada_str_get_c(const cdada_str_t* str, const uint32_t pos, char* c); /** * Get the last char in the str * @param str String pointer * @param c char * * @returns Return codes: * CDADA_SUCCESS: got last char * CDADA_E_EMPTY: string is empty * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, c is NULL */ int cdada_str_last_c(const cdada_str_t* str, char* c); //Manipulation /** * Set or replace the contents of the string * * @returns Return codes: * CDADA_SUCCESS: string reset * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_set(cdada_str_t* str, const char* new_str); /** * Clears the contents of the str ("") * * @returns Return codes: * CDADA_SUCCESS: string is cleared * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ static inline int cdada_str_clear(cdada_str_t* str){ return cdada_str_set(str, ""); } /** * Append a substring at the end of the str * * @param str String pointer * @param substr Substring to insert * * @returns Return codes: * CDADA_SUCCESS: substr appended * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, substr is NULL */ int cdada_str_append(cdada_str_t* str, const char* substr); /** * Trim n characters from the end of the string * * @param str String pointer * @param n Number of characters * * @returns Return codes: * CDADA_SUCCESS: substr appended * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, n > length */ int cdada_str_trim(cdada_str_t* str, const uint32_t n); /** * Insert a substring in a specific position of the string * * @param str String pointer * @param pos Position where to inser the substring * @param substr Substring to insert * * @returns Return codes: * CDADA_SUCCESS: substr inserted * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, pos > length */ int cdada_str_insert(cdada_str_t* str, uint32_t pos, const char* substr); /** * Erase a substring starting at position [pos] element in the str * * @param str String pointer * @param pos Position where to insert the substring * @param substr_len Length of the substr * * @returns Return codes: * CDADA_SUCCESS: substr erased * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted, pos > length, * (pos+substr_len) > length */ int cdada_str_erase(cdada_str_t* str, const uint32_t pos, const uint32_t substr_len); /** * Convert string to all lower case * * @param str String pointer * * @returns Return codes: * CDADA_SUCCESS: string transformed to lower * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_lower(cdada_str_t* str); /** * Convert string to all upper case * * @param str String pointer * * @returns Return codes: * CDADA_SUCCESS: string transformed to upper * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_upper(cdada_str_t* str); /** * Replace all occurences of match with new_str * * @param str String pointer * @param match Match substring * @param new_str Substring to replace with * * @returns Return codes: * CDADA_SUCCESS: string replaced * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_replace_all(cdada_str_t* str, const char* match, const char* new_str); /** * Replace first occurence of match with new_str, starting at position pos * * @param str String pointer * @param match Match substring * @param new_str Substring to replace with * @param pos Start position * * @returns Return codes: * CDADA_SUCCESS: string replaced * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted string or internal error (bug) * CDADA_E_INVALID: string is NULL or corrupted */ int cdada_str_replace(cdada_str_t* str, const char* match, const char* new_str, const uint32_t pos); CDADA_END_DECLS #endif //__CDADA_STRING_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/bbitmap.h0000644000175000017500000001130514354105336023423 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redibbitmapibution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redibbitmapibutions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redibbitmapibutions 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 dibbitmapibution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_BBITMAP_H__ #define __CDADA_BBITMAP_H__ #include #include #include #include /** * @file cdada/bbitmap.h * @author Marc Sune * * @brief Big bitmap */ /** * cdada bbitmap structure */ typedef struct{ uint32_t magic_num; uint32_t n_words; uint64_t* ptr; }cdada_bbitmap_t; CDADA_BEGIN_DECLS /** * Create a big bitmap with n_bits number of bits, from bit 0...n_bits-1 * * @returns Returns a cdada_bbitmap object or NULL, if some error is found */ cdada_bbitmap_t* cdada_bbitmap_create(const uint32_t n_bits); /** * Destroy a big bitmap * * @returns Return codes: * CDADA_SUCCESS: bitmap is destroyed * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or corrupted */ int cdada_bbitmap_destroy(cdada_bbitmap_t* bitmap); /** * Set bit in big bitmap * * @returns Return codes: * CDADA_SUCCESS: bit is set * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or bit is beyond bounds */ int cdada_bbitmap_set(cdada_bbitmap_t* bitmap, const uint32_t bit); /** * Set all bits in big bitmap * * @returns Return codes: * CDADA_SUCCESS: all bits set * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or corrupted */ int cdada_bbitmap_set_all(cdada_bbitmap_t* bitmap); /** * Is bit set * * @returns Returns true if bit is set else (including invalid) false */ bool cdada_bbitmap_is_set(cdada_bbitmap_t* bitmap, const uint32_t bit); /** * Clear bit in big bitmap * * @returns Return codes: * CDADA_SUCCESS: bit is cleared * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or bit is beyond bounds */ int cdada_bbitmap_clear(cdada_bbitmap_t* bitmap, const uint32_t bit); /** * Clear all bits in big bitmap * * @returns Return codes: * CDADA_SUCCESS: all bits cleared * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or corrupted */ int cdada_bbitmap_clear_all(cdada_bbitmap_t* bitmap); //Dumpers /** * Dump to a string the contents of the bbitmap * * @param bitmap Bitmap object * @param size Size of the buffer * @param buffer Buffer. If NULL, necessary bytes, including '\0' will be set in * 'size_used' * @param size_used If buffer != NULL, the number of bytes written else number of * bytes necessary to write, including '\0' * * @returns Return codes: * CDADA_SUCCESS: bitmap was dumped to buffer * CDADA_E_INCOMPLETE: not enough room in buffer * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or corrupted */ int cdada_bbitmap_dump(cdada_bbitmap_t* bitmap, uint32_t size, char* buffer, uint32_t* bytes_used); /** * @brief Print the contents of the bbitmap * * @param bitmap Bitmap object * @param stream stdout or stderr * * @returns Return codes: * CDADA_SUCCESS: bitmap was dumped to `stream` * CDADA_E_MEM: out of memory * CDADA_E_UNKNOWN: corrupted bitmap or internal error (bug) * CDADA_E_INVALID: bitmap is NULL or corrupted */ int cdada_bbitmap_print(cdada_bbitmap_t* bitmap, FILE *stream); CDADA_END_DECLS #endif //__CDADA_BBITMAP_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/list_custom_cc.h0000644000175000017500000002323514354105336025024 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_LIST_CUSTOM_CC_H__ #define __CDADA_LIST_CUSTOM_CC_H__ //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #define __CDADA_INTERNAL_INCLUDE #include #include #include #include #include #include /** * @file cdada/list_custom_cc.h * @author Marc Sune * * @brief This file needs to be included in a C++ file to autogenerate the * code necessary to use a custom type as a val/value for cdada structs. */ #define __CDADA_STD_LIST_TYPE(T) std::list< T > /** * @internal Custom type create f */ #define __CDADA_LIST_CUSTOM_CREATE_F(TYPE) \ void __cdada_list_autogen_create_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ s->list.custom = (void*)new __CDADA_STD_LIST_TYPE(TYPE)(); \ } /** * @internal Custom type destroy f */ #define __CDADA_LIST_CUSTOM_DESTROY_F(TYPE) \ void __cdada_list_autogen_destroy_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ delete p; \ } /** * @internal Custom type clear f */ #define __CDADA_LIST_CUSTOM_CLEAR_F(TYPE) \ void __cdada_list_autogen_clear_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ p->clear(); \ } /** * @internal Custom type empty f */ #define __CDADA_LIST_CUSTOM_EMPTY_F(TYPE) \ bool __cdada_list_autogen_empty_##TYPE (const void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return p->empty(); \ } /** * @internal Custom type size f */ #define __CDADA_LIST_CUSTOM_SIZE_F(TYPE) \ uint32_t __cdada_list_autogen_size_##TYPE (const void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return p->size(); \ } /** * @internal Custom type insert f */ #define __CDADA_LIST_CUSTOM_INSERT_F(TYPE) \ int __cdada_list_autogen_insert_##TYPE (void* m, const void* val, \ const uint32_t pos){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_insert_u< TYPE > (s, p, val, pos);\ } /** * @internal Custom type get f */ #define __CDADA_LIST_CUSTOM_GET_F(TYPE) \ int __cdada_list_autogen_get_##TYPE (const void* m, const uint32_t pos,\ void* val){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_get_u< TYPE > (s, p, pos, val);\ } /** * @internal Custom type first_last f */ #define __CDADA_LIST_CUSTOM_FIRST_LAST_F(TYPE) \ int __cdada_list_autogen_first_last_##TYPE (const void* m, bool first, \ void* key){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_first_last_u< TYPE > (s, p, first, key);\ } /** * @internal Custom type erase f */ #define __CDADA_LIST_CUSTOM_ERASE_F(TYPE) \ int __cdada_list_autogen_erase_##TYPE (void* m, const uint32_t pos){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_erase_u< TYPE > (s, p, pos);\ } /** * @internal Custom type remove f */ #define __CDADA_LIST_CUSTOM_REMOVE_F(TYPE) \ int __cdada_list_autogen_remove_##TYPE (void* m, const void* val){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_remove_u< TYPE > (s, p, val);\ } /** * @internal Custom type push f */ #define __CDADA_LIST_CUSTOM_PUSH_F(TYPE) \ int __cdada_list_autogen_push_##TYPE (void* m, const void* val,\ bool front){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_push_u< TYPE > (s, p, val, front);\ } /** * @internal Custom type pop f */ #define __CDADA_LIST_CUSTOM_POP_F(TYPE) \ int __cdada_list_autogen_pop_##TYPE (void* m, bool front){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_pop_u< TYPE > (s, p, front);\ } /** * @internal Custom type sort f */ #define __CDADA_LIST_CUSTOM_SORT_F(TYPE) \ void __cdada_list_autogen_sort_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ p->sort(); \ } /** * @internal Custom type reverse f */ #define __CDADA_LIST_CUSTOM_REVERSE_F(TYPE) \ void __cdada_list_autogen_reverse_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ p->reverse(); \ } /** * @internal Custom type unique f */ #define __CDADA_LIST_CUSTOM_UNIQUE_F(TYPE) \ void __cdada_list_autogen_unique_##TYPE (void* m){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ p->unique(); \ } /** * @internal Custom type traverse f */ #define __CDADA_LIST_CUSTOM_TRAVERSE_F(TYPE) \ void __cdada_list_autogen_traverse_##TYPE (const void* m, \ cdada_list_it f, \ void* opaque){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_traverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type rtraverse f */ #define __CDADA_LIST_CUSTOM_RTRAVERSE_F(TYPE) \ void __cdada_list_autogen_rtraverse_##TYPE (const void* m, \ cdada_list_it f, \ void* opaque){ \ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_rtraverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type dump f */ #define __CDADA_LIST_CUSTOM_DUMP_F(TYPE) \ void __cdada_list_autogen_dump_##TYPE (const void* m, \ std::stringstream& ss){\ __cdada_list_int_t* s = (__cdada_list_int_t*)m; \ __CDADA_STD_LIST_TYPE(TYPE)* p = \ (__CDADA_STD_LIST_TYPE(TYPE)*)s->list.custom; \ return cdada_list_dump_u< TYPE > (s, p, ss);\ } /** * @internal Create ops func ptrs struct */ #define __CDADA_LIST_CUSTOM_OPS(TYPE) \ __cdada_list_ops_t __cdada_list_autogen_##TYPE = { \ __cdada_list_autogen_create_##TYPE, \ __cdada_list_autogen_destroy_##TYPE, \ __cdada_list_autogen_clear_##TYPE, \ __cdada_list_autogen_empty_##TYPE, \ __cdada_list_autogen_size_##TYPE, \ __cdada_list_autogen_insert_##TYPE, \ __cdada_list_autogen_get_##TYPE, \ __cdada_list_autogen_first_last_##TYPE, \ __cdada_list_autogen_erase_##TYPE, \ __cdada_list_autogen_remove_##TYPE, \ __cdada_list_autogen_push_##TYPE, \ __cdada_list_autogen_pop_##TYPE, \ __cdada_list_autogen_sort_##TYPE, \ __cdada_list_autogen_reverse_##TYPE, \ __cdada_list_autogen_unique_##TYPE, \ __cdada_list_autogen_traverse_##TYPE, \ __cdada_list_autogen_rtraverse_##TYPE, \ __cdada_list_autogen_dump_##TYPE, \ } /** * Auto-generate (instantiate) new custom type list, with TYPE */ #define CDADA_LIST_CUSTOM_GEN(TYPE) \ __CDADA_LIST_CUSTOM_CREATE_F(TYPE); \ __CDADA_LIST_CUSTOM_DESTROY_F(TYPE); \ __CDADA_LIST_CUSTOM_CLEAR_F(TYPE); \ __CDADA_LIST_CUSTOM_EMPTY_F(TYPE); \ __CDADA_LIST_CUSTOM_SIZE_F(TYPE); \ __CDADA_LIST_CUSTOM_INSERT_F(TYPE); \ __CDADA_LIST_CUSTOM_GET_F(TYPE); \ __CDADA_LIST_CUSTOM_FIRST_LAST_F(TYPE); \ __CDADA_LIST_CUSTOM_ERASE_F(TYPE); \ __CDADA_LIST_CUSTOM_REMOVE_F(TYPE); \ __CDADA_LIST_CUSTOM_PUSH_F(TYPE); \ __CDADA_LIST_CUSTOM_POP_F(TYPE); \ __CDADA_LIST_CUSTOM_SORT_F(TYPE); \ __CDADA_LIST_CUSTOM_REVERSE_F(TYPE); \ __CDADA_LIST_CUSTOM_UNIQUE_F(TYPE); \ __CDADA_LIST_CUSTOM_TRAVERSE_F(TYPE); \ __CDADA_LIST_CUSTOM_RTRAVERSE_F(TYPE); \ __CDADA_LIST_CUSTOM_DUMP_F(TYPE); \ __CDADA_LIST_CUSTOM_OPS(TYPE) #undef __CDADA_INTERNAL_INCLUDE #endif //__CDADA_LIST_CUSTOM_CC_H__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/__queue_internal.h0000644000175000017500000001171614354105336025331 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_QUEUE_INT__ #define __CDADA_QUEUE_INT__ //Internal headers should never be directly included #ifndef __CDADA_INTERNAL_INCLUDE #error CDADA internal headers shall not be directly included #endif //__CDADA_INTERNAL_INCLUDE //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #include #include #include #include #include /** * @file cdada/__queue_internal.h * @author Marc Sune * * @brief Internals of the queue wrapper */ /** * @internal Function pointer struct for autogen types */ typedef struct __cdada_queue_ops{ void (*create)(cdada_queue_t* s); void (*destroy)(cdada_queue_t* s); bool (*empty)(const cdada_queue_t* s); uint32_t (*size)(const cdada_queue_t* s); int (*push)(cdada_queue_t* s, const void* val); int (*pop)(cdada_queue_t* s); int (*front)(const cdada_queue_t* s, void *val); int (*back)(const cdada_queue_t* s, void *val); void (*dump)(const cdada_queue_t* m, std::stringstream& ss); }__cdada_queue_ops_t; /** * @internal Main internal structure */ typedef struct{ uint32_t magic_num; uint32_t user_val_len; uint32_t val_len; uint64_t max_capacity; union { std::queue* u8; std::queue* u16; std::queue* u32; std::queue* u64; std::queue* u128; std::queue* u256; std::queue* u512; std::queue* u1024; std::queue* u2048; void* custom; }queue; __cdada_queue_ops_t* ops; }__cdada_queue_int_t; template int cdada_queue_push_u(__cdada_queue_int_t* m, std::queue* m_u, const void* val){ if(m->val_len == m->user_val_len){ T* __attribute((__may_alias__)) aux; aux = (T*)val; m_u->push(*aux); return CDADA_SUCCESS; } //Note: at this point it can only be a struct //We have to pad the struct T aux; memset(&aux, 0, sizeof(T)); memcpy(&aux, val, m->user_val_len); m_u->push(aux); return CDADA_SUCCESS; } template int cdada_queue_pop_u(__cdada_queue_int_t* m, std::queue* m_u){ int rv = CDADA_E_EMPTY; if(!m_u->empty()){ m_u->pop(); rv = CDADA_SUCCESS; } return rv; } template int cdada_queue_front_u(__cdada_queue_int_t* m, std::queue* m_u, void *val){ T* __attribute((__may_alias__)) aux = (T*)val; int rv = CDADA_E_EMPTY; if(!m_u->empty()){ if(m->val_len == m->user_val_len){ *aux = m_u->front(); return CDADA_SUCCESS; } //Avoid padding from the wrapper aux = &(m_u->front()); memcpy(val, aux, m->user_val_len); return CDADA_SUCCESS; } return rv; } template int cdada_queue_back_u(__cdada_queue_int_t* m, std::queue* m_u, void *val){ T* __attribute((__may_alias__)) aux = (T*)val; int rv = CDADA_E_EMPTY; if(!m_u->empty()){ if(m->val_len == m->user_val_len){ *aux = m_u->back(); return CDADA_SUCCESS; } //Avoid padding from the wrapper aux = &(m_u->back()); memcpy(val, aux, m->user_val_len); return CDADA_SUCCESS; } return rv; } template bool cdada_queue_empty_u(__cdada_queue_int_t* m, std::queue* m_u){ return m_u->empty(); } template void cdada_queue_dump_u(const __cdada_queue_int_t* queue, std::queue* m_u, std::stringstream& ss){ typename std::queue aux; //No iterators in queue, ephemeral copy //TODO use extended queue class to avoid extra copy instead aux = *m_u; while(!aux.empty()){ T& t = aux.front(); __cdada_str_obj(ss, t, queue->user_val_len); aux.pop(); if(!aux.empty()) ss << ", "; } } #endif //__CDADA_QUEUE_INT__ pmacct-1.7.8/src/external_libs/libcdada/include/cdada/set_custom_cc.h0000644000175000017500000001615614354105336024650 0ustar paolopaolo/* Copyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __CDADA_SET_CUSTOM_CC_H__ #define __CDADA_SET_CUSTOM_CC_H__ //This header should _always_ be included from C++ #ifndef __cplusplus #error CDADA autogenreation headers shall be included only from C++ files #endif //__cplusplus #define __CDADA_INTERNAL_INCLUDE #include #include #include #include #include #include /** * @file cdada/set_custom_cc.h * @author Marc Sune * * @brief This file needs to be included in a C++ file to autogenerate the * code necessary to use a custom type as a key/value for cdada structs. */ #define __CDADA_STD_SET_TYPE(T) std::set< T > /** * @internal Custom type create f */ #define __CDADA_SET_CUSTOM_CREATE_F(TYPE) \ void __cdada_set_autogen_create_##TYPE (void* m){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ s->set.custom = (void*)new __CDADA_STD_SET_TYPE(TYPE)(); \ } /** * @internal Custom type destroy f */ #define __CDADA_SET_CUSTOM_DESTROY_F(TYPE) \ void __cdada_set_autogen_destroy_##TYPE (void* m){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ delete p; \ } /** * @internal Custom type clear f */ #define __CDADA_SET_CUSTOM_CLEAR_F(TYPE) \ void __cdada_set_autogen_clear_##TYPE (void* m){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ p->clear(); \ } /** * @internal Custom type empty f */ #define __CDADA_SET_CUSTOM_EMPTY_F(TYPE) \ bool __cdada_set_autogen_empty_##TYPE (const void* m){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return p->empty(); \ } /** * @internal Custom type size f */ #define __CDADA_SET_CUSTOM_SIZE_F(TYPE) \ uint32_t __cdada_set_autogen_size_##TYPE (const void* m){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return p->size(); \ } /** * @internal Custom type insert f */ #define __CDADA_SET_CUSTOM_INSERT_F(TYPE) \ int __cdada_set_autogen_insert_##TYPE (void* m, const void* key){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_insert_u< TYPE > (s, p, key);\ } /** * @internal Custom type erase f */ #define __CDADA_SET_CUSTOM_ERASE_F(TYPE) \ int __cdada_set_autogen_erase_##TYPE (void* m, const void* key){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_erase_u< TYPE > (s, p, key);\ } /** * @internal Custom type find f */ #define __CDADA_SET_CUSTOM_FIND_F(TYPE) \ bool __cdada_set_autogen_find_##TYPE (const void* m, const void* key){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_find_u< TYPE > (s, p, key);\ } /** * @internal Custom type first_last f */ #define __CDADA_SET_CUSTOM_FIRST_LAST_F(TYPE) \ int __cdada_set_autogen_first_last_##TYPE (const void* m, bool first, \ void* key){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_first_last_u< TYPE > (s, p, first, key);\ } /** * @internal Custom type traverse f */ #define __CDADA_SET_CUSTOM_TRAVERSE_F(TYPE) \ void __cdada_set_autogen_traverse_##TYPE (const void* m, \ cdada_set_it f, \ void* opaque){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_traverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type rtraverse f */ #define __CDADA_SET_CUSTOM_RTRAVERSE_F(TYPE) \ void __cdada_set_autogen_rtraverse_##TYPE (const void* m, \ cdada_set_it f, \ void* opaque){ \ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_rtraverse_u< TYPE > (s, p, f, opaque);\ } /** * @internal Custom type dump f */ #define __CDADA_SET_CUSTOM_DUMP_F(TYPE) \ void __cdada_set_autogen_dump_##TYPE (const void* m, \ std::stringstream& ss){\ __cdada_set_int_t* s = (__cdada_set_int_t*)m; \ __CDADA_STD_SET_TYPE(TYPE)* p = \ (__CDADA_STD_SET_TYPE(TYPE)*)s->set.custom; \ return cdada_set_dump_u< TYPE > (s, p, ss);\ } /** * @internal Create ops func ptrs struct */ #define __CDADA_SET_CUSTOM_OPS(TYPE) \ __cdada_set_ops_t __cdada_set_autogen_##TYPE = { \ __cdada_set_autogen_create_##TYPE, \ __cdada_set_autogen_destroy_##TYPE, \ __cdada_set_autogen_clear_##TYPE, \ __cdada_set_autogen_empty_##TYPE, \ __cdada_set_autogen_size_##TYPE, \ __cdada_set_autogen_insert_##TYPE, \ __cdada_set_autogen_erase_##TYPE, \ __cdada_set_autogen_find_##TYPE, \ __cdada_set_autogen_first_last_##TYPE, \ __cdada_set_autogen_traverse_##TYPE, \ __cdada_set_autogen_rtraverse_##TYPE, \ __cdada_set_autogen_dump_##TYPE, \ } /** * Auto-generate (instantiate) new custom type set, with TYPE */ #define CDADA_SET_CUSTOM_GEN(TYPE) \ __CDADA_SET_CUSTOM_CREATE_F(TYPE); \ __CDADA_SET_CUSTOM_DESTROY_F(TYPE); \ __CDADA_SET_CUSTOM_CLEAR_F(TYPE); \ __CDADA_SET_CUSTOM_EMPTY_F(TYPE); \ __CDADA_SET_CUSTOM_SIZE_F(TYPE); \ __CDADA_SET_CUSTOM_INSERT_F(TYPE); \ __CDADA_SET_CUSTOM_ERASE_F(TYPE); \ __CDADA_SET_CUSTOM_FIND_F(TYPE); \ __CDADA_SET_CUSTOM_FIRST_LAST_F(TYPE); \ __CDADA_SET_CUSTOM_TRAVERSE_F(TYPE); \ __CDADA_SET_CUSTOM_RTRAVERSE_F(TYPE); \ __CDADA_SET_CUSTOM_DUMP_F(TYPE); \ __CDADA_SET_CUSTOM_OPS(TYPE) #undef __CDADA_INTERNAL_INCLUDE #endif //__CDADA_SET_CUSTOM_CC_H__ pmacct-1.7.8/src/external_libs/libcdada/include/Makefile.am0000644000175000017500000000125714354105336022641 0ustar paolopaoloMAINTAINERCLEANFILES = Makefile.in nobase_include_HEADERS = cdada.h cdada/version.h \ cdada/bbitmap.h \ cdada/list.h \ cdada/list_custom_cc.h \ cdada/map.h \ cdada/map_custom_cc.h \ cdada/queue.h \ cdada/queue_custom_cc.h \ cdada/set.h \ cdada/set_custom_cc.h \ cdada/stack.h \ cdada/stack_custom_cc.h \ cdada/str.h \ cdada/utils.h \ cdada/__common_internal.h \ cdada/__list_internal.h \ cdada/__map_internal.h \ cdada/__queue_internal.h \ cdada/__set_internal.h \ cdada/__stack_internal.h pmacct-1.7.8/src/external_libs/libcdada/doc/0000755000175000017500000000000014354105336017722 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/doc/Custom.md0000644000175000017500000000643214354105336021523 0ustar paolopaolo# Custom type containers Default containers in `libcdada`: * Don't require C++ code to be compiled. It's sufficient to link `-lcdada` * Keys (values for lists) are limited to 1-256 bytes * Types that are not aligned to a power 2 bytes might be suboptimal both in performance and memory Custom type containers solve these two limitations by specializing backend `libstc++` containers for your C types. Some tools are provided so that you don't have to write C++ (if you don't want to). The only changes to your code from regular `libcdada` will be: ```diff + //Fwd decl + CDADA_LIST_CUSTOM_TYPE_DECL(foo_t); int my_func(){ - list = cdada_list_create(foo_t); + list = cdada_list_create_custom(foo_t); TEST_ASSERT(list != NULL); ``` The rest of operations over the containers are done using the same `libcdada` API. ## Step by step guide In this example we aim to create customer containers for: * A `list` of objects of C type `foo_t` * A `map` of objects of C type `bar_t` The code for this example, in the two variants is in: * [custom-gen/](../examples/custom-gen/) * [custom-macro/](../examples/custom-macro/) ### 1. Create `cdada.cc` file #### 1.1 Code generation `cdada-gen` Make sure `cdada-gen` is installed (you need `python3`), and: ```bash ~/ cdada-gen -o cdada.cc list:foo_t map:bar_t ``` Now edit the autogenerated file `cada.cc` and add the header includes for types `foo_t` `bar_t`: ```diff /*****************************************************************************/ /* BEGIN libcdada AUTOGENERATED C++ file */ /*****************************************************************************/ // File autogenerated from cmd: ['./cdada-gen', 'list:foo_t', 'map:bar_t', '-o', 'cdada.cc'] // Add your header includes for types {'foo_t', 'bar_t'} here + #include "foo.h" + #include "bar.h" /////////////////////////////////////////////////////////////////////////////// /// DO NOT MODIFY AFTER THIS LINE /// /////////////////////////////////////////////////////////////////////////////// ``` #### 1.2 MACRO option Alternatively, create a new file `cdada.cc` and add: ```cc #include #include #include "foo.h" #include "bar.h" //Autogen C++ comparison operators (once per user type) CDADA_CUSTOM_GEN_MEMCP_OPERATORS(foo_t); CDADA_CUSTOM_GEN_MEMCP_OPERATORS(bar_t); //Autogenerate C++ code for the containers CDADA_LIST_CUSTOM_GEN(foo_t); CDADA_MAP_CUSTOM_GEN(bar_t); ``` ### 2. Modify the code of your application Replace `cdada_list_xxx()` by `cdada_xxx_create_custom()`, and add forward declarations `CDADA_XXX_CUSTOM_TYPE_DECL` in the compilation unit where `cdada_xxx_create_custom()` are called: ```diff + //Fwd decl + CDADA_LIST_CUSTOM_TYPE_DECL(foo_t); + CDADA_MAP_CUSTOM_TYPE_DECL(bar_t); int my_func(){ - list = cdada_list_create(foo_t); + list = cdada_list_create_custom(foo_t); - map = cdada_map_create(bar_t); + map = cdada_map_create_custom(bar_t); TEST_ASSERT(list != NULL); ``` ### 3. Compile and link Make sure `cdada.cc` is compiled with `g++` or `clang++`: ```bash ~/ g++ -c cdada.cc cdada.o ``` And link it: ```bash ~/ gcc cdada.o -o my_program -lcdada -lstdc++ ``` pmacct-1.7.8/src/external_libs/libcdada/doc/Benchmarks.md0000644000175000017500000001030714354105336022322 0ustar paolopaolo# Benchmarks This section compares the performance of `libcdada` to native `libstdc++` code, to measure the overhead it adds. The benchmarking code is here: * [benchmark.cc](../test/benchmark.cc) Please note: * The benchmarking is not exhaustive, but just wants to highlight tha the the library is roughly equivalent to the underlying `libstdc++`, and that for aligned types or custom `libcdada` containers this overhead is negligible * If you have _hard_ performance requirements to meet, consider writing your own data structures. #### Conditions * Tested in Linux * Standard Debian10 `libstdc++` package * `libcdada` configured with `../configure` (`-O3`) * All lcores have been tuned to, to avoid CPU scaling during the test ``` ~/ sudo cpufreq-set -c 0 -g performance #... ~/ sudo cpufreq-set -c 7 -g performance ``` * Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz/4.6GHz * 16GB DDR4 2667 MHz ## Results The results of a random execution of `./benchmark`: ```d ==================================================================== Type: uint32_t ==================================================================== SET insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ set 752 698 C cdada_set(uint32_t) 746 743 C cdada_set_custom(uint32_t) 758 744 MAP insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ map 830 722 C cdada_map(uint32_t) 809 1009 C cdada_map_custom(uint32_t) 818 1017 LIST insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ list 20 17 C cdada_list(uint32_t) 28 20 C cdada_list_custom(uint32_t) 27 20 ==================================================================== Type: test_u552_t (69 bytes) (Note: cdada non-custom containers will pad to 128bytes) ==================================================================== SET insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ set 1410 1082 C cdada_set(test_u552_t) 1623 1311 C cdada_set_custom(test_u552_t) 1433 1098 MAP insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ map 1593 1148 C cdada_map(test_u552_t) 1646 1768 C cdada_map_custom(test_u552_t) 1605 1631 LIST insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ list 42 22 C cdada_list(test_u552_t) 67 40 C cdada_list_custom(test_u552_t) 44 25 ==================================================================== Type: test_u3552_t (444 bytes) (Note: cdada non-custom containers don't support >256 bytes) ==================================================================== SET insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ set 1991 1465 C cdada_set_custom(test_u3552_t) 2005 1479 MAP insert(ticks) erase(ticks) ------------------------------------------------------------------- C++ map 1993 1472 C cdada_map_custom(test_u3552_t) 1988 2021 LIST insert(ticks) erase(ticks) -------------------------------------------------------------------- C++ list 178 76 C cdada_list_custom(test_u3552_t) 175 79 ``` pmacct-1.7.8/src/external_libs/libcdada/configure0000755000175000017500000233507714354105427021106 0ustar paolopaolo#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for LIBCDADA v0.4.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="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 " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: marcdevel@gmail.com about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='LIBCDADA' PACKAGE_TARNAME='libcdada' PACKAGE_VERSION='v0.4.0' PACKAGE_STRING='LIBCDADA v0.4.0' PACKAGE_BUGREPORT='marcdevel@gmail.com' PACKAGE_URL='http://github.com/msune/libcdada' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS WITH_EXAMPLES_FALSE WITH_EXAMPLES_TRUE WITH_TESTS_FALSE WITH_TESTS_TRUE VALGRIND_CHECK_RULES valgrind_enabled_tools valgrind_tools ENABLE_VALGRIND_sgcheck ENABLE_VALGRIND_drd ENABLE_VALGRIND_helgrind ENABLE_VALGRIND_memcheck VALGRIND_ENABLED VALGRIND_ENABLED_FALSE VALGRIND_ENABLED_TRUE VALGRIND CDADA_VERSION_PATCH CDADA_VERSION_MINOR CDADA_VERSION_MAJOR CDADA_DESCRIBE CDADA_BRANCH CDADA_BUILD CDADA_VERSION_NORMALIZED CDADA_VERSION ff_git DEBUG_FALSE DEBUG_TRUE HAVE_PYTHON_FALSE HAVE_PYTHON_TRUE pkgpyexecdir pyexecdir pkgpythondir pythondir PYTHON_PLATFORM PYTHON_EXEC_PREFIX PYTHON_PREFIX PYTHON_VERSION PYTHON CXXCPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LIBTOOL PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG ac_ct_AR AR LD FGREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking with_gnu_ld enable_shared enable_static with_pic enable_fast_install with_aix_soname with_sysroot enable_libtool_lock enable_debug enable_profile enable_valgrind enable_valgrind_memcheck enable_valgrind_helgrind enable_valgrind_drd enable_valgrind_sgcheck with_tests with_examples ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LT_SYS_LIBRARY_PATH CXXCPP PYTHON' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures LIBCDADA v0.4.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/libcdada] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of LIBCDADA v0.4.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-debug turn on debug mode [default=no] --enable-profile turn on profile mode [default=no] --enable-valgrind Whether to enable Valgrind on the unit tests --disable-valgrind-memcheck Whether to skip memcheck during the Valgrind tests --disable-valgrind-helgrind Whether to skip helgrind during the Valgrind tests --disable-valgrind-drd Whether to skip drd during the Valgrind tests --disable-valgrind-sgcheck Whether to skip sgcheck during the Valgrind tests Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --without-tests Do not build and run tests [default=with] --without-examples Do not build examples [default=with] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor PYTHON the Python interpreter Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . LIBCDADA home page: . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF LIBCDADA configure v0.4.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ---------------------------------- ## ## Report this to marcdevel@gmail.com ## ## ---------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by LIBCDADA $as_me v0.4.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` 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 || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='libcdada' VERSION='v0.4.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 $as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi AUTOCONF_ENV="SHELL=/bin/sh" case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cr} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* 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 #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cr libconftest.a conftest.o" >&5 $AR cr libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[912]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*|11.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Some useful default flags CFLAGS="-std=gnu89 -Werror -Wall $CFLAGS" CXXFLAGS="-Werror -Wall $CXXFLAGS" $as_echo "#define __STDC_FORMAT_MACROS /**/" >>confdefs.h # Check for Python3 if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 3" >&5 $as_echo_n "checking whether $PYTHON version is >= 3... " >&6; } prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '3'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Python interpreter is too old" "$LINENO" 5 fi am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 3" >&5 $as_echo_n "checking for a Python interpreter with version >= 3... " >&6; } if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else for am_cv_pathless_PYTHON in python python2 python3 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '3'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 $as_echo "$am_cv_pathless_PYTHON" >&6; } # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. set dummy $am_cv_pathless_PYTHON; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 $as_echo "$PYTHON" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi am_display_PYTHON=$am_cv_pathless_PYTHON fi if test "$PYTHON" = :; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 $as_echo_n "checking for $am_display_PYTHON version... " >&6; } if ${am_cv_python_version+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[:2])"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 $as_echo "$am_cv_python_version" >&6; } PYTHON_VERSION=$am_cv_python_version PYTHON_PREFIX='${prefix}' PYTHON_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 $as_echo_n "checking for $am_display_PYTHON platform... " >&6; } if ${am_cv_python_platform+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 $as_echo "$am_cv_python_platform" >&6; } PYTHON_PLATFORM=$am_cv_python_platform # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[:3] == '2.7': can_use_sysconfig = 0 except ImportError: pass" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 $as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } if ${am_cv_python_pythondir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 $as_echo "$am_cv_python_pythondir" >&6; } pythondir=$am_cv_python_pythondir pkgpythondir=\${pythondir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 $as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } if ${am_cv_python_pyexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 $as_echo "$am_cv_python_pyexecdir" >&6; } pyexecdir=$am_cv_python_pyexecdir pkgpyexecdir=\${pyexecdir}/$PACKAGE fi if test "$PYTHON" != :; then HAVE_PYTHON_TRUE= HAVE_PYTHON_FALSE='#' else HAVE_PYTHON_TRUE='#' HAVE_PYTHON_FALSE= fi # Debug # Check for debug mode - MUST BE THE FIRST CHECK { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable debug mode" >&5 $as_echo_n "checking whether to enable debug mode... " >&6; } debug_default="no" # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; else enable_debug=$debug_default fi if test "$enable_debug" = "yes"; then CFLAGS="$CFLAGS -g -O0" CXXFLAGS="$CXXFLAGS -g -O0 -fno-inline" $as_echo "#define DEBUG /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else CFLAGS="$CFLAGS -O3" #--compiler-options -fno-strict-aliasing --compiler-options -fno-inline CXXFLAGS="$CXXFLAGS -O3" #-fomit-frame-pointer" $as_echo "#define NDEBUG /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$enable_debug" = yes; then DEBUG_TRUE= DEBUG_FALSE='#' else DEBUG_TRUE='#' DEBUG_FALSE= fi # Check for profiling mode # Check for profiling mode { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable profiling mode" >&5 $as_echo_n "checking whether to enable profiling mode... " >&6; } profile_default="no" # Check whether --enable-profile was given. if test "${enable_profile+set}" = set; then : enableval=$enable_profile; else enable_profile=$profile_default fi if test "$enable_profile" = "yes"; then CFLAGS="$( echo $CFLAGS | sed s/-fomit-frame-pointer//g )" CXXFLAGS="$( echo $CXXFLAGS | sed s/-fomit-frame-pointer//g )" CFLAGS="$CFLAGS -pg" CXXFLAGS="$CXXFLAGS -pg" LDFLAGS="$LDFLAGS -pg" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Checking version # Set application version based on the git version #Default CDADA_VERSION="$PACKAGE_VERSION" #Unknown (no GIT repository detected)" FILE_VERSION=`cat $srcdir/VERSION` # Extract the first word of "git", so it can be a program name with args. set dummy git; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ff_git+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ff_git"; then ac_cv_prog_ff_git="$ff_git" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ff_git="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ff_git" && ac_cv_prog_ff_git="no" fi fi ff_git=$ac_cv_prog_ff_git if test -n "$ff_git"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ff_git" >&5 $as_echo "$ff_git" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi #Normalize CDADA_VERSION_NORMALIZED=`echo $CDADA_VERSION | sed s/dev//g | sed s/RC.*//g | tr -d v` #Substs CDADA_VERSION="$CDADA_VERSION" CDADA_VERSION_NORMALIZED="$CDADA_VERSION_NORMALIZED" { $as_echo "$as_me:${as_lineno-$LINENO}: checking the build version" >&5 $as_echo_n "checking the build version... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CDADA_VERSION ($CDADA_VERSION_NORMALIZED)" >&5 $as_echo "$CDADA_VERSION ($CDADA_VERSION_NORMALIZED)" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking the build number" >&5 $as_echo_n "checking the build number... " >&6; } if test $ff_git = no then { $as_echo "$as_me:${as_lineno-$LINENO}: result: git not found!" >&5 $as_echo "git not found!" >&6; } else if test -d $srcdir/.git ; then #Try to retrieve the build number _CDADA_GIT_BUILD=`git log -1 --pretty=%H` _CDADA_GIT_BRANCH=`git rev-parse --abbrev-ref HEAD` _CDADA_GIT_DESCRIBE=`git describe --abbrev=40` CDADA_BUILD="$_CDADA_GIT_BUILD" CDADA_BRANCH="$_CDADA_GIT_BRANCH" CDADA_DESCRIBE="$_CDADA_GIT_DESCRIBE" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_CDADA_GIT_BUILD" >&5 $as_echo "$_CDADA_GIT_BUILD" >&6; } fi #File version always exists CDADA_VERSION_MAJOR=`echo $CDADA_VERSION | awk -F "." '{ print $1 }' | sed 's/v//'` CDADA_VERSION_MINOR=`echo $CDADA_VERSION | awk -F "." '{ print $2 }'` CDADA_VERSION_PATCH=`echo $CDADA_VERSION | awk -F "." '{ print $3 }'` # Checking valgrind # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html # =========================================================================== # # SYNOPSIS # # AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) # AX_VALGRIND_CHECK() # # DESCRIPTION # # AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows # running `make check` under a variety of Valgrind tools to check for # memory and threading errors. # # Defines VALGRIND_CHECK_RULES which should be substituted in your # Makefile; and $enable_valgrind which can be used in subsequent configure # output. VALGRIND_ENABLED is defined and substituted, and corresponds to # the value of the --enable-valgrind option, which defaults to being # enabled if Valgrind is installed and disabled otherwise. Individual # Valgrind tools can be disabled via --disable-valgrind-, the # default is configurable via the AX_VALGRIND_DFLT command or is to use # all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT # calls must be made before the call to AX_VALGRIND_CHECK. # # If unit tests are written using a shell script and automake's # LOG_COMPILER system, the $(VALGRIND) variable can be used within the # shell scripts to enable Valgrind, as described here: # # https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html # # Usage example: # # configure.ac: # # AX_VALGRIND_DFLT([sgcheck], [off]) # AX_VALGRIND_CHECK # # in each Makefile.am with tests: # # @VALGRIND_CHECK_RULES@ # VALGRIND_SUPPRESSIONS_FILES = my-project.supp # EXTRA_DIST = my-project.supp # # This results in a "check-valgrind" rule being added. Running `make # check-valgrind` in that directory will recursively run the module's test # suite (`make check`) once for each of the available Valgrind tools (out # of memcheck, helgrind and drd) while the sgcheck will be skipped unless # enabled again on the commandline with --enable-valgrind-sgcheck. The # results for each check will be output to test-suite-$toolname.log. The # target will succeed if there are zero errors and fail otherwise. # # Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in # memcheck, helgrind, drd and sgcheck. These are useful because often only # some of those tools can be ran cleanly on a codebase. # # The macro supports running with and without libtool. # # LICENSE # # Copyright (c) 2014, 2015, 2016 Philip Withnall # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 17 #Now check # Check whether --enable-valgrind was given. if test "${enable_valgrind+set}" = set; then : enableval=$enable_valgrind; enable_valgrind=$enableval else enable_valgrind= fi if test "$enable_valgrind" != "no"; then : # Check for Valgrind. # Extract the first word of "valgrind", so it can be a program name with args. set dummy valgrind; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_VALGRIND+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$VALGRIND"; then ac_cv_prog_VALGRIND="$VALGRIND" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_VALGRIND="valgrind" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi VALGRIND=$ac_cv_prog_VALGRIND if test -n "$VALGRIND"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND" >&5 $as_echo "$VALGRIND" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$VALGRIND" = ""; then : if test "$enable_valgrind" = "yes"; then : as_fn_error $? "Could not find valgrind; either install it or reconfigure with --disable-valgrind" "$LINENO" 5 else enable_valgrind=no fi else enable_valgrind=yes fi fi if test "$enable_valgrind" = "yes"; then VALGRIND_ENABLED_TRUE= VALGRIND_ENABLED_FALSE='#' else VALGRIND_ENABLED_TRUE='#' VALGRIND_ENABLED_FALSE= fi VALGRIND_ENABLED=$enable_valgrind # Check for Valgrind tools we care about. valgrind_enabled_tools= # Check whether --enable-valgrind-memcheck was given. if test "${enable_valgrind_memcheck+set}" = set; then : enableval=$enable_valgrind_memcheck; enable_valgrind_memcheck=$enableval else enable_valgrind_memcheck= fi if test "$enable_valgrind" = "no"; then : enable_valgrind_memcheck=no elif test "$enable_valgrind_memcheck" != "no"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Valgrind tool memcheck" >&5 $as_echo_n "checking for Valgrind tool memcheck... " >&6; } if ${ax_cv_valgrind_tool_memcheck+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_valgrind_tool_memcheck=no if `$VALGRIND --tool=memcheck --help >/dev/null 2>&1`; then : ax_cv_valgrind_tool_memcheck=yes fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_valgrind_tool_memcheck" >&5 $as_echo "$ax_cv_valgrind_tool_memcheck" >&6; } if test "$ax_cv_valgrind_tool_memcheck" = "no"; then : if test "$enable_valgrind_memcheck" = "yes"; then : as_fn_error $? "Valgrind does not support memcheck; reconfigure with --disable-valgrind-memcheck" "$LINENO" 5 else enable_valgrind_memcheck=no fi else enable_valgrind_memcheck=yes fi fi if test "$enable_valgrind_memcheck" = "yes"; then : valgrind_enabled_tools="$valgrind_enabled_tools memcheck" fi ENABLE_VALGRIND_memcheck=$enable_valgrind_memcheck # Check whether --enable-valgrind-helgrind was given. if test "${enable_valgrind_helgrind+set}" = set; then : enableval=$enable_valgrind_helgrind; enable_valgrind_helgrind=$enableval else enable_valgrind_helgrind= fi if test "$enable_valgrind" = "no"; then : enable_valgrind_helgrind=no elif test "$enable_valgrind_helgrind" != "no"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Valgrind tool helgrind" >&5 $as_echo_n "checking for Valgrind tool helgrind... " >&6; } if ${ax_cv_valgrind_tool_helgrind+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_valgrind_tool_helgrind=no if `$VALGRIND --tool=helgrind --help >/dev/null 2>&1`; then : ax_cv_valgrind_tool_helgrind=yes fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_valgrind_tool_helgrind" >&5 $as_echo "$ax_cv_valgrind_tool_helgrind" >&6; } if test "$ax_cv_valgrind_tool_helgrind" = "no"; then : if test "$enable_valgrind_helgrind" = "yes"; then : as_fn_error $? "Valgrind does not support helgrind; reconfigure with --disable-valgrind-helgrind" "$LINENO" 5 else enable_valgrind_helgrind=no fi else enable_valgrind_helgrind=yes fi fi if test "$enable_valgrind_helgrind" = "yes"; then : valgrind_enabled_tools="$valgrind_enabled_tools helgrind" fi ENABLE_VALGRIND_helgrind=$enable_valgrind_helgrind # Check whether --enable-valgrind-drd was given. if test "${enable_valgrind_drd+set}" = set; then : enableval=$enable_valgrind_drd; enable_valgrind_drd=$enableval else enable_valgrind_drd= fi if test "$enable_valgrind" = "no"; then : enable_valgrind_drd=no elif test "$enable_valgrind_drd" != "no"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Valgrind tool drd" >&5 $as_echo_n "checking for Valgrind tool drd... " >&6; } if ${ax_cv_valgrind_tool_drd+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_valgrind_tool_drd=no if `$VALGRIND --tool=drd --help >/dev/null 2>&1`; then : ax_cv_valgrind_tool_drd=yes fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_valgrind_tool_drd" >&5 $as_echo "$ax_cv_valgrind_tool_drd" >&6; } if test "$ax_cv_valgrind_tool_drd" = "no"; then : if test "$enable_valgrind_drd" = "yes"; then : as_fn_error $? "Valgrind does not support drd; reconfigure with --disable-valgrind-drd" "$LINENO" 5 else enable_valgrind_drd=no fi else enable_valgrind_drd=yes fi fi if test "$enable_valgrind_drd" = "yes"; then : valgrind_enabled_tools="$valgrind_enabled_tools drd" fi ENABLE_VALGRIND_drd=$enable_valgrind_drd # Check whether --enable-valgrind-sgcheck was given. if test "${enable_valgrind_sgcheck+set}" = set; then : enableval=$enable_valgrind_sgcheck; enable_valgrind_sgcheck=$enableval else enable_valgrind_sgcheck= fi if test "$enable_valgrind" = "no"; then : enable_valgrind_sgcheck=no elif test "$enable_valgrind_sgcheck" != "no"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Valgrind tool sgcheck" >&5 $as_echo_n "checking for Valgrind tool sgcheck... " >&6; } if ${ax_cv_valgrind_tool_sgcheck+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_valgrind_tool_sgcheck=no if `$VALGRIND --tool=exp-sgcheck --help >/dev/null 2>&1`; then : ax_cv_valgrind_tool_sgcheck=yes fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_valgrind_tool_sgcheck" >&5 $as_echo "$ax_cv_valgrind_tool_sgcheck" >&6; } if test "$ax_cv_valgrind_tool_sgcheck" = "no"; then : if test "$enable_valgrind_sgcheck" = "yes"; then : as_fn_error $? "Valgrind does not support sgcheck; reconfigure with --disable-valgrind-sgcheck" "$LINENO" 5 else enable_valgrind_sgcheck=no fi else enable_valgrind_sgcheck=yes fi fi if test "$enable_valgrind_sgcheck" = "yes"; then : valgrind_enabled_tools="$valgrind_enabled_tools sgcheck" fi ENABLE_VALGRIND_sgcheck=$enable_valgrind_sgcheck valgrind_tools="memcheck helgrind drd sgcheck" valgrind_enabled_tools=$valgrind_enabled_tools VALGRIND_CHECK_RULES=' # Valgrind check # # Optional: # - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions # files to load. (Default: empty) # - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. # (Default: --num-callers=30) # - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: # memcheck, helgrind, drd, sgcheck). (Default: various) # Optional variables VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) VALGRIND_FLAGS ?= --num-callers=30 VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no VALGRIND_helgrind_FLAGS ?= --history-level=approx VALGRIND_drd_FLAGS ?= VALGRIND_sgcheck_FLAGS ?= # Internal use valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) valgrind_quiet = $(valgrind_quiet_$(V)) valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) valgrind_quiet_0 = --quiet valgrind_v_use = $(valgrind_v_use_$(V)) valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; # Support running with and without libtool. ifneq ($(LIBTOOL),) valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute else valgrind_lt = endif # Use recursive makes in order to ignore errors during check check-valgrind-am: ifeq ($(VALGRIND_ENABLED),yes) $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) else @echo "Need to reconfigure with --enable-valgrind" endif # Valgrind running VALGRIND_TESTS_ENVIRONMENT = \ $(TESTS_ENVIRONMENT) \ env VALGRIND=$(VALGRIND) \ G_SLICE=always-malloc,debug-blocks \ G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly VALGRIND_LOG_COMPILER = \ $(valgrind_lt) \ $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) define valgrind_tool_rule check-valgrind-$(1)-am: ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) ifneq ($$(TESTS),) $$(valgrind_v_use)$$(MAKE) check-TESTS \ TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ LOG_FLAGS="$$(valgrind_$(1)_flags)" \ TEST_SUITE_LOG=test-suite-$(1).log endif else ifeq ($$(VALGRIND_ENABLED),yes) @echo "Need to reconfigure with --enable-valgrind-$(1)" else @echo "Need to reconfigure with --enable-valgrind" endif endef $(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) A''M_DISTCHECK_CONFIGURE_FLAGS ?= A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind MOSTLYCLEANFILES ?= MOSTLYCLEANFILES += $(valgrind_log_files) .PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) ' # Checking RDTSC { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether RDTSC support is available" >&5 $as_echo_n "checking whether RDTSC support is available... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(){ unsigned int hi, lo; __asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi)); printf("%u, %u\n", hi, lo); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_rdtsc=yes else have_rdtsc=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$have_rdtsc" = "yes"; then $as_echo "#define HAVE_RDTSC /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Tests WITH_TESTS_DEFAULT=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile and run tests" >&5 $as_echo_n "checking whether to compile and run tests... " >&6; } # Check whether --with-tests was given. if test "${with_tests+set}" = set; then : withval=$with_tests; WITH_TESTS="$withval" else WITH_TESTS="$WITH_TESTS_DEFAULT" fi if test x"$WITH_TESTS" = x"yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$WITH_TESTS" = "xyes"; then WITH_TESTS_TRUE= WITH_TESTS_FALSE='#' else WITH_TESTS_TRUE='#' WITH_TESTS_FALSE= fi # Examples WITH_EXAMPLES_DEFAULT=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile examples" >&5 $as_echo_n "checking whether to compile examples... " >&6; } # Check whether --with-examples was given. if test "${with_examples+set}" = set; then : withval=$with_examples; WITH_EXAMPLES="$withval" else WITH_EXAMPLES="$WITH_EXAMPLES_DEFAULT" fi if test x"$WITH_EXAMPLES" = x"yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$WITH_EXAMPLES" = "xyes"; then WITH_EXAMPLES_TRUE= WITH_EXAMPLES_FALSE='#' else WITH_EXAMPLES_TRUE='#' WITH_EXAMPLES_FALSE= fi # Output files ac_config_files="$ac_config_files Makefile include/Makefile examples/Makefile src/Makefile tools/Makefile include/cdada/version.h" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_PYTHON_TRUE}" && test -z "${HAVE_PYTHON_FALSE}"; then as_fn_error $? "conditional \"HAVE_PYTHON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then as_fn_error $? "conditional \"DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${VALGRIND_ENABLED_TRUE}" && test -z "${VALGRIND_ENABLED_FALSE}"; then as_fn_error $? "conditional \"VALGRIND_ENABLED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_TESTS_TRUE}" && test -z "${WITH_TESTS_FALSE}"; then as_fn_error $? "conditional \"WITH_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_EXAMPLES_TRUE}" && test -z "${WITH_EXAMPLES_FALSE}"; then as_fn_error $? "conditional \"WITH_EXAMPLES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by LIBCDADA $as_me v0.4.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to . LIBCDADA home page: ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ LIBCDADA config.status v0.4.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ SHELL \ ECHO \ LD \ PATH_SEPARATOR \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "include/cdada/version.h") CONFIG_FILES="$CONFIG_FILES include/cdada/version.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 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 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 . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi pmacct-1.7.8/src/external_libs/libcdada/README.md0000644000175000017500000000722214354105336020437 0ustar paolopaolomaster [![Build status](https://github.com/msune/libcdada/workflows/ci/badge.svg?branch=master)](https://github.com/msune/libcdada/actions), devel [![Build status](https://github.com/msune/libcdada/workflows/ci/badge.svg?branch=devel)](https://github.com/msune/libcdada/actions) **libcdada** - basic data structures in C (`libstdc++` wrapper) --------------------------------------------------------------- Small library that offers basic data structures (`list`, `set`, `map`...) in a pure C API for user-space applications. Key features: * Easy to use, portable * No "magic" MACROs, and no need to modify your data structures (except, perhaps, for `__attribute__((packed))`) * Stable and well-tested backend engine (`libstdc++`) for most of the data structures * Reasonable performance - comparable to `libstdc++` Example ------- ```c #include int x, val=0; cdada_list_t* my_list = cdada_list_create(int); //Add to list {10, 11, 5, 5} x=10; cdada_list_push_back(my_list, &x); x=11; cdada_list_push_back(my_list, &x); x=5; cdada_list_push_back(my_list, &x); cdada_list_push_back(my_list, &x); //Get element in position 1 cdada_list_get(my_list, 1, &val); assert(val == 11); //First/last cdada_list_first(my_list, &val); assert(val == 10); //Add {10, 11, 5, 11} x=11; cdada_list_push_back(my_list, &val); //Traverse list cdada_list_traverse(my_list, my_iterator_func, opaque); ``` ```c #include cdada_str_t* s = cdada_str_create("One string"); fprintf(stdout, "%s\n", cdada_str(s)); //Reset cdada_str_set(s, "This is a test"); fprintf(stdout, "%s\n", cdada_str(s)); cdada_str_append(s, " simple string"); cdada_str_lower(s); cdada_str_replace_all(s, "test ", ""); //Will print: "this is a simple string" fprintf(stdout, "%s\n", cdada_str(s)); ``` More examples for `map` and `set` and custom containers in the [examples](examples/) folder. Documentation ------------- Public API: * [cdada.h](include/cdada.h): includes all headers listed below * [cdada/bbitmap.h](include/cdada/bbitmap.h): big bitmap (> 64bit) * [cdada/list.h](include/cdada/list.h): an ordered list of objects (equivalent to `std::list`) * [cdada/map.h](include/cdada/map.h): a hashmap {key -> value}, with unique keys (equivalent to `std::map`) * [cdada/queue.h](include/cdada/queue.h): queue (FIFO queue) implementation (equivalent to `std::queue`) * [cdada/set.h](include/cdada/set.h): a set of objects (equivalent to `std::set`) * [cdada/stack.h](include/cdada/stack.h): stack (LIFO queue) implementation (equivalent to `std::stack`) * [cdada/str.h](include/cdada/str.h): a string (equivalent to `std::string`) * [cdada/utils.h](include/cdada/utils.h): error codes and utility functions `libcdada` is not thread-safe. Default containers support 1-256 bytes keys (values for lists), but they will perform better when aligned to {1,2,4,8,32,64,128,256} bytes - keys are padded to a power of 2 bytes. #### Custom containers For larger keys (any length), optimal memory usage and performance take a look at `libcdada`'s **[custom containers](doc/Custom.md)**. #### Benchmarking Take a look at **[benchmarking](doc/Benchmarks.md)** for an rough idea of the overhead of `libcdada` compared to `libstdc++`. Installation ------------ Requirements: * POSIX system * C and C++ gcc compatible compilers (gcc, icc, clang...) * Automake * Autoconf * Libtool * libstdc++ (C++98) ``` sh autogen.sh cd build ../configure sudo make install ``` #### Windows support The library solely depends on `libstdc++`, so it should be very easy to port it to Windows. If you are interested, consider submitting a PR. Contact ------- Marc Sune < marcdevel (at) gmail (dot) com> pmacct-1.7.8/src/external_libs/libcdada/Makefile.in0000644000175000017500000007054014354105430021223 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = @WITH_EXAMPLES_TRUE@am__append_2 = examples subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/config_m4/debug.m4 \ $(top_srcdir)/config_m4/profiling.m4 \ $(top_srcdir)/config_m4/versioning.m4 \ $(top_srcdir)/config_m4/valgrind.m4 \ $(top_srcdir)/config_m4/rdtsc.m4 \ $(top_srcdir)/config_m4/tests.m4 \ $(top_srcdir)/config_m4/examples.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = include/cdada/version.h CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__extra_recursive_targets = check-valgrind-recursive \ check-valgrind-memcheck-recursive \ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ check-valgrind-sgcheck-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = include src tools examples am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build-aux/ar-lib \ $(top_srcdir)/build-aux/compile \ $(top_srcdir)/build-aux/config.guess \ $(top_srcdir)/build-aux/config.sub \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/ltmain.sh \ $(top_srcdir)/build-aux/missing \ $(top_srcdir)/include/cdada/version.h.in AUTHORS \ build-aux/ar-lib build-aux/compile build-aux/config.guess \ build-aux/config.sub build-aux/install-sh build-aux/ltmain.sh \ build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDADA_BRANCH = @CDADA_BRANCH@ CDADA_BUILD = @CDADA_BUILD@ CDADA_DESCRIBE = @CDADA_DESCRIBE@ CDADA_VERSION = @CDADA_VERSION@ CDADA_VERSION_MAJOR = @CDADA_VERSION_MAJOR@ CDADA_VERSION_MINOR = @CDADA_VERSION_MINOR@ CDADA_VERSION_NORMALIZED = @CDADA_VERSION_NORMALIZED@ CDADA_VERSION_PATCH = @CDADA_VERSION_PATCH@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VALGRIND_ENABLED = @VALGRIND_ENABLED@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ ff_git = @ff_git@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ MAINTAINERCLEANFILES = \ $(top_srcdir)/aclocal.m4 \ $(top_srcdir)/configure \ $(top_srcdir)/Makefile.in SUBDIRS = include src tools $(am__append_1) $(am__append_2) all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): include/cdada/version.h: $(top_builddir)/config.status $(top_srcdir)/include/cdada/version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" check-valgrind-local: check-valgrind-memcheck-local: check-valgrind-helgrind-local: check-valgrind-drd-local: check-valgrind-sgcheck-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) check-valgrind: check-valgrind-recursive check-valgrind-am: check-valgrind-local check-valgrind-drd: check-valgrind-drd-recursive check-valgrind-drd-am: check-valgrind-drd-local check-valgrind-helgrind: check-valgrind-helgrind-recursive check-valgrind-helgrind-am: check-valgrind-helgrind-local check-valgrind-memcheck: check-valgrind-memcheck-recursive check-valgrind-memcheck-am: check-valgrind-memcheck-local check-valgrind-sgcheck: check-valgrind-sgcheck-recursive check-valgrind-sgcheck-am: check-valgrind-sgcheck-local clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: $(am__recursive_targets) install-am install-exec-am \ install-strip uninstall-am .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am check-valgrind-am \ check-valgrind-drd-am check-valgrind-drd-local \ check-valgrind-helgrind-am check-valgrind-helgrind-local \ check-valgrind-local check-valgrind-memcheck-am \ check-valgrind-memcheck-local check-valgrind-sgcheck-am \ check-valgrind-sgcheck-local clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip dist-zstd distcheck distclean \ distclean-generic distclean-libtool distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-exec-hook install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-hook .PRECIOUS: Makefile #Could be improved.. .PHONY: doc doc: @cd doc/ && make doc install-exec-hook: uninstall-hook: maintainer-clean-local: rm -rf $(top_srcdir)/m4 rm -rf $(top_srcdir)/build-aux # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/examples/0000755000175000017500000000000014354105430020766 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/queue_u32.c0000644000175000017500000000152214354105336022754 0ustar paolopaolo#include #include #include #include int main(int args, char** argv){ uint32_t item; cdada_queue_t* q = cdada_queue_create(uint32_t); //Push {1,3,5,4,6,5} item = 1; cdada_queue_push(q, &item); item = 3; cdada_queue_push(q, &item); item = 5; cdada_queue_push(q, &item); item = 4; cdada_queue_push(q, &item); item = 6; cdada_queue_push(q, &item); item = 5; cdada_queue_push(q, &item); fprintf(stdout, "The queue has a size of %u:\n", cdada_queue_size(q)); uint32_t val; cdada_queue_front(q, &val); fprintf(stdout, "Popping %u off the queue:\n", val); cdada_queue_pop(q); fprintf(stdout, "After removal of front, the queue has a size of %u, contents:\n", cdada_queue_size(q)); cdada_queue_print(q, stdout); //Don't leak cdada_queue_destroy(q); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/stack_u32.c0000644000175000017500000000151614354105336022740 0ustar paolopaolo#include #include #include #include int main(int args, char** argv){ uint32_t item; cdada_stack_t* s = cdada_stack_create(uint32_t); //Push {1,3,5,4,6,5} item = 1; cdada_stack_push(s, &item); item = 3; cdada_stack_push(s, &item); item = 5; cdada_stack_push(s, &item); item = 4; cdada_stack_push(s, &item); item = 6; cdada_stack_push(s, &item); item = 5; cdada_stack_push(s, &item); fprintf(stdout, "The stack has a size of %u:\n", cdada_stack_size(s)); uint32_t val; cdada_stack_top(s, &val); fprintf(stdout, "Popping %u off the stack:\n", val); cdada_stack_pop(s); fprintf(stdout, "After removal of top, the stack has a size of %u, contents:\n", cdada_stack_size(s)); cdada_stack_print(s, stdout); //Don't leak cdada_stack_destroy(s); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/custom-macro/0000755000175000017500000000000014354105336023404 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/custom-macro/bar.h0000777000175000017500000000000014354105336027527 2../custom-gen/bar.hustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/custom-macro/foo.h0000777000175000017500000000000014354105336027565 2../custom-gen/foo.hustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/custom-macro/cdada.cc0000644000175000017500000000053014354105336024745 0ustar paolopaolo#include #include #include "foo.h" #include "bar.h" //Autogen C++ comparison operators (once per user type) CDADA_CUSTOM_GEN_MEMCP_OPERATORS(foo_t); CDADA_CUSTOM_GEN_MEMCP_OPERATORS(bar_t); //Autogenerate C++ code for the containers CDADA_LIST_CUSTOM_GEN(foo_t); CDADA_MAP_CUSTOM_GEN(bar_t); pmacct-1.7.8/src/external_libs/libcdada/examples/custom-macro/my_program.c0000777000175000017500000000000014354105336033366 2../custom-gen/my_program_gen.custar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/bbitmap.c0000644000175000017500000000265414354105336022564 0ustar paolopaolo#include #include #include #include int main(int args, char** argv){ int rv; cdada_bbitmap_t* b = cdada_bbitmap_create(256); cdada_bbitmap_print(b, stdout); cdada_bbitmap_set(b, 113); fprintf(stdout, "\nAfter setting bit 113:\n"); cdada_bbitmap_print(b, stdout); if(!cdada_bbitmap_is_set(b, 113)){ fprintf(stderr, "libcdada has a bug!"); exit(1); } cdada_bbitmap_set_all(b); fprintf(stdout, "\nAfter setting all bit:\n"); if(!cdada_bbitmap_is_set(b, 113) || !cdada_bbitmap_is_set(b, 0) || !cdada_bbitmap_is_set(b, 255)){ fprintf(stderr, "libcdada has a bug!"); exit(1); } cdada_bbitmap_print(b, stdout); cdada_bbitmap_clear(b, 113); if(cdada_bbitmap_is_set(b, 113) || !cdada_bbitmap_is_set(b, 0) || !cdada_bbitmap_is_set(b, 255)){ fprintf(stderr, "libcdada has a bug!"); exit(1); } fprintf(stdout, "\nCleared bit 113:\n"); cdada_bbitmap_print(b, stdout); //Use a buffer char buffer[1024]; uint32_t used; //Calculate the number of bytes we need rv = cdada_bbitmap_dump(b, 0, NULL, &used); fprintf(stdout, "\nWe will need: %u bytes\n", used); rv = cdada_bbitmap_dump(b, 1024, buffer, &used); if(rv == CDADA_E_INCOMPLETE){ fprintf(stderr, "Warning: dump was truncated\n"); } fprintf(stdout, "\nFinal printf using dump() function, same state:\n%s\nEnd\n", buffer); //Don't leak cdada_bbitmap_destroy(b); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/list_u32.c0000644000175000017500000000321514354105336022604 0ustar paolopaolo#include #include #include #include void trav_print_and_sum(const cdada_list_t* s, const void* k, void* opaque){ uint32_t key = *(uint32_t*)k; uint32_t* o = (uint32_t*)opaque; *o += key; fprintf(stdout, "\t[%u] cnt=%u\n", key, *o); } int main(int args, char** argv){ uint32_t item, counter; cdada_list_t* l = cdada_list_create(uint32_t); //Add {1,3,5,4,6,5} item = 1; cdada_list_push_back(l, &item); item = 3; cdada_list_push_back(l, &item); item = 5; cdada_list_push_back(l, &item); item = 4; cdada_list_push_back(l, &item); item = 6; cdada_list_push_back(l, &item); item = 5; cdada_list_push_back(l, &item); fprintf(stdout, "The list has a size of %u, contents:\n", cdada_list_size(l)); counter = 0; cdada_list_traverse(l, &trav_print_and_sum, &counter); fprintf(stdout, "TOTAL: %u\n", counter); //{{1,3,5,6,5} cdada_list_erase(l, 3); fprintf(stdout, "After removal of 4, the list has a size of %u, contents:\n", cdada_list_size(l)); counter = 0; cdada_list_traverse(l, &trav_print_and_sum, &counter); fprintf(stdout, "TOTAL: %u\n", counter); //Remove front element and reverse {5,6,5,3} cdada_list_pop_front(l); cdada_list_reverse(l); cdada_list_get(l, 1, &item); fprintf(stdout, "After pop front and reverse, 2nd element is: %u, size: %u\n", item, cdada_list_size(l)); //Sort and unique {3,5,6} cdada_list_sort(l); cdada_list_unique(l); fprintf(stdout, "After unique contents:\n"); counter = 0; cdada_list_traverse(l, &trav_print_and_sum, &counter); fprintf(stdout, "TOTAL: %u\n", counter); //Don't leak cdada_list_destroy(l); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/custom-gen/0000755000175000017500000000000014354105336023054 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/examples/custom-gen/my_program_gen.c0000644000175000017500000000342114354105336026225 0ustar paolopaolo#include #include #include #include #include #include #include #include "foo.h" #include "bar.h" //Type fwd decl CDADA_LIST_CUSTOM_TYPE_DECL(foo_t); CDADA_MAP_CUSTOM_TYPE_DECL(bar_t); int main(int args, char** argv){ foo_t foo_key; bar_t bar_key; int i, rv, values[32]; int* val; void* val_aux; //Avoid alias warnings cdada_list_t* list; cdada_map_t* map; list = cdada_list_create_custom(foo_t); map = cdada_map_create_custom(bar_t); assert(list != NULL); assert(map != NULL); // //LIST // //Add elements in the list - !! always initialize all values memset(&foo_key, 0, sizeof(foo_key)); foo_key.aa = 64ULL; foo_key.bb = 32ULL; cdada_list_push_back(list, &foo_key); foo_key.aa = 12ULL; foo_key.bb = 15ULL; cdada_list_push_back(list, &foo_key); fprintf(stdout, "The list has a size of %u, contents:\n", cdada_list_size(list)); foo_key.aa = 64ULL; foo_key.bb = 32ULL; if(cdada_list_get(list, 0, &foo_key) != CDADA_SUCCESS){ //libcdada has a bug exit(1); } assert(foo_key.aa == 64ULL); cdada_list_erase(list, 0); fprintf(stdout, "The list has a size of %u, contents:\n", cdada_list_size(list)); // //MAP // memset(&bar_key, 0, sizeof(bar_key)); for(i=0;i<32;++i){ bar_key.aa = 2*i; bar_key.bb = 0.55; values[i] = i; cdada_map_insert(map, &bar_key, &values[i]); } bar_key.aa = 2*5; bar_key.bb = 0.55; rv = cdada_map_find(map, &bar_key, &val_aux); if(rv != CDADA_SUCCESS){ //libcdada has a bug exit(1); } val = (int*)val_aux; assert(*val == 5); fprintf(stdout, "Value for aa: %u, bb: %f -> %d\n", bar_key.aa, bar_key.bb, *val); //Don't leak cdada_list_destroy(list); cdada_map_destroy(map); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/custom-gen/bar.h0000644000175000017500000000027714354105336023777 0ustar paolopaolo#ifndef BAR_H #define BAR_H #include //69byte type typedef struct{ uint16_t aa; float bb; uint8_t unaligned; } __attribute__((packed)) bar_t; //MUST BE PACKED #endif //BAR_H pmacct-1.7.8/src/external_libs/libcdada/examples/custom-gen/foo.h0000644000175000017500000000030214354105336024003 0ustar paolopaolo#ifndef FOO_H #define FOO_H #include //69byte type typedef struct{ uint64_t aa; uint64_t bb; uint8_t big[3000]; } __attribute__((packed)) foo_t; //MUST BE PACKED #endif //FOO_H pmacct-1.7.8/src/external_libs/libcdada/examples/custom-gen/cdada.cc0000644000175000017500000002350714354105336024426 0ustar paolopaolo/*****************************************************************************/ /* BEGIN libcdada AUTOGENERATED C++ file */ /*****************************************************************************/ // File autogenerated from cmd: ['../../tools/cdada-gen', 'list:foo_t', 'map:bar_t', '-o', 'cdada.cc'] // Add your header includes for types {'bar_t', 'foo_t'} here #include "foo.h" #include "bar.h" /////////////////////////////////////////////////////////////////////////////// /// DO NOT MODIFY AFTER THIS LINE /// /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include //C++ comparison operators for user stypes (memcmp) inline bool operator<(const bar_t & a1, const bar_t & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( bar_t )) < 0; } inline bool operator==(const bar_t & a1, const bar_t & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( bar_t )) == 0; } inline bool operator<(const foo_t & a1, const foo_t & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( foo_t )) < 0; } inline bool operator==(const foo_t & a1, const foo_t & a2){ return memcmp((const void*)&a1, (const void*)&a2, sizeof( foo_t )) == 0; } //Cdata wrappers //BEGIN list for foo_t (std::list) //Operator void __cdada_list_autogen_create_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; s->list.custom = (void*)new std::list(); } void __cdada_list_autogen_destroy_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; delete p; } void __cdada_list_autogen_clear_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->clear(); } bool __cdada_list_autogen_empty_foo_t (const void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return p->empty(); } uint32_t __cdada_list_autogen_size_foo_t (const void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return p->size(); } int __cdada_list_autogen_insert_foo_t (void* m, const void* val, const uint32_t pos){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_insert_u (s, p, val, pos); } int __cdada_list_autogen_get_foo_t (const void* m, const uint32_t pos, void* val){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_get_u (s, p, pos, val); } int __cdada_list_autogen_first_last_foo_t (const void* m, bool first, void* key){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_first_last_u (s, p, first, key); } int __cdada_list_autogen_erase_foo_t (void* m, const uint32_t pos){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_erase_u (s, p, pos); } int __cdada_list_autogen_remove_foo_t (void* m, const void* val){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_remove_u (s, p, val); } int __cdada_list_autogen_push_foo_t (void* m, const void* val, bool front){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_push_u (s, p, val, front); } int __cdada_list_autogen_pop_foo_t (void* m, bool front){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_pop_u (s, p, front); } void __cdada_list_autogen_sort_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->sort(); } void __cdada_list_autogen_reverse_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->reverse(); } void __cdada_list_autogen_unique_foo_t (void* m){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; p->unique(); } void __cdada_list_autogen_traverse_foo_t (const void* m, cdada_list_it f, void* opaque){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_traverse_u (s, p, f, opaque); } void __cdada_list_autogen_rtraverse_foo_t (const void* m, cdada_list_it f, void* opaque){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_rtraverse_u (s, p, f, opaque); } void __cdada_list_autogen_dump_foo_t (const void* m, std::stringstream& ss){ __cdada_list_int_t* s = (__cdada_list_int_t*)m; std::list* p = (std::list*)s->list.custom; return cdada_list_dump_u< foo_t > (s, p, ss); } __cdada_list_ops_t __cdada_list_autogen_foo_t = { __cdada_list_autogen_create_foo_t, __cdada_list_autogen_destroy_foo_t, __cdada_list_autogen_clear_foo_t, __cdada_list_autogen_empty_foo_t, __cdada_list_autogen_size_foo_t, __cdada_list_autogen_insert_foo_t, __cdada_list_autogen_get_foo_t, __cdada_list_autogen_first_last_foo_t, __cdada_list_autogen_erase_foo_t, __cdada_list_autogen_remove_foo_t, __cdada_list_autogen_push_foo_t, __cdada_list_autogen_pop_foo_t, __cdada_list_autogen_sort_foo_t, __cdada_list_autogen_reverse_foo_t, __cdada_list_autogen_unique_foo_t, __cdada_list_autogen_traverse_foo_t, __cdada_list_autogen_rtraverse_foo_t, __cdada_list_autogen_dump_foo_t, }; //END list for foo_t (std::list) //BEGIN map for bar_t (std::map) void __cdada_map_autogen_create_bar_t (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; s->map.custom = (void*)new std::map(); } void __cdada_map_autogen_destroy_bar_t (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; delete p; } void __cdada_map_autogen_clear_bar_t (void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; p->clear(); } bool __cdada_map_autogen_empty_bar_t (const void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return p->empty(); } uint32_t __cdada_map_autogen_size_bar_t (const void* m){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return p->size(); } int __cdada_map_autogen_insert_bar_t (void* m, const void* key, void* val, const bool replace){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_insert_u (s, p, key, val, replace); } int __cdada_map_autogen_erase_bar_t (void* m, const void* key){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_erase_u (s, p, key); } int __cdada_map_autogen_find_bar_t (const void* m, const void* key, void** val){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_find_u (s, p, key, val); } int __cdada_map_autogen_first_last_bar_t (const void* m, bool first, void* key, void** val){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_first_last_u (s, p, first, key, val); } void __cdada_map_autogen_traverse_bar_t (const void* m, cdada_map_it f, void* opaque){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_traverse_u (s, p, f, opaque); } void __cdada_map_autogen_rtraverse_bar_t (const void* m, cdada_map_it f, void* opaque){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_rtraverse_u (s, p, f, opaque); } void __cdada_map_autogen_dump_bar_t (const void* m, std::stringstream& ss){ __cdada_map_int_t* s = (__cdada_map_int_t*)m; std::map* p = (std::map*)s->map.custom; return cdada_map_dump_u< bar_t > (s, p, ss); } __cdada_map_ops_t __cdada_map_autogen_bar_t = { __cdada_map_autogen_create_bar_t, __cdada_map_autogen_destroy_bar_t, __cdada_map_autogen_clear_bar_t, __cdada_map_autogen_empty_bar_t, __cdada_map_autogen_size_bar_t, __cdada_map_autogen_insert_bar_t, __cdada_map_autogen_erase_bar_t, __cdada_map_autogen_find_bar_t, __cdada_map_autogen_first_last_bar_t, __cdada_map_autogen_traverse_bar_t, __cdada_map_autogen_rtraverse_bar_t, __cdada_map_autogen_dump_bar_t, }; //END map for bar_t (std::map) /*****************************************************************************/ /* END libcdada AUTOGENERATED C++ file */ /*****************************************************************************/ pmacct-1.7.8/src/external_libs/libcdada/examples/map_struct.c0000644000175000017500000000573114354105336023326 0ustar paolopaolo#include #include #include #include #include //Define the key type, with strings to make it fun //Make sure it packed(!) and if possible align to power of 2 typedef struct{ char corridor[20]; char shelf[20]; char item[24]; }__attribute__((packed)) my_key_t; typedef struct{ float price; float percentage_discount; }my_val_t; void trav_print(const cdada_map_t* s, const void* k, void* v, void* opaque){ my_key_t* key = (my_key_t*)k; my_val_t* val = (my_val_t*)v; fprintf(stdout, "\t[corridor: %s, shelf: %s, item: %s] = {%f, %f%%}\n", key->corridor, key->shelf, key->item, val->price, val->percentage_discount); } void print_inventory(cdada_map_t* m){ fprintf(stdout, "Inventory size %u, contents:\n", cdada_map_size(m)); cdada_map_traverse(m, &trav_print, NULL); } int main(int args, char** argv){ my_key_t key; my_val_t* val; void* val_aux; //Avoid alias warnings cdada_map_t* m = cdada_map_create(my_key_t); fprintf(stdout, "Map %s (%u)\n", cdada_map_empty(m)? "is empty" : "has elements", cdada_map_size(m)); //Key must have all bytes initialized(!) memset(&key, 0, sizeof(my_key_t)); //Add inventory Apple MacBook Pro to inventory val = (my_val_t*)malloc(sizeof(my_val_t)); snprintf(key.corridor, 20, "central"); snprintf(key.shelf, 20, "2nd"); snprintf(key.item, 24, "Apple MacBook Pro"); val->price = 1500; val->percentage_discount = 0.0; cdada_map_insert(m, &key, val); print_inventory(m); //Attempt to add the same should yield E_EXISTS val = (my_val_t*)malloc(sizeof(my_val_t)); int rv = cdada_map_insert(m, &key, val); if(rv != CDADA_E_EXISTS){ fprintf(stderr, "libcdada has a bug!\n"); return EXIT_FAILURE; } //Add another item memset(&key, 0, sizeof(my_key_t)); //Let's not leave trailing chars snprintf(key.corridor, 20, "left"); snprintf(key.shelf, 20, "4th"); snprintf(key.item, 24, "Lenovo T440s"); val->price = 1300; val->percentage_discount = 15.0; rv = cdada_map_insert(m, &key, val); if(rv != CDADA_SUCCESS){ fprintf(stderr, "libcdada has a bug!\n"); return EXIT_FAILURE; } print_inventory(m); //Find an element memset(&key, 0, sizeof(my_key_t)); //Let's not leave trailing chars snprintf(key.corridor, 20, "central"); snprintf(key.shelf, 20, "2nd"); snprintf(key.item, 24, "Apple MacBook Pro"); cdada_map_find(m, &key, &val_aux); val = (my_val_t*)val_aux; fprintf(stdout, "Macbook pro price: %f, discount: %f %%\n", val->price, val->percentage_discount); fprintf(stdout, "Map %s (%u)\n", cdada_map_empty(m)? "is empty" : "has elements", cdada_map_size(m)); //Erase MacBook Pro from inventory cdada_map_erase(m, &key); free(val); fprintf(stdout, "Map %s (%u)\n", cdada_map_empty(m)? "is empty" : "has elements", cdada_map_size(m)); //Cleanup while(cdada_map_first(m, &key, &val_aux) == CDADA_SUCCESS){ free(val_aux); cdada_map_erase(m, &key); } //Don't leak cdada_map_destroy(m); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/examples/README.md0000644000175000017500000000160014354105336022247 0ustar paolopaolo`libcdada` examples ------------------- Two simple examples and one advanced are provided: * [bbitmap](bbitmap.c): big bitmap example (bitmap > 64 bits) * [list_u32](list_u32.c): unsigned integer `list` manipulation (equivalent `std::list`) * [map_struct](map_struct.c): `map` with a complex struct (strings) (equivalent to `std::map` * [queue_u32](queue_u32.c): `queue` (FIFO queue) (equivalent to `std::queue`) * [stack_u32](stack_u32.c): `stack` (LIFO queue) (equivalent to `std::stack`) * [str](str.c): string manipulation example * Custom type examples using a combination of custom data structures (`set`, `data`). These are more efficient and don't have size limits: * [custom-gen/my_program_gen](custom-gen/): using C++ code generator `cdada-gen` * [custom-macro/my_program](custom-macro/): using cdada MACROs for code generation pmacct-1.7.8/src/external_libs/libcdada/examples/Makefile.in0000644000175000017500000014232614354105430023043 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = bbitmap$(EXEEXT) list_u32$(EXEEXT) \ map_struct$(EXEEXT) custom_gen$(EXEEXT) custom_macro$(EXEEXT) \ str$(EXEEXT) queue_u32$(EXEEXT) stack_u32$(EXEEXT) subdir = examples ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/config_m4/debug.m4 \ $(top_srcdir)/config_m4/profiling.m4 \ $(top_srcdir)/config_m4/versioning.m4 \ $(top_srcdir)/config_m4/valgrind.m4 \ $(top_srcdir)/config_m4/rdtsc.m4 \ $(top_srcdir)/config_m4/tests.m4 \ $(top_srcdir)/config_m4/examples.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_bbitmap_OBJECTS = bbitmap-bbitmap.$(OBJEXT) bbitmap_OBJECTS = $(am_bbitmap_OBJECTS) bbitmap_DEPENDENCIES = ../src/.libs/libcdada.a AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__dirstamp = $(am__leading_dot)dirstamp am_custom_gen_OBJECTS = \ custom-gen/custom_gen-my_program_gen.$(OBJEXT) \ custom-gen/custom_gen-cdada.$(OBJEXT) custom_gen_OBJECTS = $(am_custom_gen_OBJECTS) custom_gen_DEPENDENCIES = ../src/.libs/libcdada.a am_custom_macro_OBJECTS = \ custom-macro/custom_macro-my_program.$(OBJEXT) \ custom-macro/custom_macro-cdada.$(OBJEXT) custom_macro_OBJECTS = $(am_custom_macro_OBJECTS) custom_macro_DEPENDENCIES = ../src/.libs/libcdada.a am_list_u32_OBJECTS = list_u32-list_u32.$(OBJEXT) list_u32_OBJECTS = $(am_list_u32_OBJECTS) list_u32_DEPENDENCIES = ../src/.libs/libcdada.a am_map_struct_OBJECTS = map_struct-map_struct.$(OBJEXT) map_struct_OBJECTS = $(am_map_struct_OBJECTS) map_struct_DEPENDENCIES = ../src/.libs/libcdada.a am_queue_u32_OBJECTS = queue_u32-queue_u32.$(OBJEXT) queue_u32_OBJECTS = $(am_queue_u32_OBJECTS) queue_u32_DEPENDENCIES = ../src/.libs/libcdada.a am_stack_u32_OBJECTS = stack_u32-stack_u32.$(OBJEXT) stack_u32_OBJECTS = $(am_stack_u32_OBJECTS) stack_u32_DEPENDENCIES = ../src/.libs/libcdada.a am_str_OBJECTS = str-str.$(OBJEXT) str_OBJECTS = $(am_str_OBJECTS) str_DEPENDENCIES = ../src/.libs/libcdada.a AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/bbitmap-bbitmap.Po \ ./$(DEPDIR)/list_u32-list_u32.Po \ ./$(DEPDIR)/map_struct-map_struct.Po \ ./$(DEPDIR)/queue_u32-queue_u32.Po \ ./$(DEPDIR)/stack_u32-stack_u32.Po ./$(DEPDIR)/str-str.Po \ custom-gen/$(DEPDIR)/custom_gen-cdada.Po \ custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po \ custom-macro/$(DEPDIR)/custom_macro-cdada.Po \ custom-macro/$(DEPDIR)/custom_macro-my_program.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(bbitmap_SOURCES) $(custom_gen_SOURCES) \ $(custom_macro_SOURCES) $(list_u32_SOURCES) \ $(map_struct_SOURCES) $(queue_u32_SOURCES) \ $(stack_u32_SOURCES) $(str_SOURCES) DIST_SOURCES = $(bbitmap_SOURCES) $(custom_gen_SOURCES) \ $(custom_macro_SOURCES) $(list_u32_SOURCES) \ $(map_struct_SOURCES) $(queue_u32_SOURCES) \ $(stack_u32_SOURCES) $(str_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = check-valgrind-recursive \ check-valgrind-memcheck-recursive \ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ check-valgrind-sgcheck-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDADA_BRANCH = @CDADA_BRANCH@ CDADA_BUILD = @CDADA_BUILD@ CDADA_DESCRIBE = @CDADA_DESCRIBE@ CDADA_VERSION = @CDADA_VERSION@ CDADA_VERSION_MAJOR = @CDADA_VERSION_MAJOR@ CDADA_VERSION_MINOR = @CDADA_VERSION_MINOR@ CDADA_VERSION_NORMALIZED = @CDADA_VERSION_NORMALIZED@ CDADA_VERSION_PATCH = @CDADA_VERSION_PATCH@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VALGRIND_ENABLED = @VALGRIND_ENABLED@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ ff_git = @ff_git@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ MAINTAINERCLEANFILES = Makefile.in list_u32_SOURCES = list_u32.c list_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ list_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ map_struct_SOURCES = map_struct.c map_struct_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ map_struct_LDADD = ../src/.libs/libcdada.a -lstdc++ custom_gen_SOURCES = custom-gen/my_program_gen.c custom-gen/cdada.cc custom_gen_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ custom_gen_LDADD = ../src/.libs/libcdada.a -lstdc++ custom_macro_SOURCES = custom-macro/my_program.c custom-macro/cdada.cc custom_macro_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ custom_macro_LDADD = ../src/.libs/libcdada.a -lstdc++ str_SOURCES = str.c str_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ str_LDADD = ../src/.libs/libcdada.a -lstdc++ bbitmap_SOURCES = bbitmap.c bbitmap_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ bbitmap_LDADD = ../src/.libs/libcdada.a -lstdc++ queue_u32_SOURCES = queue_u32.c queue_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ queue_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ stack_u32_SOURCES = stack_u32.c stack_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ stack_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign examples/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list bbitmap$(EXEEXT): $(bbitmap_OBJECTS) $(bbitmap_DEPENDENCIES) $(EXTRA_bbitmap_DEPENDENCIES) @rm -f bbitmap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(bbitmap_OBJECTS) $(bbitmap_LDADD) $(LIBS) custom-gen/$(am__dirstamp): @$(MKDIR_P) custom-gen @: > custom-gen/$(am__dirstamp) custom-gen/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) custom-gen/$(DEPDIR) @: > custom-gen/$(DEPDIR)/$(am__dirstamp) custom-gen/custom_gen-my_program_gen.$(OBJEXT): \ custom-gen/$(am__dirstamp) \ custom-gen/$(DEPDIR)/$(am__dirstamp) custom-gen/custom_gen-cdada.$(OBJEXT): custom-gen/$(am__dirstamp) \ custom-gen/$(DEPDIR)/$(am__dirstamp) custom_gen$(EXEEXT): $(custom_gen_OBJECTS) $(custom_gen_DEPENDENCIES) $(EXTRA_custom_gen_DEPENDENCIES) @rm -f custom_gen$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(custom_gen_OBJECTS) $(custom_gen_LDADD) $(LIBS) custom-macro/$(am__dirstamp): @$(MKDIR_P) custom-macro @: > custom-macro/$(am__dirstamp) custom-macro/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) custom-macro/$(DEPDIR) @: > custom-macro/$(DEPDIR)/$(am__dirstamp) custom-macro/custom_macro-my_program.$(OBJEXT): \ custom-macro/$(am__dirstamp) \ custom-macro/$(DEPDIR)/$(am__dirstamp) custom-macro/custom_macro-cdada.$(OBJEXT): \ custom-macro/$(am__dirstamp) \ custom-macro/$(DEPDIR)/$(am__dirstamp) custom_macro$(EXEEXT): $(custom_macro_OBJECTS) $(custom_macro_DEPENDENCIES) $(EXTRA_custom_macro_DEPENDENCIES) @rm -f custom_macro$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(custom_macro_OBJECTS) $(custom_macro_LDADD) $(LIBS) list_u32$(EXEEXT): $(list_u32_OBJECTS) $(list_u32_DEPENDENCIES) $(EXTRA_list_u32_DEPENDENCIES) @rm -f list_u32$(EXEEXT) $(AM_V_CCLD)$(LINK) $(list_u32_OBJECTS) $(list_u32_LDADD) $(LIBS) map_struct$(EXEEXT): $(map_struct_OBJECTS) $(map_struct_DEPENDENCIES) $(EXTRA_map_struct_DEPENDENCIES) @rm -f map_struct$(EXEEXT) $(AM_V_CCLD)$(LINK) $(map_struct_OBJECTS) $(map_struct_LDADD) $(LIBS) queue_u32$(EXEEXT): $(queue_u32_OBJECTS) $(queue_u32_DEPENDENCIES) $(EXTRA_queue_u32_DEPENDENCIES) @rm -f queue_u32$(EXEEXT) $(AM_V_CCLD)$(LINK) $(queue_u32_OBJECTS) $(queue_u32_LDADD) $(LIBS) stack_u32$(EXEEXT): $(stack_u32_OBJECTS) $(stack_u32_DEPENDENCIES) $(EXTRA_stack_u32_DEPENDENCIES) @rm -f stack_u32$(EXEEXT) $(AM_V_CCLD)$(LINK) $(stack_u32_OBJECTS) $(stack_u32_LDADD) $(LIBS) str$(EXEEXT): $(str_OBJECTS) $(str_DEPENDENCIES) $(EXTRA_str_DEPENDENCIES) @rm -f str$(EXEEXT) $(AM_V_CCLD)$(LINK) $(str_OBJECTS) $(str_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f custom-gen/*.$(OBJEXT) -rm -f custom-macro/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bbitmap-bbitmap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list_u32-list_u32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_struct-map_struct.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue_u32-queue_u32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack_u32-stack_u32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-str.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@custom-gen/$(DEPDIR)/custom_gen-cdada.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@custom-macro/$(DEPDIR)/custom_macro-cdada.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@custom-macro/$(DEPDIR)/custom_macro-my_program.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< bbitmap-bbitmap.o: bbitmap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bbitmap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bbitmap-bbitmap.o -MD -MP -MF $(DEPDIR)/bbitmap-bbitmap.Tpo -c -o bbitmap-bbitmap.o `test -f 'bbitmap.c' || echo '$(srcdir)/'`bbitmap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/bbitmap-bbitmap.Tpo $(DEPDIR)/bbitmap-bbitmap.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bbitmap.c' object='bbitmap-bbitmap.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bbitmap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bbitmap-bbitmap.o `test -f 'bbitmap.c' || echo '$(srcdir)/'`bbitmap.c bbitmap-bbitmap.obj: bbitmap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bbitmap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bbitmap-bbitmap.obj -MD -MP -MF $(DEPDIR)/bbitmap-bbitmap.Tpo -c -o bbitmap-bbitmap.obj `if test -f 'bbitmap.c'; then $(CYGPATH_W) 'bbitmap.c'; else $(CYGPATH_W) '$(srcdir)/bbitmap.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/bbitmap-bbitmap.Tpo $(DEPDIR)/bbitmap-bbitmap.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bbitmap.c' object='bbitmap-bbitmap.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bbitmap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bbitmap-bbitmap.obj `if test -f 'bbitmap.c'; then $(CYGPATH_W) 'bbitmap.c'; else $(CYGPATH_W) '$(srcdir)/bbitmap.c'; fi` custom-gen/custom_gen-my_program_gen.o: custom-gen/my_program_gen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom-gen/custom_gen-my_program_gen.o -MD -MP -MF custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Tpo -c -o custom-gen/custom_gen-my_program_gen.o `test -f 'custom-gen/my_program_gen.c' || echo '$(srcdir)/'`custom-gen/my_program_gen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Tpo custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='custom-gen/my_program_gen.c' object='custom-gen/custom_gen-my_program_gen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom-gen/custom_gen-my_program_gen.o `test -f 'custom-gen/my_program_gen.c' || echo '$(srcdir)/'`custom-gen/my_program_gen.c custom-gen/custom_gen-my_program_gen.obj: custom-gen/my_program_gen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom-gen/custom_gen-my_program_gen.obj -MD -MP -MF custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Tpo -c -o custom-gen/custom_gen-my_program_gen.obj `if test -f 'custom-gen/my_program_gen.c'; then $(CYGPATH_W) 'custom-gen/my_program_gen.c'; else $(CYGPATH_W) '$(srcdir)/custom-gen/my_program_gen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Tpo custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='custom-gen/my_program_gen.c' object='custom-gen/custom_gen-my_program_gen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom-gen/custom_gen-my_program_gen.obj `if test -f 'custom-gen/my_program_gen.c'; then $(CYGPATH_W) 'custom-gen/my_program_gen.c'; else $(CYGPATH_W) '$(srcdir)/custom-gen/my_program_gen.c'; fi` custom-macro/custom_macro-my_program.o: custom-macro/my_program.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom-macro/custom_macro-my_program.o -MD -MP -MF custom-macro/$(DEPDIR)/custom_macro-my_program.Tpo -c -o custom-macro/custom_macro-my_program.o `test -f 'custom-macro/my_program.c' || echo '$(srcdir)/'`custom-macro/my_program.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) custom-macro/$(DEPDIR)/custom_macro-my_program.Tpo custom-macro/$(DEPDIR)/custom_macro-my_program.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='custom-macro/my_program.c' object='custom-macro/custom_macro-my_program.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom-macro/custom_macro-my_program.o `test -f 'custom-macro/my_program.c' || echo '$(srcdir)/'`custom-macro/my_program.c custom-macro/custom_macro-my_program.obj: custom-macro/my_program.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom-macro/custom_macro-my_program.obj -MD -MP -MF custom-macro/$(DEPDIR)/custom_macro-my_program.Tpo -c -o custom-macro/custom_macro-my_program.obj `if test -f 'custom-macro/my_program.c'; then $(CYGPATH_W) 'custom-macro/my_program.c'; else $(CYGPATH_W) '$(srcdir)/custom-macro/my_program.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) custom-macro/$(DEPDIR)/custom_macro-my_program.Tpo custom-macro/$(DEPDIR)/custom_macro-my_program.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='custom-macro/my_program.c' object='custom-macro/custom_macro-my_program.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom-macro/custom_macro-my_program.obj `if test -f 'custom-macro/my_program.c'; then $(CYGPATH_W) 'custom-macro/my_program.c'; else $(CYGPATH_W) '$(srcdir)/custom-macro/my_program.c'; fi` list_u32-list_u32.o: list_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(list_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT list_u32-list_u32.o -MD -MP -MF $(DEPDIR)/list_u32-list_u32.Tpo -c -o list_u32-list_u32.o `test -f 'list_u32.c' || echo '$(srcdir)/'`list_u32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/list_u32-list_u32.Tpo $(DEPDIR)/list_u32-list_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='list_u32.c' object='list_u32-list_u32.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(list_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o list_u32-list_u32.o `test -f 'list_u32.c' || echo '$(srcdir)/'`list_u32.c list_u32-list_u32.obj: list_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(list_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT list_u32-list_u32.obj -MD -MP -MF $(DEPDIR)/list_u32-list_u32.Tpo -c -o list_u32-list_u32.obj `if test -f 'list_u32.c'; then $(CYGPATH_W) 'list_u32.c'; else $(CYGPATH_W) '$(srcdir)/list_u32.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/list_u32-list_u32.Tpo $(DEPDIR)/list_u32-list_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='list_u32.c' object='list_u32-list_u32.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(list_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o list_u32-list_u32.obj `if test -f 'list_u32.c'; then $(CYGPATH_W) 'list_u32.c'; else $(CYGPATH_W) '$(srcdir)/list_u32.c'; fi` map_struct-map_struct.o: map_struct.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(map_struct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT map_struct-map_struct.o -MD -MP -MF $(DEPDIR)/map_struct-map_struct.Tpo -c -o map_struct-map_struct.o `test -f 'map_struct.c' || echo '$(srcdir)/'`map_struct.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/map_struct-map_struct.Tpo $(DEPDIR)/map_struct-map_struct.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map_struct.c' object='map_struct-map_struct.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(map_struct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o map_struct-map_struct.o `test -f 'map_struct.c' || echo '$(srcdir)/'`map_struct.c map_struct-map_struct.obj: map_struct.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(map_struct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT map_struct-map_struct.obj -MD -MP -MF $(DEPDIR)/map_struct-map_struct.Tpo -c -o map_struct-map_struct.obj `if test -f 'map_struct.c'; then $(CYGPATH_W) 'map_struct.c'; else $(CYGPATH_W) '$(srcdir)/map_struct.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/map_struct-map_struct.Tpo $(DEPDIR)/map_struct-map_struct.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map_struct.c' object='map_struct-map_struct.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(map_struct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o map_struct-map_struct.obj `if test -f 'map_struct.c'; then $(CYGPATH_W) 'map_struct.c'; else $(CYGPATH_W) '$(srcdir)/map_struct.c'; fi` queue_u32-queue_u32.o: queue_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(queue_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT queue_u32-queue_u32.o -MD -MP -MF $(DEPDIR)/queue_u32-queue_u32.Tpo -c -o queue_u32-queue_u32.o `test -f 'queue_u32.c' || echo '$(srcdir)/'`queue_u32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/queue_u32-queue_u32.Tpo $(DEPDIR)/queue_u32-queue_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue_u32.c' object='queue_u32-queue_u32.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(queue_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o queue_u32-queue_u32.o `test -f 'queue_u32.c' || echo '$(srcdir)/'`queue_u32.c queue_u32-queue_u32.obj: queue_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(queue_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT queue_u32-queue_u32.obj -MD -MP -MF $(DEPDIR)/queue_u32-queue_u32.Tpo -c -o queue_u32-queue_u32.obj `if test -f 'queue_u32.c'; then $(CYGPATH_W) 'queue_u32.c'; else $(CYGPATH_W) '$(srcdir)/queue_u32.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/queue_u32-queue_u32.Tpo $(DEPDIR)/queue_u32-queue_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue_u32.c' object='queue_u32-queue_u32.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(queue_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o queue_u32-queue_u32.obj `if test -f 'queue_u32.c'; then $(CYGPATH_W) 'queue_u32.c'; else $(CYGPATH_W) '$(srcdir)/queue_u32.c'; fi` stack_u32-stack_u32.o: stack_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stack_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stack_u32-stack_u32.o -MD -MP -MF $(DEPDIR)/stack_u32-stack_u32.Tpo -c -o stack_u32-stack_u32.o `test -f 'stack_u32.c' || echo '$(srcdir)/'`stack_u32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stack_u32-stack_u32.Tpo $(DEPDIR)/stack_u32-stack_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stack_u32.c' object='stack_u32-stack_u32.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stack_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stack_u32-stack_u32.o `test -f 'stack_u32.c' || echo '$(srcdir)/'`stack_u32.c stack_u32-stack_u32.obj: stack_u32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stack_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stack_u32-stack_u32.obj -MD -MP -MF $(DEPDIR)/stack_u32-stack_u32.Tpo -c -o stack_u32-stack_u32.obj `if test -f 'stack_u32.c'; then $(CYGPATH_W) 'stack_u32.c'; else $(CYGPATH_W) '$(srcdir)/stack_u32.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stack_u32-stack_u32.Tpo $(DEPDIR)/stack_u32-stack_u32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stack_u32.c' object='stack_u32-stack_u32.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stack_u32_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stack_u32-stack_u32.obj `if test -f 'stack_u32.c'; then $(CYGPATH_W) 'stack_u32.c'; else $(CYGPATH_W) '$(srcdir)/stack_u32.c'; fi` str-str.o: str.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(str_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT str-str.o -MD -MP -MF $(DEPDIR)/str-str.Tpo -c -o str-str.o `test -f 'str.c' || echo '$(srcdir)/'`str.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/str-str.Tpo $(DEPDIR)/str-str.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='str.c' object='str-str.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(str_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o str-str.o `test -f 'str.c' || echo '$(srcdir)/'`str.c str-str.obj: str.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(str_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT str-str.obj -MD -MP -MF $(DEPDIR)/str-str.Tpo -c -o str-str.obj `if test -f 'str.c'; then $(CYGPATH_W) 'str.c'; else $(CYGPATH_W) '$(srcdir)/str.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/str-str.Tpo $(DEPDIR)/str-str.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='str.c' object='str-str.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(str_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o str-str.obj `if test -f 'str.c'; then $(CYGPATH_W) 'str.c'; else $(CYGPATH_W) '$(srcdir)/str.c'; fi` .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< custom-gen/custom_gen-cdada.o: custom-gen/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT custom-gen/custom_gen-cdada.o -MD -MP -MF custom-gen/$(DEPDIR)/custom_gen-cdada.Tpo -c -o custom-gen/custom_gen-cdada.o `test -f 'custom-gen/cdada.cc' || echo '$(srcdir)/'`custom-gen/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) custom-gen/$(DEPDIR)/custom_gen-cdada.Tpo custom-gen/$(DEPDIR)/custom_gen-cdada.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='custom-gen/cdada.cc' object='custom-gen/custom_gen-cdada.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o custom-gen/custom_gen-cdada.o `test -f 'custom-gen/cdada.cc' || echo '$(srcdir)/'`custom-gen/cdada.cc custom-gen/custom_gen-cdada.obj: custom-gen/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT custom-gen/custom_gen-cdada.obj -MD -MP -MF custom-gen/$(DEPDIR)/custom_gen-cdada.Tpo -c -o custom-gen/custom_gen-cdada.obj `if test -f 'custom-gen/cdada.cc'; then $(CYGPATH_W) 'custom-gen/cdada.cc'; else $(CYGPATH_W) '$(srcdir)/custom-gen/cdada.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) custom-gen/$(DEPDIR)/custom_gen-cdada.Tpo custom-gen/$(DEPDIR)/custom_gen-cdada.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='custom-gen/cdada.cc' object='custom-gen/custom_gen-cdada.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_gen_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o custom-gen/custom_gen-cdada.obj `if test -f 'custom-gen/cdada.cc'; then $(CYGPATH_W) 'custom-gen/cdada.cc'; else $(CYGPATH_W) '$(srcdir)/custom-gen/cdada.cc'; fi` custom-macro/custom_macro-cdada.o: custom-macro/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT custom-macro/custom_macro-cdada.o -MD -MP -MF custom-macro/$(DEPDIR)/custom_macro-cdada.Tpo -c -o custom-macro/custom_macro-cdada.o `test -f 'custom-macro/cdada.cc' || echo '$(srcdir)/'`custom-macro/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) custom-macro/$(DEPDIR)/custom_macro-cdada.Tpo custom-macro/$(DEPDIR)/custom_macro-cdada.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='custom-macro/cdada.cc' object='custom-macro/custom_macro-cdada.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o custom-macro/custom_macro-cdada.o `test -f 'custom-macro/cdada.cc' || echo '$(srcdir)/'`custom-macro/cdada.cc custom-macro/custom_macro-cdada.obj: custom-macro/cdada.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT custom-macro/custom_macro-cdada.obj -MD -MP -MF custom-macro/$(DEPDIR)/custom_macro-cdada.Tpo -c -o custom-macro/custom_macro-cdada.obj `if test -f 'custom-macro/cdada.cc'; then $(CYGPATH_W) 'custom-macro/cdada.cc'; else $(CYGPATH_W) '$(srcdir)/custom-macro/cdada.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) custom-macro/$(DEPDIR)/custom_macro-cdada.Tpo custom-macro/$(DEPDIR)/custom_macro-cdada.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='custom-macro/cdada.cc' object='custom-macro/custom_macro-cdada.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(custom_macro_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o custom-macro/custom_macro-cdada.obj `if test -f 'custom-macro/cdada.cc'; then $(CYGPATH_W) 'custom-macro/cdada.cc'; else $(CYGPATH_W) '$(srcdir)/custom-macro/cdada.cc'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs check-valgrind-local: check-valgrind-memcheck-local: check-valgrind-helgrind-local: check-valgrind-drd-local: check-valgrind-sgcheck-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f custom-gen/$(DEPDIR)/$(am__dirstamp) -rm -f custom-gen/$(am__dirstamp) -rm -f custom-macro/$(DEPDIR)/$(am__dirstamp) -rm -f custom-macro/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) check-valgrind: check-valgrind-am check-valgrind-am: check-valgrind-local check-valgrind-drd: check-valgrind-drd-am check-valgrind-drd-am: check-valgrind-drd-local check-valgrind-helgrind: check-valgrind-helgrind-am check-valgrind-helgrind-am: check-valgrind-helgrind-local check-valgrind-memcheck: check-valgrind-memcheck-am check-valgrind-memcheck-am: check-valgrind-memcheck-local check-valgrind-sgcheck: check-valgrind-sgcheck-am check-valgrind-sgcheck-am: check-valgrind-sgcheck-local clean: clean-am clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/bbitmap-bbitmap.Po -rm -f ./$(DEPDIR)/list_u32-list_u32.Po -rm -f ./$(DEPDIR)/map_struct-map_struct.Po -rm -f ./$(DEPDIR)/queue_u32-queue_u32.Po -rm -f ./$(DEPDIR)/stack_u32-stack_u32.Po -rm -f ./$(DEPDIR)/str-str.Po -rm -f custom-gen/$(DEPDIR)/custom_gen-cdada.Po -rm -f custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po -rm -f custom-macro/$(DEPDIR)/custom_macro-cdada.Po -rm -f custom-macro/$(DEPDIR)/custom_macro-my_program.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/bbitmap-bbitmap.Po -rm -f ./$(DEPDIR)/list_u32-list_u32.Po -rm -f ./$(DEPDIR)/map_struct-map_struct.Po -rm -f ./$(DEPDIR)/queue_u32-queue_u32.Po -rm -f ./$(DEPDIR)/stack_u32-stack_u32.Po -rm -f ./$(DEPDIR)/str-str.Po -rm -f custom-gen/$(DEPDIR)/custom_gen-cdada.Po -rm -f custom-gen/$(DEPDIR)/custom_gen-my_program_gen.Po -rm -f custom-macro/$(DEPDIR)/custom_macro-cdada.Po -rm -f custom-macro/$(DEPDIR)/custom_macro-my_program.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \ check-valgrind-am check-valgrind-drd-am \ check-valgrind-drd-local check-valgrind-helgrind-am \ check-valgrind-helgrind-local check-valgrind-local \ check-valgrind-memcheck-am check-valgrind-memcheck-local \ check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/examples/Makefile.am0000644000175000017500000000310314354105336023024 0ustar paolopaoloMAINTAINERCLEANFILES = Makefile.in noinst_PROGRAMS = bbitmap \ list_u32 \ map_struct \ custom_gen \ custom_macro \ str \ queue_u32 \ stack_u32 list_u32_SOURCES = list_u32.c list_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ list_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ map_struct_SOURCES = map_struct.c map_struct_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ map_struct_LDADD = ../src/.libs/libcdada.a -lstdc++ custom_gen_SOURCES = custom-gen/my_program_gen.c custom-gen/cdada.cc custom_gen_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ custom_gen_LDADD = ../src/.libs/libcdada.a -lstdc++ custom_macro_SOURCES = custom-macro/my_program.c custom-macro/cdada.cc custom_macro_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ custom_macro_LDADD = ../src/.libs/libcdada.a -lstdc++ str_SOURCES = str.c str_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ str_LDADD = ../src/.libs/libcdada.a -lstdc++ bbitmap_SOURCES = bbitmap.c bbitmap_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ bbitmap_LDADD = ../src/.libs/libcdada.a -lstdc++ queue_u32_SOURCES = queue_u32.c queue_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ queue_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ stack_u32_SOURCES = stack_u32.c stack_u32_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ stack_u32_LDADD = ../src/.libs/libcdada.a -lstdc++ pmacct-1.7.8/src/external_libs/libcdada/examples/str.c0000644000175000017500000000330714354105336021752 0ustar paolopaolo#include #include #include #include #include #include void trav(const cdada_str_t* str, const char it, uint32_t pos, void* opaque){ fprintf(stdout, "%u: %c\n", pos, it); } int main(int args, char** argv){ fprintf(stdout, "Running libcdada: %s, MAJOR: %s, MINOR: %s, PATCH: %s. Build '%s' \n", cdada_get_ver(), cdada_get_ver_maj(), cdada_get_ver_min(), cdada_get_ver_patch(), cdada_get_build()); cdada_str_t* s = cdada_str_create("One string"); fprintf(stdout, "%s\n", cdada_str(s)); //Clear cdada_str_clear(s); fprintf(stdout, "%s\n", cdada_str(s)); //Reset cdada_str_set(s, "This is a test"); fprintf(stdout, "%s\n", cdada_str(s)); cdada_str_append(s, " simple string"); cdada_str_lower(s); cdada_str_replace_all(s, "test ", ""); fprintf(stdout, "%s\n", cdada_str(s)); //"THIS IS A SIMPLE STRING" cdada_str_upper(s); fprintf(stdout, "%s\n", cdada_str(s)); //Insert in a position "THIS IS A _VERY_, _VERY_ SIMPLE STRING" cdada_str_insert(s, 10, "_VERY_, _VERY_ "); fprintf(stdout, "%s\n", cdada_str(s)); //Replace first occurrence from char 11 cdada_str_replace(s, "_VERY_ ", "", 16); fprintf(stdout, "%s\n", cdada_str(s)); //Remove all "," //Insert in a position "THIS IS A _VERY_ SIMPLE STRING" cdada_str_replace_all(s, ",", ""); fprintf(stdout, "%s\n", cdada_str(s)); //Trim "THIS IS A _VERY_ SIMPLE" cdada_str_trim(s, 6); fprintf(stdout, "%s\n", cdada_str(s)); cdada_str_append(s, "SENTENCE"); fprintf(stdout, "%s\n", cdada_str(s)); //Traverse char by char and print char\n cdada_str_traverse(s, trav, NULL); //Don't leak cdada_str_destroy(s); return EXIT_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/Makefile.am0000644000175000017500000000061114354105366021212 0ustar paolopaoloMAINTAINERCLEANFILES = \ $(top_srcdir)/aclocal.m4 \ $(top_srcdir)/configure \ $(top_srcdir)/Makefile.in SUBDIRS = include src tools if WITH_TESTS SUBDIRS += endif if WITH_EXAMPLES SUBDIRS += examples endif #Could be improved.. .PHONY: doc doc: @cd doc/ && make doc install-exec-hook: uninstall-hook: maintainer-clean-local: rm -rf $(top_srcdir)/m4 rm -rf $(top_srcdir)/build-aux pmacct-1.7.8/src/external_libs/libcdada/LICENSE0000644000175000017500000000242114354105336020161 0ustar paolopaoloCopyright (c) 2020, Marc Sune Clos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. pmacct-1.7.8/src/external_libs/libcdada/src/0000755000175000017500000000000014354105430017737 5ustar paolopaolopmacct-1.7.8/src/external_libs/libcdada/src/set.cc0000644000175000017500000003750514354105336021060 0ustar paolopaolo#include "cdada/set.h" #include "cdada/__common_internal.h" #include "cdada/__set_internal.h" #include #include using namespace std; cdada_set_t* __cdada_set_create(const uint16_t key_size, __cdada_set_ops_t* ops){ __cdada_set_int_t* m = NULL; if(unlikely(key_size == 0)) return m; m = (__cdada_set_int_t*)malloc(sizeof(__cdada_set_int_t)); memset(m, 0, sizeof(__cdada_set_int_t)); m->magic_num = CDADA_MAGIC; m->user_key_len = key_size; try{ //Custom type if(ops){ m->key_len = m->user_key_len = key_size; m->ops = ops; (*m->ops->create)(m); return m; } //Regular if(key_size == 1){ m->set.u8 = new set(); m->key_len = 1; }else if(key_size == 2){ m->set.u16 = new set(); m->key_len = 2; }else if(key_size > 2 && key_size <= 4){ m->set.u32 = new set(); m->key_len = 4; }else if(key_size > 4 && key_size <= 8){ m->set.u64 = new set(); m->key_len = 8; }else if(key_size > 8 && key_size <= 16){ m->set.u128 = new set(); m->key_len = 16; }else if(key_size > 16 && key_size <= 32){ m->set.u256 = new set(); m->key_len = 32; }else if(key_size > 32 && key_size <= 64){ m->set.u512 = new set(); m->key_len = 64; }else if(key_size > 64 && key_size <= 128){ m->set.u1024 = new set(); m->key_len = 128; }else if(key_size > 128 && key_size <= 256){ m->set.u2048 = new set(); m->key_len = 256; }else{ //Unsupported; use custom type goto ROLLBACK; } }catch(bad_alloc& e){ goto ROLLBACK; }catch(...){ CDADA_ASSERT(0); goto ROLLBACK; } return m; ROLLBACK: free(m); return NULL; } /** * Destroy a set structure */ int cdada_set_destroy(cdada_set_t* set){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); try{ if(m->ops){ (*m->ops->destroy)(m); }else{ switch(m->key_len){ case 1: delete m->set.u8; break; case 2: delete m->set.u16; break; case 4: delete m->set.u32; break; case 8: delete m->set.u64; break; case 16: delete m->set.u128; break; case 32: delete m->set.u256; break; case 64: delete m->set.u512; break; case 128: delete m->set.u1024; break; case 256: delete m->set.u2048; break; default: CDADA_ASSERT(0); break; } } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } m->magic_num = 0x0; free(m); return CDADA_SUCCESS; } int cdada_set_clear(cdada_set_t* set){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: m->set.u8->clear(); break; case 2: m->set.u16->clear(); break; case 4: m->set.u32->clear(); break; case 8: m->set.u64->clear(); break; case 16: m->set.u128->clear(); break; case 32: m->set.u256->clear(); break; case 64: m->set.u512->clear(); break; case 128: m->set.u1024->clear(); break; case 256: m->set.u2048->clear(); break; case 0: (*m->ops->clear)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } bool cdada_set_empty(const cdada_set_t* set){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return false; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return m->set.u8->empty(); case 2: return m->set.u16->empty(); case 4: return m->set.u32->empty(); case 8: return m->set.u64->empty(); case 16: return m->set.u128->empty(); case 32: return m->set.u256->empty(); case 64: return m->set.u512->empty(); case 128: return m->set.u1024->empty(); case 256: return m->set.u2048->empty(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->empty)(m); default: CDADA_ASSERT(0); return false; } }catch(...){ CDADA_ASSERT(0); return false; } return false; } uint32_t cdada_set_size(const cdada_set_t* set){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return 0; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return m->set.u8->size(); case 2: return m->set.u16->size(); case 4: return m->set.u32->size(); case 8: return m->set.u64->size(); case 16: return m->set.u128->size(); case 32: return m->set.u256->size(); case 64: return m->set.u512->size(); case 128: return m->set.u1024->size(); case 256: return m->set.u2048->size(); case 0: return (*m->ops->size)(m); default: CDADA_ASSERT(0); break; } }catch(...){ CDADA_ASSERT(0); return 0; } return 0; } int cdada_set_insert(cdada_set_t* set, const void* key){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); if(unlikely(!key)) return CDADA_E_INVALID; //NOTE: we don't want std::set insert "replace semantics", so we return //E_EXISTS if key is present in the set try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_set_insert_u(m, m->set.u8, key); case 2: return cdada_set_insert_u(m, m->set.u16, key); case 4: return cdada_set_insert_u(m, m->set.u32, key); case 8: return cdada_set_insert_u(m, m->set.u64, key); case 16: return cdada_set_insert_u(m, m->set.u128, key); case 32: return cdada_set_insert_u(m, m->set.u256, key); case 64: return cdada_set_insert_u(m, m->set.u512, key); case 128: return cdada_set_insert_u(m, m->set.u1024, key); case 256: return cdada_set_insert_u(m, m->set.u2048, key); case 0: return (*m->ops->insert)(m, key); default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_set_erase(cdada_set_t* set, const void* key){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); if(unlikely(!key)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_set_erase_u(m, m->set.u8, key); case 2: return cdada_set_erase_u(m, m->set.u16, key); case 4: return cdada_set_erase_u(m, m->set.u32, key); case 8: return cdada_set_erase_u(m, m->set.u64, key); case 16: return cdada_set_erase_u(m, m->set.u128, key); break; case 32: return cdada_set_erase_u(m, m->set.u256, key); case 64: return cdada_set_erase_u(m, m->set.u512, key); case 128: return cdada_set_erase_u(m, m->set.u1024, key); case 256: return cdada_set_erase_u(m, m->set.u2048, key); case 0: return (*m->ops->erase)(m, key); default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } bool cdada_set_find(const cdada_set_t* set, const void* key){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; if(unlikely(!m || m->magic_num != CDADA_MAGIC || !key)) return false; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_set_find_u(m, m->set.u8, key); case 2: return cdada_set_find_u(m, m->set.u16, key); case 4: return cdada_set_find_u(m, m->set.u32, key); case 8: return cdada_set_find_u(m, m->set.u64, key); case 16: return cdada_set_find_u(m, m->set.u128, key); case 32: return cdada_set_find_u(m, m->set.u256, key); case 64: return cdada_set_find_u(m, m->set.u512, key); case 128: return cdada_set_find_u(m, m->set.u1024, key); case 256: return cdada_set_find_u(m, m->set.u2048, key); case 0: return (*m->ops->find)(m, key); default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){} CDADA_ASSERT(0); return false; } static int __cdada_set_first_last(const cdada_set_t* set, bool first, void* key){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; if(unlikely(!m || m->magic_num != CDADA_MAGIC || !key)) return false; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_set_first_last_u(m, m->set.u8, first, key); case 2: return cdada_set_first_last_u(m, m->set.u16, first, key); case 4: return cdada_set_first_last_u(m, m->set.u32, first, key); case 8: return cdada_set_first_last_u(m, m->set.u64, first, key); case 16: return cdada_set_first_last_u(m, m->set.u128, first, key); case 32: return cdada_set_first_last_u(m, m->set.u256, first, key); case 64: return cdada_set_first_last_u(m, m->set.u512, first, key); case 128: return cdada_set_first_last_u(m, m->set.u1024, first, key); case 256: return cdada_set_first_last_u(m, m->set.u2048, first, key); case 0: return (*m->ops->first_last)(m, first, key); default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){} CDADA_ASSERT(0); return false; } int cdada_set_first(const cdada_set_t* set, void* key){ return __cdada_set_first_last(set, true, key); } int cdada_set_last(const cdada_set_t* set, void* key){ return __cdada_set_first_last(set, false, key); } int cdada_set_traverse(const cdada_set_t* set, cdada_set_it f, void* opaque){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_set_traverse_u(m, m->set.u8, f, opaque); break; case 2: cdada_set_traverse_u(m, m->set.u16, f, opaque); break; case 4: cdada_set_traverse_u(m, m->set.u32, f, opaque); break; case 8: cdada_set_traverse_u(m, m->set.u64, f, opaque); break; case 16: cdada_set_traverse_u(m, m->set.u128, f, opaque); break; case 32: cdada_set_traverse_u(m, m->set.u256, f, opaque); break; case 64: cdada_set_traverse_u(m, m->set.u512, f, opaque); break; case 128: cdada_set_traverse_u(m, m->set.u1024, f, opaque); break; case 256: cdada_set_traverse_u(m, m->set.u2048, f, opaque); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->traverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_set_rtraverse(const cdada_set_t* set, cdada_set_it f, void* opaque){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_set_rtraverse_u(m, m->set.u8, f, opaque); break; case 2: cdada_set_rtraverse_u(m, m->set.u16, f, opaque); break; case 4: cdada_set_rtraverse_u(m, m->set.u32, f, opaque); break; case 8: cdada_set_rtraverse_u(m, m->set.u64, f, opaque); break; case 16: cdada_set_rtraverse_u(m, m->set.u128, f, opaque); break; case 32: cdada_set_rtraverse_u(m, m->set.u256, f, opaque); break; case 64: cdada_set_rtraverse_u(m, m->set.u512, f, opaque); break; case 128: cdada_set_rtraverse_u(m, m->set.u1024, f, opaque); break; case 256: cdada_set_rtraverse_u(m, m->set.u2048, f, opaque); break; case 0: (*m->ops->rtraverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_set_dump(cdada_set_t* set, uint32_t size, char* buffer, uint32_t* size_used){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); if(!size_used || (buffer&&size ==0)) return CDADA_E_INVALID; try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_set_dump_u(m, m->set.u8, ss); break; case 2: cdada_set_dump_u(m, m->set.u16, ss); break; case 4: cdada_set_dump_u(m, m->set.u32, ss); break; case 8: cdada_set_dump_u(m, m->set.u64, ss); break; case 16: cdada_set_dump_u(m, m->set.u128, ss); break; case 32: cdada_set_dump_u(m, m->set.u256, ss); break; case 64: cdada_set_dump_u(m, m->set.u512, ss); break; case 128: cdada_set_dump_u(m, m->set.u1024, ss); break; case 256: cdada_set_dump_u(m, m->set.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}"; *size_used = ss.str().length()+1; if(!buffer) return CDADA_SUCCESS; snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_set_print(cdada_set_t* set, FILE *stream){ __cdada_set_int_t* m = (__cdada_set_int_t*)set; CDADA_CHECK_MAGIC(m); try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_set_dump_u(m, m->set.u8, ss); break; case 2: cdada_set_dump_u(m, m->set.u16, ss); break; case 4: cdada_set_dump_u(m, m->set.u32, ss); break; case 8: cdada_set_dump_u(m, m->set.u64, ss); break; case 16: cdada_set_dump_u(m, m->set.u128, ss); break; case 32: cdada_set_dump_u(m, m->set.u256, ss); break; case 64: cdada_set_dump_u(m, m->set.u512, ss); break; case 128: cdada_set_dump_u(m, m->set.u1024, ss); break; case 256: cdada_set_dump_u(m, m->set.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}\n"; fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/utils.c0000644000175000017500000000123314354105336021247 0ustar paolopaolo#include "cdada/utils.h" #include "cdada/version.h" static const char* cdada_err_str[CDADA_E_COUNT] = { "Success", "Unknown error", "Invalid input", "Not found", "Element exists", "Out of memory", "Feature unsupported", "Empty", "Incomplete" }; const char* cdada_strerr(int err){ return err >= CDADA_E_COUNT? "Invalid code" : cdada_err_str[err]; } const char* cdada_get_ver(){ return CDADA_VERSION; } const char* cdada_get_ver_maj(){ return CDADA_VERSION_MAJOR; } const char* cdada_get_ver_min(){ return CDADA_VERSION_MINOR; } const char* cdada_get_ver_patch(){ return CDADA_VERSION_PATCH; } const char* cdada_get_build(){ return CDADA_BUILD; } pmacct-1.7.8/src/external_libs/libcdada/src/map.cc0000644000175000017500000004146514354105336021042 0ustar paolopaolo#include "cdada/map.h" #include "cdada/__common_internal.h" #include "cdada/__map_internal.h" #include #include using namespace std; cdada_map_t* __cdada_map_create(const uint16_t key_size, __cdada_map_ops_t* ops){ __cdada_map_int_t* m = NULL; if(unlikely(key_size == 0)) return m; m = (__cdada_map_int_t*)malloc(sizeof(__cdada_map_int_t)); memset(m, 0, sizeof(__cdada_map_int_t)); m->magic_num = CDADA_MAGIC; m->user_key_len = key_size; try{ //Custom type if(ops){ m->key_len = m->user_key_len = key_size; m->ops = ops; (*m->ops->create)(m); return m; } if(key_size == 1){ m->map.u8 = new map(); m->key_len = 1; }else if(key_size == 2){ m->map.u16 = new map(); m->key_len = 2; }else if(key_size > 2 && key_size <= 4){ m->map.u32 = new map(); m->key_len = 4; }else if(key_size > 4 && key_size <= 8){ m->map.u64 = new map(); m->key_len = 8; }else if(key_size > 8 && key_size <= 16){ m->map.u128 = new map(); m->key_len = 16; }else if(key_size > 16 && key_size <= 32){ m->map.u256 = new map(); m->key_len = 32; }else if(key_size > 32 && key_size <= 64){ m->map.u512 = new map(); m->key_len = 64; }else if(key_size > 64 && key_size <= 128){ m->map.u1024 = new map(); m->key_len = 128; }else if(key_size > 128 && key_size <= 256){ m->map.u2048 = new map(); m->key_len = 256; }else{ goto ROLLBACK; } }catch(bad_alloc& e){ goto ROLLBACK; }catch(...){ CDADA_ASSERT(0); goto ROLLBACK; } return m; ROLLBACK: free(m); return NULL; } /** * Destroy a map structure */ int cdada_map_destroy(cdada_map_t* map){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: delete m->map.u8; break; case 2: delete m->map.u16; break; case 4: delete m->map.u32; break; case 8: delete m->map.u64; break; case 16: delete m->map.u128; break; case 32: delete m->map.u256; break; case 64: delete m->map.u512; break; case 128: delete m->map.u1024; break; case 256: delete m->map.u2048; break; case 0: CDADA_ASSERT(m->ops); (*m->ops->destroy)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } m->magic_num = 0x0; free(m); return CDADA_SUCCESS; } int cdada_map_clear(cdada_map_t* map){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: m->map.u8->clear(); break; case 2: m->map.u16->clear(); break; case 4: m->map.u32->clear(); break; case 8: m->map.u64->clear(); break; case 16: m->map.u128->clear(); break; case 32: m->map.u256->clear(); break; case 64: m->map.u512->clear(); break; case 128: m->map.u1024->clear(); break; case 256: m->map.u2048->clear(); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->clear)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } bool cdada_map_empty(const cdada_map_t* map){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return false; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return m->map.u8->empty(); case 2: return m->map.u16->empty(); case 4: return m->map.u32->empty(); case 8: return m->map.u64->empty(); case 16: return m->map.u128->empty(); case 32: return m->map.u256->empty(); case 64: return m->map.u512->empty(); case 128: return m->map.u1024->empty(); case 256: return m->map.u2048->empty(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->empty)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return false; } uint32_t cdada_map_size(const cdada_map_t* map){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return 0; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return m->map.u8->size(); case 2: return m->map.u16->size(); case 4: return m->map.u32->size(); case 8: return m->map.u64->size(); case 16: return m->map.u128->size(); case 32: return m->map.u256->size(); case 64: return m->map.u512->size(); case 128: return m->map.u1024->size(); case 256: return m->map.u2048->size(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->size)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return 0; } int _cdada_map_insert(cdada_map_t* map, const void* key, void* val, const bool replace){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!key || !val)) return CDADA_E_INVALID; //NOTE: we don't want std::map insert "replace semantics", so we return //E_EXISTS if key is present in the map try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_map_insert_u(m, m->map.u8, key, val, replace); case 2: return cdada_map_insert_u(m, m->map.u16, key, val, replace); case 4: return cdada_map_insert_u(m, m->map.u32, key, val, replace); case 8: return cdada_map_insert_u(m, m->map.u64, key, val, replace); case 16: return cdada_map_insert_u(m, m->map.u128, key, val, replace); case 32: return cdada_map_insert_u(m, m->map.u256, key, val, replace); case 64: return cdada_map_insert_u(m, m->map.u512, key, val, replace); case 128: return cdada_map_insert_u(m, m->map.u1024, key, val, replace); case 256: return cdada_map_insert_u(m, m->map.u2048, key, val, replace); case 0: CDADA_ASSERT(m->ops); return (*m->ops->insert)(m, key, val, replace); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_map_insert(cdada_map_t* map, const void* key, void* val){ return _cdada_map_insert(map, key, val, false); } int cdada_map_insert_replace(cdada_map_t* map, const void* key, void* val){ return _cdada_map_insert(map, key, val, true); } int cdada_map_erase(cdada_map_t* map, const void* key){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!key)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_map_erase_u(m, m->map.u8, key); case 2: return cdada_map_erase_u(m, m->map.u16, key); case 4: return cdada_map_erase_u(m, m->map.u32, key); case 8: return cdada_map_erase_u(m, m->map.u64, key); case 16: return cdada_map_erase_u(m, m->map.u128, key); case 32: return cdada_map_erase_u(m, m->map.u256, key); case 64: return cdada_map_erase_u(m, m->map.u512, key); case 128: return cdada_map_erase_u(m, m->map.u1024, key); case 256: return cdada_map_erase_u(m, m->map.u2048, key); case 0: CDADA_ASSERT(m->ops); return (*m->ops->erase)(m, key); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_map_find(const cdada_map_t* map, const void* key, void** val){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!key || val == NULL)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_map_find_u(m, m->map.u8, key, val); case 2: return cdada_map_find_u(m, m->map.u16, key, val); case 4: return cdada_map_find_u(m, m->map.u32, key, val); case 8: return cdada_map_find_u(m, m->map.u64, key, val); case 16: return cdada_map_find_u(m, m->map.u128, key, val); case 32: return cdada_map_find_u(m, m->map.u256, key, val); case 64: return cdada_map_find_u(m, m->map.u512, key, val); case 128: return cdada_map_find_u(m, m->map.u1024, key, val); case 256: return cdada_map_find_u(m, m->map.u2048, key, val); break; case 0: CDADA_ASSERT(m->ops); return (*m->ops->find)(m, key, val); default: break; } }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } static int __cdada_map_first_last(const cdada_map_t* map, bool first, void* key, void** val){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!key || val == NULL)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: return cdada_map_first_last_u(m, m->map.u8, first, key, val); case 2: return cdada_map_first_last_u(m, m->map.u16, first, key, val); case 4: return cdada_map_first_last_u(m, m->map.u32, first, key, val); case 8: return cdada_map_first_last_u(m, m->map.u64, first, key, val); case 16: return cdada_map_first_last_u(m, m->map.u128, first, key, val); case 32: return cdada_map_first_last_u(m, m->map.u256, first, key, val); case 64: return cdada_map_first_last_u(m, m->map.u512, first, key, val); case 128: return cdada_map_first_last_u(m, m->map.u1024, first, key, val); case 256: return cdada_map_first_last_u(m, m->map.u2048, first, key, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->first_last)(m, first, key, val); default: break; } }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_map_first(const cdada_map_t* map, void* key, void** val){ return __cdada_map_first_last(map, true, key, val); } int cdada_map_last(const cdada_map_t* map, void* key, void** val){ return __cdada_map_first_last(map, false, key, val); } int cdada_map_traverse(const cdada_map_t* map, cdada_map_it f, void* opaque){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_map_traverse_u(m, m->map.u8, f, opaque); break; case 2: cdada_map_traverse_u(m, m->map.u16, f, opaque); break; case 4: cdada_map_traverse_u(m, m->map.u32, f, opaque); break; case 8: cdada_map_traverse_u(m, m->map.u64, f, opaque); break; case 16: cdada_map_traverse_u(m, m->map.u128, f, opaque); break; case 32: cdada_map_traverse_u(m, m->map.u256, f, opaque); break; case 64: cdada_map_traverse_u(m, m->map.u512, f, opaque); break; case 128: cdada_map_traverse_u(m, m->map.u1024, f, opaque); break; case 256: cdada_map_traverse_u(m, m->map.u2048, f, opaque); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->traverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_map_rtraverse(const cdada_map_t* map, cdada_map_it f, void* opaque){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_map_rtraverse_u(m, m->map.u8, f, opaque); break; case 2: cdada_map_rtraverse_u(m, m->map.u16, f, opaque); break; case 4: cdada_map_rtraverse_u(m, m->map.u32, f, opaque); break; case 8: cdada_map_rtraverse_u(m, m->map.u64, f, opaque); break; case 16: cdada_map_rtraverse_u(m, m->map.u128, f, opaque); break; case 32: cdada_map_rtraverse_u(m, m->map.u256, f, opaque); break; case 64: cdada_map_rtraverse_u(m, m->map.u512, f, opaque); break; case 128: cdada_map_rtraverse_u(m, m->map.u1024, f, opaque); break; case 256: cdada_map_rtraverse_u(m, m->map.u2048, f, opaque); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->rtraverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_map_dump(cdada_map_t* map, uint32_t size, char* buffer, uint32_t* size_used){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); if(!size_used || (buffer&&size ==0)) return CDADA_E_INVALID; try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_map_dump_u(m, m->map.u8, ss); break; case 2: cdada_map_dump_u(m, m->map.u16, ss); break; case 4: cdada_map_dump_u(m, m->map.u32, ss); break; case 8: cdada_map_dump_u(m, m->map.u64, ss); break; case 16: cdada_map_dump_u(m, m->map.u128, ss); break; case 32: cdada_map_dump_u(m, m->map.u256, ss); break; case 64: cdada_map_dump_u(m, m->map.u512, ss); break; case 128: cdada_map_dump_u(m, m->map.u1024, ss); break; case 256: cdada_map_dump_u(m, m->map.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}"; *size_used = ss.str().length()+1; if(!buffer) return CDADA_SUCCESS; snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_map_print(cdada_map_t* map, FILE *stream){ __cdada_map_int_t* m = (__cdada_map_int_t*)map; CDADA_CHECK_MAGIC(m); try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->key_len; switch(c){ case 1: cdada_map_dump_u(m, m->map.u8, ss); break; case 2: cdada_map_dump_u(m, m->map.u16, ss); break; case 4: cdada_map_dump_u(m, m->map.u32, ss); break; case 8: cdada_map_dump_u(m, m->map.u64, ss); break; case 16: cdada_map_dump_u(m, m->map.u128, ss); break; case 32: cdada_map_dump_u(m, m->map.u256, ss); break; case 64: cdada_map_dump_u(m, m->map.u512, ss); break; case 128: cdada_map_dump_u(m, m->map.u1024, ss); break; case 256: cdada_map_dump_u(m, m->map.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}\n"; fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/queue.cc0000644000175000017500000003147114354105336021405 0ustar paolopaolo#include "cdada/queue.h" #include "cdada/__common_internal.h" #include "cdada/__queue_internal.h" #include #include using namespace std; cdada_queue_t* __cdada_queue_create(const uint16_t val_size, __cdada_queue_ops_t* ops){ __cdada_queue_int_t* m = NULL; if(unlikely(val_size == 0)) return m; m = (__cdada_queue_int_t*)malloc(sizeof(__cdada_queue_int_t)); memset(m, 0, sizeof(__cdada_queue_int_t)); m->magic_num = CDADA_MAGIC; m->user_val_len = val_size; try{ //Custom type if(ops){ m->val_len = m->user_val_len = val_size; m->ops = ops; (*m->ops->create)(m); return m; } if(val_size == 1){ m->queue.u8 = new queue(); m->val_len = 1; }else if(val_size == 2){ m->queue.u16 = new queue(); m->val_len = 2; }else if(val_size > 2 && val_size <= 4){ m->queue.u32 = new queue(); m->val_len = 4; }else if(val_size > 4 && val_size <= 8){ m->queue.u64 = new queue(); m->val_len = 8; }else if(val_size > 8 && val_size <= 16){ m->queue.u128 = new queue(); m->val_len = 16; }else if(val_size > 16 && val_size <= 32){ m->queue.u256 = new queue(); m->val_len = 32; }else if(val_size > 32 && val_size <= 64){ m->queue.u512 = new queue(); m->val_len = 64; }else if(val_size > 64 && val_size <= 128){ m->queue.u1024 = new queue(); m->val_len = 128; }else if(val_size > 128 && val_size <= 256){ m->queue.u2048 = new queue(); m->val_len = 256; }else{ goto ROLLBACK; } }catch(bad_alloc& e){ goto ROLLBACK; }catch(...){ CDADA_ASSERT(0); goto ROLLBACK; } return m; ROLLBACK: free(m); return NULL; } /** * Destroy a queue structure */ int cdada_queue_destroy(cdada_queue_t* queue){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: delete m->queue.u8; break; case 2: delete m->queue.u16; break; case 4: delete m->queue.u32; break; case 8: delete m->queue.u64; break; case 16: delete m->queue.u128; break; case 32: delete m->queue.u256; break; case 64: delete m->queue.u512; break; case 128: delete m->queue.u1024; break; case 256: delete m->queue.u2048; break; case 0: CDADA_ASSERT(m->ops); (*m->ops->destroy)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } m->magic_num = 0x0; free(m); return CDADA_SUCCESS; } int cdada_queue_push(cdada_queue_t* queue, const void* val){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; if(m->max_capacity && cdada_queue_size(queue) >= m->max_capacity) return CDADA_E_FULL; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_queue_push_u(m, m->queue.u8, val); case 2: return cdada_queue_push_u(m, m->queue.u16, val); case 4: return cdada_queue_push_u(m, m->queue.u32, val); case 8: return cdada_queue_push_u(m, m->queue.u64, val); case 16: return cdada_queue_push_u(m, m->queue.u128, val); case 32: return cdada_queue_push_u(m, m->queue.u256, val); case 64: return cdada_queue_push_u(m, m->queue.u512, val); case 128: return cdada_queue_push_u(m, m->queue.u1024, val); case 256: return cdada_queue_push_u(m, m->queue.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->push)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_queue_pop(cdada_queue_t* queue){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_queue_pop_u(m, m->queue.u8); case 2: return cdada_queue_pop_u(m, m->queue.u16); case 4: return cdada_queue_pop_u(m, m->queue.u32); case 8: return cdada_queue_pop_u(m, m->queue.u64); case 16: return cdada_queue_pop_u(m, m->queue.u128); case 32: return cdada_queue_pop_u(m, m->queue.u256); case 64: return cdada_queue_pop_u(m, m->queue.u512); case 128: return cdada_queue_pop_u(m, m->queue.u1024); case 256: return cdada_queue_pop_u(m, m->queue.u2048); case 0: CDADA_ASSERT(m->ops); return (*m->ops->pop)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } uint32_t cdada_queue_size(const cdada_queue_t* queue){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return 0; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return m->queue.u8->size(); case 2: return m->queue.u16->size(); case 4: return m->queue.u32->size(); case 8: return m->queue.u64->size(); case 16: return m->queue.u128->size(); case 32: return m->queue.u256->size(); case 64: return m->queue.u512->size(); case 128: return m->queue.u1024->size(); case 256: return m->queue.u2048->size(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->size)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return 0; } int cdada_queue_front(const cdada_queue_t* queue, void* val){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_queue_front_u(m, m->queue.u8, val); case 2: return cdada_queue_front_u(m, m->queue.u16, val); case 4: return cdada_queue_front_u(m, m->queue.u32, val); case 8: return cdada_queue_front_u(m, m->queue.u64, val); case 16: return cdada_queue_front_u(m, m->queue.u128, val); case 32: return cdada_queue_front_u(m, m->queue.u256, val); case 64: return cdada_queue_front_u(m, m->queue.u512, val); case 128: return cdada_queue_front_u(m, m->queue.u1024, val); case 256: return cdada_queue_front_u(m, m->queue.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->front)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_queue_back(const cdada_queue_t* queue, void* val){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_queue_back_u(m, m->queue.u8, val); case 2: return cdada_queue_back_u(m, m->queue.u16, val); case 4: return cdada_queue_back_u(m, m->queue.u32, val); case 8: return cdada_queue_back_u(m, m->queue.u64, val); case 16: return cdada_queue_back_u(m, m->queue.u128, val); case 32: return cdada_queue_back_u(m, m->queue.u256, val); case 64: return cdada_queue_back_u(m, m->queue.u512, val); case 128: return cdada_queue_back_u(m, m->queue.u1024, val); case 256: return cdada_queue_back_u(m, m->queue.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->back)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } bool cdada_queue_empty(const cdada_queue_t* queue){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return false; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_queue_empty_u(m, m->queue.u8); case 2: return cdada_queue_empty_u(m, m->queue.u16); case 4: return cdada_queue_empty_u(m, m->queue.u32); case 8: return cdada_queue_empty_u(m, m->queue.u64); case 16: return cdada_queue_empty_u(m, m->queue.u128); case 32: return cdada_queue_empty_u(m, m->queue.u256); case 64: return cdada_queue_empty_u(m, m->queue.u512); case 128: return cdada_queue_empty_u(m, m->queue.u1024); case 256: return cdada_queue_empty_u(m, m->queue.u2048); case 0: CDADA_ASSERT(m->ops); return (*m->ops->empty)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return false; } uint64_t cdada_queue_get_max_capacity(const cdada_queue_t* queue){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; if(unlikely(!(m) || m->magic_num != CDADA_MAGIC)) return 0; return m->max_capacity; } int cdada_queue_set_max_capacity(const cdada_queue_t* queue, const uint64_t limit){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; if(unlikely(!(m) || m->magic_num != CDADA_MAGIC)) return CDADA_E_INVALID; m->max_capacity = limit; return CDADA_SUCCESS; } int cdada_queue_dump(cdada_queue_t* queue, uint32_t size, char* buffer, uint32_t* size_used){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); if(!size_used || (buffer&&size ==0)) return CDADA_E_INVALID; try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_queue_dump_u(m, m->queue.u8, ss); break; case 2: cdada_queue_dump_u(m, m->queue.u16, ss); break; case 4: cdada_queue_dump_u(m, m->queue.u32, ss); break; case 8: cdada_queue_dump_u(m, m->queue.u64, ss); break; case 16: cdada_queue_dump_u(m, m->queue.u128, ss); break; case 32: cdada_queue_dump_u(m, m->queue.u256, ss); break; case 64: cdada_queue_dump_u(m, m->queue.u512, ss); break; case 128: cdada_queue_dump_u(m, m->queue.u1024, ss); break; case 256: cdada_queue_dump_u(m, m->queue.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}"; *size_used = ss.str().length()+1; if(!buffer) return CDADA_SUCCESS; snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_queue_print(cdada_queue_t* queue, FILE *stream){ __cdada_queue_int_t* m = (__cdada_queue_int_t*)queue; CDADA_CHECK_MAGIC(m); try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_queue_dump_u(m, m->queue.u8, ss); break; case 2: cdada_queue_dump_u(m, m->queue.u16, ss); break; case 4: cdada_queue_dump_u(m, m->queue.u32, ss); break; case 8: cdada_queue_dump_u(m, m->queue.u64, ss); break; case 16: cdada_queue_dump_u(m, m->queue.u128, ss); break; case 32: cdada_queue_dump_u(m, m->queue.u256, ss); break; case 64: cdada_queue_dump_u(m, m->queue.u512, ss); break; case 128: cdada_queue_dump_u(m, m->queue.u1024, ss); break; case 256: cdada_queue_dump_u(m, m->queue.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}\n"; fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/list.cc0000644000175000017500000005621314354105336021235 0ustar paolopaolo#include "cdada/list.h" #include "cdada/__common_internal.h" #include "cdada/__list_internal.h" #include #include using namespace std; cdada_list_t* __cdada_list_create(const uint16_t val_size, __cdada_list_ops_t* ops){ __cdada_list_int_t* m = NULL; if(unlikely(val_size == 0)) return m; m = (__cdada_list_int_t*)malloc(sizeof(__cdada_list_int_t)); memset(m, 0, sizeof(__cdada_list_int_t)); m->magic_num = CDADA_MAGIC; m->user_val_len = val_size; try{ //Custom type if(ops){ m->val_len = m->user_val_len = val_size; m->ops = ops; (*m->ops->create)(m); return m; } if(val_size == 1){ m->list.u8 = new list(); m->val_len = 1; }else if(val_size == 2){ m->list.u16 = new list(); m->val_len = 2; }else if(val_size > 2 && val_size <= 4){ m->list.u32 = new list(); m->val_len = 4; }else if(val_size > 4 && val_size <= 8){ m->list.u64 = new list(); m->val_len = 8; }else if(val_size > 8 && val_size <= 16){ m->list.u128 = new list(); m->val_len = 16; }else if(val_size > 16 && val_size <= 32){ m->list.u256 = new list(); m->val_len = 32; }else if(val_size > 32 && val_size <= 64){ m->list.u512 = new list(); m->val_len = 64; }else if(val_size > 64 && val_size <= 128){ m->list.u1024 = new list(); m->val_len = 128; }else if(val_size > 128 && val_size <= 256){ m->list.u2048 = new list(); m->val_len = 256; }else{ goto ROLLBACK; } }catch(bad_alloc& e){ goto ROLLBACK; }catch(...){ CDADA_ASSERT(0); goto ROLLBACK; } return m; ROLLBACK: free(m); return NULL; } /** * Destroy a list structure */ int cdada_list_destroy(cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: delete m->list.u8; break; case 2: delete m->list.u16; break; case 4: delete m->list.u32; break; case 8: delete m->list.u64; break; case 16: delete m->list.u128; break; case 32: delete m->list.u256; break; case 64: delete m->list.u512; break; case 128: delete m->list.u1024; break; case 256: delete m->list.u2048; break; case 0: CDADA_ASSERT(m->ops); (*m->ops->destroy)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } m->magic_num = 0x0; free(m); return CDADA_SUCCESS; } int cdada_list_clear(cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: m->list.u8->clear(); break; case 2: m->list.u16->clear(); break; case 4: m->list.u32->clear(); break; case 8: m->list.u64->clear(); break; case 16: m->list.u128->clear(); break; case 32: m->list.u256->clear(); break; case 64: m->list.u512->clear(); break; case 128: m->list.u1024->clear(); break; case 256: m->list.u2048->clear(); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->clear)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } bool cdada_list_empty(const cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return false; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return m->list.u8->empty(); case 2: return m->list.u16->empty(); case 4: return m->list.u32->empty(); case 8: return m->list.u64->empty(); case 16: return m->list.u128->empty(); case 32: return m->list.u256->empty(); case 64: return m->list.u512->empty(); case 128: return m->list.u1024->empty(); case 256: return m->list.u2048->empty(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->empty)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return false; } uint32_t cdada_list_size(const cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return 0; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return m->list.u8->size(); case 2: return m->list.u16->size(); case 4: return m->list.u32->size(); case 8: return m->list.u64->size(); case 16: return m->list.u128->size(); case 32: return m->list.u256->size(); case 64: return m->list.u512->size(); case 128: return m->list.u1024->size(); case 256: return m->list.u2048->size(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->size)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return 0; } int cdada_list_insert(cdada_list_t* list, const void* val, const uint32_t pos){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; //NOTE: we don't want std::list insert "replace semantics", so we return //E_EXISTS if val is present in the list try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_insert_u(m, m->list.u8, val, pos); case 2: return cdada_list_insert_u(m, m->list.u16, val, pos); case 4: return cdada_list_insert_u(m, m->list.u32, val, pos); case 8: return cdada_list_insert_u(m, m->list.u64, val, pos); case 16: return cdada_list_insert_u(m, m->list.u128, val, pos); case 32: return cdada_list_insert_u(m, m->list.u256, val, pos); case 64: return cdada_list_insert_u(m, m->list.u512, val, pos); case 128: return cdada_list_insert_u(m, m->list.u1024, val, pos); case 256: return cdada_list_insert_u(m, m->list.u2048, val, pos); case 0: CDADA_ASSERT(m->ops); return (*m->ops->insert)(m, val, pos); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_list_get(const cdada_list_t* list, const uint32_t pos, void* val){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; //NOTE: we don't want std::list insert "replace semantics", so we return //E_EXISTS if val is present in the list try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_get_u(m, m->list.u8, pos, val); case 2: return cdada_list_get_u(m, m->list.u16, pos, val); case 4: return cdada_list_get_u(m, m->list.u32, pos, val); case 8: return cdada_list_get_u(m, m->list.u64, pos, val); case 16: return cdada_list_get_u(m, m->list.u128, pos, val); case 32: return cdada_list_get_u(m, m->list.u256, pos, val); case 64: return cdada_list_get_u(m, m->list.u512, pos, val); case 128: return cdada_list_get_u(m, m->list.u1024, pos, val); case 256: return cdada_list_get_u(m, m->list.u2048, pos, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->get)(m, pos, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } static int __cdada_list_first_last(const cdada_list_t* list, bool first, void* key){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC || !key)) return false; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_first_last_u(m, m->list.u8, first, key); case 2: return cdada_list_first_last_u(m, m->list.u16, first, key); case 4: return cdada_list_first_last_u(m, m->list.u32, first, key); case 8: return cdada_list_first_last_u(m, m->list.u64, first, key); case 16: return cdada_list_first_last_u(m, m->list.u128, first, key); case 32: return cdada_list_first_last_u(m, m->list.u256, first, key); case 64: return cdada_list_first_last_u(m, m->list.u512, first, key); case 128: return cdada_list_first_last_u(m, m->list.u1024, first, key); case 256: return cdada_list_first_last_u(m, m->list.u2048, first, key); case 0: return (*m->ops->first_last)(m, first, key); default: break; } }catch(...){} CDADA_ASSERT(0); return false; } int cdada_list_first(const cdada_list_t* list, void* key){ return __cdada_list_first_last(list, true, key); } int cdada_list_last(const cdada_list_t* list, void* key){ return __cdada_list_first_last(list, false, key); } int cdada_list_erase(cdada_list_t* list, const uint32_t pos){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_erase_u(m, m->list.u8, pos); case 2: return cdada_list_erase_u(m, m->list.u16, pos); case 4: return cdada_list_erase_u(m, m->list.u32, pos); case 8: return cdada_list_erase_u(m, m->list.u64, pos); case 16: return cdada_list_erase_u(m, m->list.u128, pos); case 32: return cdada_list_erase_u(m, m->list.u256, pos); case 64: return cdada_list_erase_u(m, m->list.u512, pos); case 128: return cdada_list_erase_u(m, m->list.u1024, pos); case 256: return cdada_list_erase_u(m, m->list.u2048, pos); case 0: CDADA_ASSERT(m->ops); return (*m->ops->erase)(m, pos); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_list_remove(cdada_list_t* list, const void* val){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; //NOTE: we don't want std::list remove "replace semantics", so we return //E_EXISTS if val is present in the list try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_remove_u(m, m->list.u8, val); case 2: return cdada_list_remove_u(m, m->list.u16, val); case 4: return cdada_list_remove_u(m, m->list.u32, val); case 8: return cdada_list_remove_u(m, m->list.u64, val); case 16: return cdada_list_remove_u(m, m->list.u128, val); case 32: return cdada_list_remove_u(m, m->list.u256, val); case 64: return cdada_list_remove_u(m, m->list.u512, val); case 128: return cdada_list_remove_u(m, m->list.u1024, val); case 256: return cdada_list_remove_u(m, m->list.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->remove)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } static int cdada_list_push_(cdada_list_t* list, const void* val, bool front){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_push_u(m, m->list.u8, val, front); case 2: return cdada_list_push_u(m, m->list.u16, val, front); case 4: return cdada_list_push_u(m, m->list.u32, val, front); case 8: return cdada_list_push_u(m, m->list.u64, val, front); case 16: return cdada_list_push_u(m, m->list.u128, val, front); case 32: return cdada_list_push_u(m, m->list.u256, val, front); case 64: return cdada_list_push_u(m, m->list.u512, val, front); case 128: return cdada_list_push_u(m, m->list.u1024, val, front); case 256: return cdada_list_push_u(m, m->list.u2048, val, front); case 0: CDADA_ASSERT(m->ops); return (*m->ops->push)(m, val, front); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_list_push_front(cdada_list_t* list, const void* val){ return cdada_list_push_(list, val, true); } int cdada_list_push_back(cdada_list_t* list, const void* val){ return cdada_list_push_(list, val, false); } static int cdada_list_pop_(cdada_list_t* list, bool front){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_list_pop_u(m, m->list.u8, front); case 2: return cdada_list_pop_u(m, m->list.u16, front); case 4: return cdada_list_pop_u(m, m->list.u32, front); case 8: return cdada_list_pop_u(m,m->list.u64, front); case 16: return cdada_list_pop_u(m, m->list.u128, front); case 32: return cdada_list_pop_u(m, m->list.u256, front); case 64: return cdada_list_pop_u(m, m->list.u512, front); case 128: return cdada_list_pop_u(m, m->list.u1024, front); case 256: return cdada_list_pop_u(m, m->list.u2048, front); case 0: CDADA_ASSERT(m->ops); return (*m->ops->pop)(m, front); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_list_pop_front(cdada_list_t* list){ return cdada_list_pop_(list, true); } int cdada_list_pop_back(cdada_list_t* list){ return cdada_list_pop_(list, false); } int cdada_list_sort(cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: m->list.u8->sort(); break; case 2: m->list.u16->sort(); break; case 4: m->list.u32->sort(); break; case 8: m->list.u64->sort(); break; case 16: m->list.u128->sort(); break; case 32: m->list.u256->sort(); break; case 64: m->list.u512->sort(); break; case 128: m->list.u1024->sort(); break; case 256: m->list.u2048->sort(); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->sort)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_reverse(cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: m->list.u8->reverse(); break; case 2: m->list.u16->reverse(); break; case 4: m->list.u32->reverse(); break; case 8: m->list.u64->reverse(); break; case 16: m->list.u128->reverse(); break; case 32: m->list.u256->reverse(); break; case 64: m->list.u512->reverse(); break; case 128: m->list.u1024->reverse(); break; case 256: m->list.u2048->reverse(); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->reverse)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_unique(cdada_list_t* list){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: m->list.u8->unique(); break; case 2: m->list.u16->unique(); break; case 4: m->list.u32->unique(); break; case 8: m->list.u64->unique(); break; case 16: m->list.u128->unique(); break; case 32: m->list.u256->unique(); break; case 64: m->list.u512->unique(); break; case 128: m->list.u1024->unique(); break; case 256: m->list.u2048->unique(); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->unique)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_traverse(const cdada_list_t* list, cdada_list_it f, void* opaque){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_list_traverse_u(m, m->list.u8, f, opaque); break; case 2: cdada_list_traverse_u(m, m->list.u16, f, opaque); break; case 4: cdada_list_traverse_u(m, m->list.u32, f, opaque); break; case 8: cdada_list_traverse_u(m, m->list.u64, f, opaque); break; case 16: cdada_list_traverse_u(m, m->list.u128, f, opaque); break; case 32: cdada_list_traverse_u(m, m->list.u256, f, opaque); break; case 64: cdada_list_traverse_u(m, m->list.u512, f, opaque); break; case 128: cdada_list_traverse_u(m, m->list.u1024, f, opaque); break; case 256: cdada_list_traverse_u(m, m->list.u2048, f, opaque); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->traverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_rtraverse(const cdada_list_t* list, cdada_list_it f, void* opaque){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(unlikely(!f)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_list_rtraverse_u(m, m->list.u8, f, opaque); break; case 2: cdada_list_rtraverse_u(m, m->list.u16, f, opaque); break; case 4: cdada_list_rtraverse_u(m, m->list.u32, f, opaque); break; case 8: cdada_list_rtraverse_u(m, m->list.u64, f, opaque); break; case 16: cdada_list_rtraverse_u(m, m->list.u128, f, opaque); break; case 32: cdada_list_rtraverse_u(m, m->list.u256, f, opaque); break; case 64: cdada_list_rtraverse_u(m, m->list.u512, f, opaque); break; case 128: cdada_list_rtraverse_u(m, m->list.u1024, f, opaque); break; case 256: cdada_list_rtraverse_u(m, m->list.u2048, f, opaque); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->rtraverse)(m, f, opaque); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_dump(cdada_list_t* list, uint32_t size, char* buffer, uint32_t* size_used){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); if(!size_used || (buffer&&size ==0)) return CDADA_E_INVALID; try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_list_dump_u(m, m->list.u8, ss); break; case 2: cdada_list_dump_u(m, m->list.u16, ss); break; case 4: cdada_list_dump_u(m, m->list.u32, ss); break; case 8: cdada_list_dump_u(m, m->list.u64, ss); break; case 16: cdada_list_dump_u(m, m->list.u128, ss); break; case 32: cdada_list_dump_u(m, m->list.u256, ss); break; case 64: cdada_list_dump_u(m, m->list.u512, ss); break; case 128: cdada_list_dump_u(m, m->list.u1024, ss); break; case 256: cdada_list_dump_u(m, m->list.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}"; *size_used = ss.str().length()+1; if(!buffer) return CDADA_SUCCESS; snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_list_print(cdada_list_t* list, FILE *stream){ __cdada_list_int_t* m = (__cdada_list_int_t*)list; CDADA_CHECK_MAGIC(m); try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_list_dump_u(m, m->list.u8, ss); break; case 2: cdada_list_dump_u(m, m->list.u16, ss); break; case 4: cdada_list_dump_u(m, m->list.u32, ss); break; case 8: cdada_list_dump_u(m, m->list.u64, ss); break; case 16: cdada_list_dump_u(m, m->list.u128, ss); break; case 32: cdada_list_dump_u(m, m->list.u256, ss); break; case 64: cdada_list_dump_u(m, m->list.u512, ss); break; case 128: cdada_list_dump_u(m, m->list.u1024, ss); break; case 256: cdada_list_dump_u(m, m->list.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}\n"; fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/stack.cc0000644000175000017500000002701614354105336021366 0ustar paolopaolo#include "cdada/stack.h" #include "cdada/__common_internal.h" #include "cdada/__stack_internal.h" #include #include using namespace std; cdada_stack_t* __cdada_stack_create(const uint16_t val_size, __cdada_stack_ops_t* ops){ __cdada_stack_int_t* m = NULL; if(unlikely(val_size == 0)) return m; m = (__cdada_stack_int_t*)malloc(sizeof(__cdada_stack_int_t)); memset(m, 0, sizeof(__cdada_stack_int_t)); m->magic_num = CDADA_MAGIC; m->user_val_len = val_size; try{ //Custom type if(ops){ m->val_len = m->user_val_len = val_size; m->ops = ops; (*m->ops->create)(m); return m; } if(val_size == 1){ m->stack.u8 = new stack(); m->val_len = 1; }else if(val_size == 2){ m->stack.u16 = new stack(); m->val_len = 2; }else if(val_size > 2 && val_size <= 4){ m->stack.u32 = new stack(); m->val_len = 4; }else if(val_size > 4 && val_size <= 8){ m->stack.u64 = new stack(); m->val_len = 8; }else if(val_size > 8 && val_size <= 16){ m->stack.u128 = new stack(); m->val_len = 16; }else if(val_size > 16 && val_size <= 32){ m->stack.u256 = new stack(); m->val_len = 32; }else if(val_size > 32 && val_size <= 64){ m->stack.u512 = new stack(); m->val_len = 64; }else if(val_size > 64 && val_size <= 128){ m->stack.u1024 = new stack(); m->val_len = 128; }else if(val_size > 128 && val_size <= 256){ m->stack.u2048 = new stack(); m->val_len = 256; }else{ goto ROLLBACK; } }catch(bad_alloc& e){ goto ROLLBACK; }catch(...){ CDADA_ASSERT(0); goto ROLLBACK; } return m; ROLLBACK: free(m); return NULL; } /** * Destroy a stack structure */ int cdada_stack_destroy(cdada_stack_t* stack){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: delete m->stack.u8; break; case 2: delete m->stack.u16; break; case 4: delete m->stack.u32; break; case 8: delete m->stack.u64; break; case 16: delete m->stack.u128; break; case 32: delete m->stack.u256; break; case 64: delete m->stack.u512; break; case 128: delete m->stack.u1024; break; case 256: delete m->stack.u2048; break; case 0: CDADA_ASSERT(m->ops); (*m->ops->destroy)(m); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } m->magic_num = 0x0; free(m); return CDADA_SUCCESS; } int cdada_stack_push(cdada_stack_t* stack, const void* val){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; if(m->max_capacity && cdada_stack_size(stack) >= m->max_capacity) return CDADA_E_FULL; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_stack_push_u(m, m->stack.u8, val); case 2: return cdada_stack_push_u(m, m->stack.u16, val); case 4: return cdada_stack_push_u(m, m->stack.u32, val); case 8: return cdada_stack_push_u(m, m->stack.u64, val); case 16: return cdada_stack_push_u(m, m->stack.u128, val); case 32: return cdada_stack_push_u(m, m->stack.u256, val); case 64: return cdada_stack_push_u(m, m->stack.u512, val); case 128: return cdada_stack_push_u(m, m->stack.u1024, val); case 256: return cdada_stack_push_u(m, m->stack.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->push)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } int cdada_stack_pop(cdada_stack_t* stack){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_stack_pop_u(m, m->stack.u8); case 2: return cdada_stack_pop_u(m, m->stack.u16); case 4: return cdada_stack_pop_u(m, m->stack.u32); case 8: return cdada_stack_pop_u(m, m->stack.u64); case 16: return cdada_stack_pop_u(m, m->stack.u128); case 32: return cdada_stack_pop_u(m, m->stack.u256); case 64: return cdada_stack_pop_u(m, m->stack.u512); case 128: return cdada_stack_pop_u(m, m->stack.u1024); case 256: return cdada_stack_pop_u(m, m->stack.u2048); case 0: CDADA_ASSERT(m->ops); return (*m->ops->pop)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } uint32_t cdada_stack_size(const cdada_stack_t* stack){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return 0; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return m->stack.u8->size(); case 2: return m->stack.u16->size(); case 4: return m->stack.u32->size(); case 8: return m->stack.u64->size(); case 16: return m->stack.u128->size(); case 32: return m->stack.u256->size(); case 64: return m->stack.u512->size(); case 128: return m->stack.u1024->size(); case 256: return m->stack.u2048->size(); case 0: CDADA_ASSERT(m->ops); return (*m->ops->size)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return 0; } int cdada_stack_top(const cdada_stack_t* stack, void* val){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); if(unlikely(!val)) return CDADA_E_INVALID; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_stack_top_u(m, m->stack.u8, val); case 2: return cdada_stack_top_u(m, m->stack.u16, val); case 4: return cdada_stack_top_u(m, m->stack.u32, val); case 8: return cdada_stack_top_u(m, m->stack.u64, val); case 16: return cdada_stack_top_u(m, m->stack.u128, val); case 32: return cdada_stack_top_u(m, m->stack.u256, val); case 64: return cdada_stack_top_u(m, m->stack.u512, val); case 128: return cdada_stack_top_u(m, m->stack.u1024, val); case 256: return cdada_stack_top_u(m, m->stack.u2048, val); case 0: CDADA_ASSERT(m->ops); return (*m->ops->top)(m, val); default: break; } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){} CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } bool cdada_stack_empty(const cdada_stack_t* stack){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; if(unlikely(!m || m->magic_num != CDADA_MAGIC)) return false; try{ int c = m->ops? 0 : m->val_len; switch(c){ case 1: return cdada_stack_empty_u(m, m->stack.u8); case 2: return cdada_stack_empty_u(m, m->stack.u16); case 4: return cdada_stack_empty_u(m, m->stack.u32); case 8: return cdada_stack_empty_u(m, m->stack.u64); case 16: return cdada_stack_empty_u(m, m->stack.u128); case 32: return cdada_stack_empty_u(m, m->stack.u256); case 64: return cdada_stack_empty_u(m, m->stack.u512); case 128: return cdada_stack_empty_u(m, m->stack.u1024); case 256: return cdada_stack_empty_u(m, m->stack.u2048); case 0: CDADA_ASSERT(m->ops); return (*m->ops->empty)(m); default: break; } }catch(...){} CDADA_ASSERT(0); return false; } uint64_t cdada_stack_get_max_capacity(const cdada_stack_t* stack){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; if(unlikely(!(m) || m->magic_num != CDADA_MAGIC)) return 0; return m->max_capacity; } int cdada_stack_set_max_capacity(const cdada_stack_t* stack, const uint64_t limit){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; if(unlikely(!(m) || m->magic_num != CDADA_MAGIC)) return CDADA_E_INVALID; m->max_capacity = limit; return CDADA_SUCCESS; } int cdada_stack_dump(cdada_stack_t* stack, uint32_t size, char* buffer, uint32_t* size_used){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); if(!size_used || (buffer&&size ==0)) return CDADA_E_INVALID; try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_stack_dump_u(m, m->stack.u8, ss); break; case 2: cdada_stack_dump_u(m, m->stack.u16, ss); break; case 4: cdada_stack_dump_u(m, m->stack.u32, ss); break; case 8: cdada_stack_dump_u(m, m->stack.u64, ss); break; case 16: cdada_stack_dump_u(m, m->stack.u128, ss); break; case 32: cdada_stack_dump_u(m, m->stack.u256, ss); break; case 64: cdada_stack_dump_u(m, m->stack.u512, ss); break; case 128: cdada_stack_dump_u(m, m->stack.u1024, ss); break; case 256: cdada_stack_dump_u(m, m->stack.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}"; *size_used = ss.str().length()+1; if(!buffer) return CDADA_SUCCESS; snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_stack_print(cdada_stack_t* stack, FILE *stream){ __cdada_stack_int_t* m = (__cdada_stack_int_t*)stack; CDADA_CHECK_MAGIC(m); try{ std::stringstream ss; ss << "{"; int c = m->ops? 0 : m->val_len; switch(c){ case 1: cdada_stack_dump_u(m, m->stack.u8, ss); break; case 2: cdada_stack_dump_u(m, m->stack.u16, ss); break; case 4: cdada_stack_dump_u(m, m->stack.u32, ss); break; case 8: cdada_stack_dump_u(m, m->stack.u64, ss); break; case 16: cdada_stack_dump_u(m, m->stack.u128, ss); break; case 32: cdada_stack_dump_u(m, m->stack.u256, ss); break; case 64: cdada_stack_dump_u(m, m->stack.u512, ss); break; case 128: cdada_stack_dump_u(m, m->stack.u1024, ss); break; case 256: cdada_stack_dump_u(m, m->stack.u2048, ss); break; case 0: CDADA_ASSERT(m->ops); (*m->ops->dump)(m, ss); break; default: CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } ss << "}\n"; fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/Makefile.in0000644000175000017500000010545514354105430022016 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/config_m4/debug.m4 \ $(top_srcdir)/config_m4/profiling.m4 \ $(top_srcdir)/config_m4/versioning.m4 \ $(top_srcdir)/config_m4/valgrind.m4 \ $(top_srcdir)/config_m4/rdtsc.m4 \ $(top_srcdir)/config_m4/tests.m4 \ $(top_srcdir)/config_m4/examples.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libcdada_la_DEPENDENCIES = am_libcdada_la_OBJECTS = libcdada_la-bbitmap.lo libcdada_la-list.lo \ libcdada_la-map.lo libcdada_la-queue.lo libcdada_la-set.lo \ libcdada_la-stack.lo libcdada_la-str.lo libcdada_la-utils.lo libcdada_la_OBJECTS = $(am_libcdada_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libcdada_la-bbitmap.Plo \ ./$(DEPDIR)/libcdada_la-list.Plo \ ./$(DEPDIR)/libcdada_la-map.Plo \ ./$(DEPDIR)/libcdada_la-queue.Plo \ ./$(DEPDIR)/libcdada_la-set.Plo \ ./$(DEPDIR)/libcdada_la-stack.Plo \ ./$(DEPDIR)/libcdada_la-str.Plo \ ./$(DEPDIR)/libcdada_la-utils.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libcdada_la_SOURCES) DIST_SOURCES = $(libcdada_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = check-valgrind-recursive \ check-valgrind-memcheck-recursive \ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ check-valgrind-sgcheck-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDADA_BRANCH = @CDADA_BRANCH@ CDADA_BUILD = @CDADA_BUILD@ CDADA_DESCRIBE = @CDADA_DESCRIBE@ CDADA_VERSION = @CDADA_VERSION@ CDADA_VERSION_MAJOR = @CDADA_VERSION_MAJOR@ CDADA_VERSION_MINOR = @CDADA_VERSION_MINOR@ CDADA_VERSION_NORMALIZED = @CDADA_VERSION_NORMALIZED@ CDADA_VERSION_PATCH = @CDADA_VERSION_PATCH@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VALGRIND = @VALGRIND@ VALGRIND_ENABLED = @VALGRIND_ENABLED@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ ff_git = @ff_git@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ valgrind_enabled_tools = @valgrind_enabled_tools@ valgrind_tools = @valgrind_tools@ MAINTAINERCLEANFILES = Makefile.in lib_LTLIBRARIES = libcdada.la libcdada_la_SOURCES = bbitmap.cc \ list.cc \ map.cc \ queue.cc \ set.cc \ stack.cc \ str.cc \ utils.c libcdada_la_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ -D__CDADA_INTERNAL_INCLUDE libcdada_la_LIBADD = all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcdada.la: $(libcdada_la_OBJECTS) $(libcdada_la_DEPENDENCIES) $(EXTRA_libcdada_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) -rpath $(libdir) $(libcdada_la_OBJECTS) $(libcdada_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-bbitmap.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-map.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-set.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-stack.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-str.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcdada_la-utils.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libcdada_la-utils.lo: utils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdada_la-utils.lo -MD -MP -MF $(DEPDIR)/libcdada_la-utils.Tpo -c -o libcdada_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-utils.Tpo $(DEPDIR)/libcdada_la-utils.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='libcdada_la-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdada_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< libcdada_la-bbitmap.lo: bbitmap.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-bbitmap.lo -MD -MP -MF $(DEPDIR)/libcdada_la-bbitmap.Tpo -c -o libcdada_la-bbitmap.lo `test -f 'bbitmap.cc' || echo '$(srcdir)/'`bbitmap.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-bbitmap.Tpo $(DEPDIR)/libcdada_la-bbitmap.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='bbitmap.cc' object='libcdada_la-bbitmap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-bbitmap.lo `test -f 'bbitmap.cc' || echo '$(srcdir)/'`bbitmap.cc libcdada_la-list.lo: list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-list.lo -MD -MP -MF $(DEPDIR)/libcdada_la-list.Tpo -c -o libcdada_la-list.lo `test -f 'list.cc' || echo '$(srcdir)/'`list.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-list.Tpo $(DEPDIR)/libcdada_la-list.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='list.cc' object='libcdada_la-list.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-list.lo `test -f 'list.cc' || echo '$(srcdir)/'`list.cc libcdada_la-map.lo: map.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-map.lo -MD -MP -MF $(DEPDIR)/libcdada_la-map.Tpo -c -o libcdada_la-map.lo `test -f 'map.cc' || echo '$(srcdir)/'`map.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-map.Tpo $(DEPDIR)/libcdada_la-map.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map.cc' object='libcdada_la-map.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-map.lo `test -f 'map.cc' || echo '$(srcdir)/'`map.cc libcdada_la-queue.lo: queue.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-queue.lo -MD -MP -MF $(DEPDIR)/libcdada_la-queue.Tpo -c -o libcdada_la-queue.lo `test -f 'queue.cc' || echo '$(srcdir)/'`queue.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-queue.Tpo $(DEPDIR)/libcdada_la-queue.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='queue.cc' object='libcdada_la-queue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-queue.lo `test -f 'queue.cc' || echo '$(srcdir)/'`queue.cc libcdada_la-set.lo: set.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-set.lo -MD -MP -MF $(DEPDIR)/libcdada_la-set.Tpo -c -o libcdada_la-set.lo `test -f 'set.cc' || echo '$(srcdir)/'`set.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-set.Tpo $(DEPDIR)/libcdada_la-set.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='set.cc' object='libcdada_la-set.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-set.lo `test -f 'set.cc' || echo '$(srcdir)/'`set.cc libcdada_la-stack.lo: stack.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-stack.lo -MD -MP -MF $(DEPDIR)/libcdada_la-stack.Tpo -c -o libcdada_la-stack.lo `test -f 'stack.cc' || echo '$(srcdir)/'`stack.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-stack.Tpo $(DEPDIR)/libcdada_la-stack.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stack.cc' object='libcdada_la-stack.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-stack.lo `test -f 'stack.cc' || echo '$(srcdir)/'`stack.cc libcdada_la-str.lo: str.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcdada_la-str.lo -MD -MP -MF $(DEPDIR)/libcdada_la-str.Tpo -c -o libcdada_la-str.lo `test -f 'str.cc' || echo '$(srcdir)/'`str.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdada_la-str.Tpo $(DEPDIR)/libcdada_la-str.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='str.cc' object='libcdada_la-str.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdada_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcdada_la-str.lo `test -f 'str.cc' || echo '$(srcdir)/'`str.cc mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs check-valgrind-local: check-valgrind-memcheck-local: check-valgrind-helgrind-local: check-valgrind-drd-local: check-valgrind-sgcheck-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) check-valgrind: check-valgrind-am check-valgrind-am: check-valgrind-local check-valgrind-drd: check-valgrind-drd-am check-valgrind-drd-am: check-valgrind-drd-local check-valgrind-helgrind: check-valgrind-helgrind-am check-valgrind-helgrind-am: check-valgrind-helgrind-local check-valgrind-memcheck: check-valgrind-memcheck-am check-valgrind-memcheck-am: check-valgrind-memcheck-local check-valgrind-sgcheck: check-valgrind-sgcheck-am check-valgrind-sgcheck-am: check-valgrind-sgcheck-local clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libcdada_la-bbitmap.Plo -rm -f ./$(DEPDIR)/libcdada_la-list.Plo -rm -f ./$(DEPDIR)/libcdada_la-map.Plo -rm -f ./$(DEPDIR)/libcdada_la-queue.Plo -rm -f ./$(DEPDIR)/libcdada_la-set.Plo -rm -f ./$(DEPDIR)/libcdada_la-stack.Plo -rm -f ./$(DEPDIR)/libcdada_la-str.Plo -rm -f ./$(DEPDIR)/libcdada_la-utils.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcdada_la-bbitmap.Plo -rm -f ./$(DEPDIR)/libcdada_la-list.Plo -rm -f ./$(DEPDIR)/libcdada_la-map.Plo -rm -f ./$(DEPDIR)/libcdada_la-queue.Plo -rm -f ./$(DEPDIR)/libcdada_la-set.Plo -rm -f ./$(DEPDIR)/libcdada_la-stack.Plo -rm -f ./$(DEPDIR)/libcdada_la-str.Plo -rm -f ./$(DEPDIR)/libcdada_la-utils.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \ check-valgrind-am check-valgrind-drd-am \ check-valgrind-drd-local check-valgrind-helgrind-am \ check-valgrind-helgrind-local check-valgrind-local \ check-valgrind-memcheck-am check-valgrind-memcheck-local \ check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/external_libs/libcdada/src/str.cc0000644000175000017500000002223414354105336021066 0ustar paolopaolo#include "cdada/str.h" #include "cdada/__str_internal.h" #include #include #include #include using namespace std; cdada_str_t* cdada_str_create(const char* str){ __cdada_str_int_t* m = NULL; m = (__cdada_str_int_t*)malloc(sizeof(__cdada_str_int_t)); if(!m) return NULL; try{ m->magic_num = CDADA_MAGIC; m->str = new std::string(str); }catch(bad_alloc& e){ free(m); return NULL; }catch(...){ CDADA_ASSERT(0); return NULL; } return m; } int cdada_str_destroy(cdada_str_t* str){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); m->magic_num = 0x0; try{ delete m->str; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } free(m); return CDADA_SUCCESS; } //Access int cdada_str_traverse(const cdada_str_t* str, cdada_str_it func, void* opaque){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!func) return CDADA_E_INVALID; std::string& s = *m->str; try{ std::string::const_iterator it; uint32_t pos = 0; for(it = s.begin(); it != s.end(); ++it){ (*func)(str, *it, pos, opaque); ++pos; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_rtraverse(const cdada_str_t* str, cdada_str_it func, void* opaque){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!func) return CDADA_E_INVALID; std::string& s = *m->str; try{ std::string::const_reverse_iterator it; uint32_t pos = s.length()-1; for(it = s.rbegin(); it != s.rend(); ++it){ (*func)(str, *it, pos, opaque); --pos; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } bool cdada_str_empty(const cdada_str_t* str){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; if(!m || m->magic_num != CDADA_MAGIC) return false; try{ return m->str->empty(); }catch(...){ CDADA_ASSERT(0); } return false; } uint32_t cdada_str_length(const cdada_str_t* str){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; if(!m || m->magic_num != CDADA_MAGIC) return 0; try{ return m->str->length(); }catch(...){ CDADA_ASSERT(0); } return 0; } const char* cdada_str(const cdada_str_t* str){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; if(!m || m->magic_num != CDADA_MAGIC) return ""; try{ return m->str->c_str(); }catch(...){ CDADA_ASSERT(0); } return ""; } int __cdada_str_find(const cdada_str_t* str, const char* substr, uint32_t* pos, bool first){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr || !pos) return CDADA_E_INVALID; std::string& s = *m->str; if(s.length() == 0) return CDADA_E_NOT_FOUND; try{ size_t p; if(first) p = s.find(substr); else p = s.rfind(substr); if(p == std::string::npos) return CDADA_E_NOT_FOUND; *pos = p; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_find_first(const cdada_str_t* str, const char* substr, uint32_t* pos){ return __cdada_str_find(str, substr, pos, true); } int cdada_str_find_last(const cdada_str_t* str, const char* substr, uint32_t* pos){ return __cdada_str_find(str, substr, pos, false); } int cdada_str_find_count(const cdada_str_t* str, const char* substr, uint32_t* n){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr || !n) return CDADA_E_INVALID; std::string& s = *m->str; try{ size_t p, p_last; uint32_t& count = *n; count = 0; p_last = 0; while(true){ p = s.find(substr, p_last); if(p == std::string::npos) break; p_last = p+1; ++count; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_find_all(const cdada_str_t* str, const char* substr, const uint32_t size, uint32_t* poss, uint32_t* cnt){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr || !poss || !size || !cnt) return CDADA_E_INVALID; std::string& s = *m->str; try{ size_t p = 0; *cnt = 0; while(true){ p = s.find(substr, p); if(p == std::string::npos) break; if((*cnt) == size) return CDADA_E_INCOMPLETE; poss[(*cnt)++] = p; p++; } }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_first_c(const cdada_str_t* str, char* c){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!c) return CDADA_E_INVALID; std::string& s = *m->str; if(s.length() == 0) return CDADA_E_EMPTY; try{ *c = *s.begin(); }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_get_c(const cdada_str_t* str, const uint32_t pos, char* c){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!c) return CDADA_E_INVALID; std::string& s = *m->str; if(s.length() == 0) return CDADA_E_EMPTY; if(pos >= s.length()) return CDADA_E_INVALID; try{ *c = s[pos]; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_last_c(const cdada_str_t* str, char* c){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!c) return CDADA_E_INVALID; std::string& s = *m->str; if(s.length() == 0) return CDADA_E_EMPTY; try{ *c = *s.rbegin(); }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } //Manipulation int cdada_str_set(cdada_str_t* str, const char* substr){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr) return CDADA_E_INVALID; std::string& s = *m->str; try{ s = substr; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_append(cdada_str_t* str, const char* substr){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr) return CDADA_E_INVALID; std::string& s = *m->str; try{ s.append(substr); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_trim(cdada_str_t* str, const uint32_t n){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!n) return CDADA_SUCCESS; std::string& s = *m->str; if(s.length() < n) return CDADA_E_INVALID; try{ s.resize(s.length() - n); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_insert(cdada_str_t* str, uint32_t pos, const char* substr){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr) return CDADA_E_INVALID; std::string& s = *m->str; if(pos > s.length()) return CDADA_E_INVALID; try{ s.insert(pos, substr); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_erase(cdada_str_t* str, const uint32_t pos, const uint32_t substr_len){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!substr_len) return CDADA_SUCCESS; std::string& s = *m->str; if(pos > s.length() || (pos+substr_len) > s.length() ) return CDADA_E_INVALID; try{ s.erase(pos, substr_len); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int __cdada_str_lower_upper(cdada_str_t* str, bool lower){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); std::string& s = *m->str; try{ if(lower) std::transform(s.begin(), s.end(), s.begin(), ::tolower); else std::transform(s.begin(), s.end(), s.begin(), ::toupper); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_lower(cdada_str_t* str){ return __cdada_str_lower_upper(str, true); } int cdada_str_upper(cdada_str_t* str){ return __cdada_str_lower_upper(str, false); } int cdada_str_replace_all(cdada_str_t* str, const char* match, const char* new_str){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!match || !new_str) return CDADA_E_INVALID; std::string& s = *m->str; try{ size_t pos = s.find(match); size_t l = strlen(match); while(pos != string::npos){ s.replace(pos, l, new_str); pos += l; pos = s.find(match, pos); } }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_str_replace(cdada_str_t* str, const char* match, const char* new_str, const uint32_t pos){ __cdada_str_int_t* m = (__cdada_str_int_t*)str; CDADA_CHECK_MAGIC(m); if(!match || !new_str) return CDADA_E_INVALID; std::string& s = *m->str; size_t l = strlen(match); if(pos+l > s.length()) return CDADA_E_INVALID; try{ std::size_t it; it = s.find(match, pos); if(it != std::string::npos) s.replace(it, l, new_str); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/libcdada/src/Makefile.am0000644000175000017500000000072114354105336022000 0ustar paolopaoloMAINTAINERCLEANFILES = Makefile.in lib_LTLIBRARIES = libcdada.la libcdada_la_SOURCES = bbitmap.cc \ list.cc \ map.cc \ queue.cc \ set.cc \ stack.cc \ str.cc \ utils.c libcdada_la_CPPFLAGS = -I$(top_builddir)/include/ -I$(top_srcdir)/include/ -D__CDADA_INTERNAL_INCLUDE libcdada_la_LIBADD = pmacct-1.7.8/src/external_libs/libcdada/src/bbitmap.cc0000644000175000017500000000552114354105336021674 0ustar paolopaolo#include "cdada/bbitmap.h" #include "cdada/__common_internal.h" #include #include using namespace std; cdada_bbitmap_t* cdada_bbitmap_create(uint32_t n_bits){ cdada_bbitmap_t* b; if(n_bits == 0) return NULL; b = (cdada_bbitmap_t*)malloc(sizeof(cdada_bbitmap_t)); if(!b) return NULL; b->magic_num = CDADA_MAGIC; b->n_words = (n_bits%64 > 0)? (n_bits/64)+1 : n_bits/64; b->ptr = (uint64_t*)malloc(b->n_words*8); if(!b->ptr){ free(b); return NULL; } memset(b->ptr, 0, b->n_words*8); return b; } int cdada_bbitmap_destroy(cdada_bbitmap_t* b){ CDADA_CHECK_MAGIC(b); b->magic_num = 0x0; free(b->ptr); free(b); return CDADA_SUCCESS; } int cdada_bbitmap_set(cdada_bbitmap_t* b, const uint32_t bit){ CDADA_CHECK_MAGIC(b); if(bit >= (b->n_words*64)) return CDADA_E_INVALID; b->ptr[bit/64] |= (1ULL << (bit%64)); return CDADA_SUCCESS; } int cdada_bbitmap_set_all(cdada_bbitmap_t* b){ CDADA_CHECK_MAGIC(b); memset(b->ptr, 0xFF, b->n_words*8); return CDADA_SUCCESS; } bool cdada_bbitmap_is_set(cdada_bbitmap_t* b, const uint32_t bit){ CDADA_CHECK_MAGIC(b); if(bit >= (b->n_words*64)) return false; return (b->ptr[bit/64] & (1ULL << (bit%64))) > 0ULL; } int cdada_bbitmap_clear(cdada_bbitmap_t* b, const uint32_t bit){ CDADA_CHECK_MAGIC(b); if(bit >= (b->n_words*64)) return CDADA_E_INVALID; b->ptr[bit/64] &= ~(1ULL << (bit%64)); return CDADA_SUCCESS; } int cdada_bbitmap_clear_all(cdada_bbitmap_t* b){ CDADA_CHECK_MAGIC(b); memset(b->ptr, 0x0, b->n_words*8); return CDADA_SUCCESS; } static inline void __cdada_bbitmap_dump_word(uint32_t word_index, uint64_t* word, stringstream& ss){ uint8_t i; bool set; char c; for(i=0;i<64; ++i){ set = (1ULL<n_words; ++i) __cdada_bbitmap_dump_word(i, &b->ptr[i], ss); if(!buffer){ *size_used = ss.str().length()+1; return CDADA_SUCCESS; } snprintf(buffer, size, "%s", ss.str().c_str()); if(ss.str().length()+1 > size) return CDADA_E_INCOMPLETE; }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } int cdada_bbitmap_print(cdada_bbitmap_t* b, FILE *stream){ uint32_t i; CDADA_CHECK_MAGIC(b); try{ std::stringstream ss; for(i=0;in_words; ++i) __cdada_bbitmap_dump_word(i, &b->ptr[i], ss); fprintf(stream, "%s", ss.str().c_str()); }catch(bad_alloc& e){ return CDADA_E_MEM; }catch(...){ CDADA_ASSERT(0); return CDADA_E_UNKNOWN; } return CDADA_SUCCESS; } pmacct-1.7.8/src/external_libs/Makefile.am0000644000175000017500000000527514354105275017501 0ustar paolopaolo#Build all submodule deps BUILT_SOURCES = submodule_deps CLEANFILES = .libcdada_mark #NOTE some pmacct users _love_ vintage software, and they run versions of git # (like v1.8.3) which don't support initializing submodules from anywhere other # than the root.... sigh .PHONY: libcdada libcdada_maintainer_clean ## ## LIBCDADA ## libcdada: @not_git=0; \ if [ -z "`git rev-parse HEAD 2> /dev/null`" ]; then \ if [ -f "$(abs_srcdir)/libcdada/include/cdada.h" ]; then \ not_git=1; \ PMACCT_EXT_LIBS_DONT_SYNC=1; \ cd $(abs_builddir); \ else \ echo "[dep: libcdada] Skipping, not a git repository and code not in tree!"; \ exit 0;\ fi;\ fi;\ echo "[dep: libcdada] Checking..."; \ if [ $$not_git -eq 0 ] && [ ! -f "$(abs_srcdir)/libcdada/.git" ]; then \ echo "[dep: libcdada] Cloning and checking out commit..";\ cd $(abs_top_srcdir); \ git submodule update --init --recursive src/external_libs/libcdada; \ if [ $$? != 0 ]; then exit 1; fi;\ cd $(abs_builddir); \ fi;\ if [ ! -f $(abs_builddir)/.libcdada_mark ] || \ [ "`cat $(abs_builddir)/.libcdada_mark 2> /dev/null`" != "`git ls-tree HEAD $(abs_srcdir)/libcdada/ | awk '{print $$3}' 2> /dev/null`" ] || \ [ "`cat $(abs_builddir)/.libcdada_mark 2> /dev/null`" != "`cd $(abs_srcdir)/libcdada && git rev-parse HEAD 2> /dev/null`" ]; then \ \ if [ -z "$$PMACCT_EXT_LIBS_DONT_SYNC" ]; then \ echo "[dep: libcdada] Syncing commit...";\ cd $(abs_top_srcdir); \ git submodule update --init --recursive src/external_libs/libcdada 2> /dev/null; \ if [ $$? != 0 ]; then exit 1; fi;\ cd $(abs_builddir); \ else\ echo "[dep: libcdada] Skipping commit sync..";\ fi;\ echo "[dep: libcdada] Building...";\ mkdir -p $(abs_builddir)/libcdada/build || true; \ cd $(abs_srcdir)/libcdada/ && \ ./autogen.sh &&\ cd $(abs_builddir)/libcdada/build && \ $(abs_srcdir)/libcdada/configure --disable-shared --host=$(host_alias) @configure_silent_rules_val@ \ --prefix=$(abs_builddir)/rootfs && make $(MAKE_JOBS) install;\ if [ $$? != 0 ]; then exit 1; fi; \ echo "`cd $(abs_srcdir)/libcdada && git rev-parse HEAD 2> /dev/null`" > $(abs_builddir)/.libcdada_mark;\ if [ $$? != 0 ]; then exit 1; fi; \ echo "[dep: libcdada] Done!";\ else\ echo "[dep: libcdada] Up-to-date!";\ fi libcdada_maintainer_clean: @rm -rf $(builddir)/libcdada/build/* submodule_prep: @mkdir -p $(builddir)/rootfs #List all of them here submodule_deps: submodule_prep libcdada #Deep cleanup maintainer-clean-local: libcdada_maintainer_clean rm -rf $(abs_builddir)/rootfs #Placed abnormally here, just because vim syntax highlighter has a bug MAKE_JOBS := `ps T | sed -n 's/.*$(MAKE_PID).*$(MAKE).* \(-j\|--jobs=\) *\([0-9][0-9]*\).*/-j \2/p'` pmacct-1.7.8/src/linklist.c0000644000175000017500000001370014354105275014577 0ustar paolopaolo/* Generic linked list routine. * Copyright (C) 1997, 2000 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "linklist.h" /* Allocate new list. */ struct pm_list * pm_list_new (void) { return calloc(1, sizeof (struct pm_list)); } /* Free list. */ void pm_list_free (struct pm_list *l) { free(l); } /* Allocate new listnode. Internal use only. */ static struct pm_listnode * pm_listnode_new (void) { return calloc(1, sizeof (struct pm_listnode)); } /* Free listnode. */ static void pm_listnode_free (struct pm_listnode *node) { free(node); } /* Add new data to the list. */ void pm_listnode_add (struct pm_list *list, void *val) { struct pm_listnode *node; assert (val != NULL); node = pm_listnode_new (); node->prev = list->tail; node->data = val; if (list->head == NULL) list->head = node; else list->tail->next = node; list->tail = node; list->count++; } /* * Add a node to the list. If the list was sorted according to the * cmp function, insert a new node with the given val such that the * list remains sorted. The new node is always inserted; there is no * notion of omitting duplicates. */ void pm_listnode_add_sort (struct pm_list *list, void *val) { struct pm_listnode *n; struct pm_listnode *new; assert (val != NULL); new = pm_listnode_new (); new->data = val; if (list->cmp) { for (n = list->head; n; n = n->next) { if ((*list->cmp) (val, n->data) < 0) { new->next = n; new->prev = n->prev; if (n->prev) n->prev->next = new; else list->head = new; n->prev = new; list->count++; return; } } } new->prev = list->tail; if (list->tail) list->tail->next = new; else list->head = new; list->tail = new; list->count++; } void pm_listnode_add_after (struct pm_list *list, struct pm_listnode *pp, void *val) { struct pm_listnode *nn; assert (val != NULL); nn = pm_listnode_new (); nn->data = val; if (pp == NULL) { if (list->head) list->head->prev = nn; else list->tail = nn; nn->next = list->head; nn->prev = pp; list->head = nn; } else { if (pp->next) pp->next->prev = nn; else list->tail = nn; nn->next = pp->next; nn->prev = pp; pp->next = nn; } list->count++; } /* Delete specific date pointer from the list. */ void pm_listnode_delete (struct pm_list *list, void *val) { struct pm_listnode *node; assert(list); for (node = list->head; node; node = node->next) { if (node->data == val) { if (node->prev) node->prev->next = node->next; else list->head = node->next; if (node->next) node->next->prev = node->prev; else list->tail = node->prev; list->count--; pm_listnode_free (node); return; } } } /* Return first node's data if it is there. */ void * pm_listnode_head (struct pm_list *list) { struct pm_listnode *node; assert(list); node = list->head; if (node) return node->data; return NULL; } /* Delete all listnode from the list. */ void pm_list_delete_all_node (struct pm_list *list) { struct pm_listnode *node; struct pm_listnode *next; assert(list); for (node = list->head; node; node = next) { next = node->next; if (list->del) (*list->del) (node->data); pm_listnode_free (node); } list->head = list->tail = NULL; list->count = 0; } /* Delete all listnode then free list itself. */ void pm_list_delete (struct pm_list *list) { assert(list); pm_list_delete_all_node (list); pm_list_free (list); } /* Lookup the node which has given data. */ struct pm_listnode * pm_listnode_lookup (struct pm_list *list, void *data) { struct pm_listnode *node; assert(list); for (node = pm_listhead(list); node; node = pm_listnextnode (node)) if (data == pm_listgetdata (node)) return node; return NULL; } /* Delete the node from list. For ospfd and ospf6d. */ void pm_list_delete_node (struct pm_list *list, struct pm_listnode *node) { if (node->prev) node->prev->next = node->next; else list->head = node->next; if (node->next) node->next->prev = node->prev; else list->tail = node->prev; list->count--; pm_listnode_free (node); } /* ospf_spf.c */ void pm_list_add_node_prev (struct pm_list *list, struct pm_listnode *current, void *val) { struct pm_listnode *node; assert (val != NULL); node = pm_listnode_new (); node->next = current; node->data = val; if (current->prev == NULL) list->head = node; else current->prev->next = node; node->prev = current->prev; current->prev = node; list->count++; } /* ospf_spf.c */ void pm_list_add_node_next (struct pm_list *list, struct pm_listnode *current, void *val) { struct pm_listnode *node; assert (val != NULL); node = pm_listnode_new (); node->prev = current; node->data = val; if (current->next == NULL) list->tail = node; else current->next->prev = node; node->next = current->next; current->next = node; list->count++; } /* ospf_spf.c */ void pm_list_add_list (struct pm_list *l, struct pm_list *m) { struct pm_listnode *n; for (n = pm_listhead (m); n; n = pm_listnextnode (n)) pm_listnode_add (l, n->data); } pmacct-1.7.8/src/ip_frag.h0000644000175000017500000000664514354105275014374 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef IP_FRAG_H #define IP_FRAG_H /* defines */ #define IPFT_HASHSZ 256 #define IPF_TIMEOUT 60 #define PRUNE_INTERVAL 7200 #define EMER_PRUNE_INTERVAL 60 #define PRUNE_OFFSET 1800 #define DEFAULT_FRAG_BUFFER_SIZE 4096000 /* 4 Mb */ /* structures */ struct ip_fragment { unsigned char tlhdr[8]; /* upper level info */ u_int8_t got_first; /* got first packet ? */ u_int16_t a; /* bytes accumulator */ u_int16_t pa; /* packets accumulator */ time_t deadline; /* timeout timestamp */ u_int16_t ip_id; u_int8_t ip_p; u_int32_t ip_src; u_int32_t ip_dst; u_int16_t bucket; struct ip_fragment *lru_next; struct ip_fragment *lru_prev; struct ip_fragment *next; struct ip_fragment *prev; }; struct lru_l { struct ip_fragment *root; struct ip_fragment *last; }; struct ip6_fragment { unsigned char tlhdr[8]; /* upper level info */ u_int8_t got_first; /* got first packet ? */ u_int16_t a; /* bytes accumulator */ u_int16_t pa; /* packets accumulator */ time_t deadline; /* timeout timestamp */ u_int32_t id; u_int32_t src[4]; u_int32_t dst[4]; u_int16_t bucket; struct ip6_fragment *lru_next; struct ip6_fragment *lru_prev; struct ip6_fragment *next; struct ip6_fragment *prev; }; struct lru_l6 { struct ip6_fragment *root; struct ip6_fragment *last; }; /* global vars */ extern struct ip_fragment *ipft[IPFT_HASHSZ]; extern struct lru_l lru_list; extern struct ip6_fragment *ipft6[IPFT_HASHSZ]; extern struct lru_l6 lru_list6; /* prototypes */ extern void enable_ip_fragment_handler(); extern void init_ip_fragment_handler(); /* wrapper */ extern void init_ip4_fragment_handler(); extern int ip_fragment_handler(struct packet_ptrs *); extern int find_fragment(u_int32_t, struct packet_ptrs *); extern int create_fragment(u_int32_t, struct ip_fragment *, u_int8_t, unsigned int, struct packet_ptrs *); extern unsigned int hash_fragment(u_int16_t, u_int32_t, u_int32_t, u_int8_t); extern void prune_old_fragments(u_int32_t, u_int32_t); extern void notify_orphan_fragment(struct ip_fragment *); extern void init_ip6_fragment_handler(); extern int ip6_fragment_handler(struct packet_ptrs *, struct ip6_frag *); extern unsigned int hash_fragment6(u_int32_t, struct in6_addr *, struct in6_addr *); extern int find_fragment6(u_int32_t, struct packet_ptrs *, struct ip6_frag *); extern int create_fragment6(u_int32_t, struct ip6_fragment *, u_int8_t, unsigned int, struct packet_ptrs *, struct ip6_frag *); extern void prune_old_fragments6(u_int32_t, u_int32_t); extern void notify_orphan_fragment6(struct ip6_fragment *); #endif //IP_FRAG_H pmacct-1.7.8/src/mongodb_plugin.c0000644000175000017500000012014714354105275015755 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "mongodb_plugin.h" #include "ip_flow.h" #include "classifier.h" #include "crc32.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif /* Global variables */ mongo db_conn; /* Functions */ void mongodb_legacy_warning(int pipe_fd, struct configuration *cfgptr, void *ptr) { Log(LOG_WARNING, "WARN ( %s/%s ): =======\n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): MongoDB plugin is in the process of being discontinued.\n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): MongoDB plugin can still be used via the 'mongodb_legacy' keyword, ie.:\n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): \n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): plugins: mongodb_legacy[abc]\n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): \n", config.name, config.type); Log(LOG_WARNING, "WARN ( %s/%s ): %s: %s\n", config.name, config.type, GET_IN_TOUCH_MSG, MANTAINER); Log(LOG_WARNING, "WARN ( %s/%s ): =======\n", config.name, config.type); exit_gracefully(0); } void mongodb_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; unsigned char *pipebuf; struct pollfd pfd; struct insert_data idata; int refresh_timeout, ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; unsigned char *dataptr; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "MongoDB Plugin", config.name); P_set_signals(); P_init_default_values(); P_config_checks(); pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); if (!config.mongo_insert_batch) config.mongo_insert_batch = DEFAULT_MONGO_INSERT_BATCH; /* setting function pointers */ if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) insert_func = P_sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) insert_func = P_sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) insert_func = P_sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) insert_func = P_sum_mac_insert; #endif else insert_func = P_cache_insert; purge_func = MongoDB_cache_purge; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); memset(&idata, 0, sizeof(idata)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); set_primptrs_funcs(&extras); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); idata.now = time(NULL); /* print_refresh time init: deadline */ refresh_deadline = idata.now; P_init_refresh_deadline(&refresh_deadline, config.sql_refresh_time, config.sql_startup_delay, config.sql_history_roundoff); if (config.sql_history) { basetime_init = P_init_historical_acct; basetime_eval = P_eval_historical_acct; basetime_cmp = P_cmp_historical_acct; (*basetime_init)(idata.now); } /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; mongo_init(&db_conn); mongo_set_op_timeout(&db_conn, 1000); bson_set_oid_fuzz(&MongoDB_oid_fuzz); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: P_update_time_reference(&idata); if (idata.now > refresh_deadline) P_cache_handle_flush_event(&pt, &prt, &tost); recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 "plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 "seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } void MongoDB_cache_purge(struct chained_cache *queue[], int index, int safe_action) { struct pkt_primitives *data = NULL; struct pkt_bgp_primitives *pbgp = NULL; struct pkt_nat_primitives *pnat = NULL; struct pkt_mpls_primitives *pmpls = NULL; struct pkt_tunnel_primitives *ptun = NULL; u_char *pcust = NULL; struct pkt_vlen_hdr_primitives *pvlen = NULL; struct pkt_bgp_primitives empty_pbgp; struct pkt_nat_primitives empty_pnat; struct pkt_mpls_primitives empty_pmpls; struct pkt_tunnel_primitives empty_ptun; u_char *empty_pcust = NULL; char src_mac[18], dst_mac[18], src_host[INET6_ADDRSTRLEN], dst_host[INET6_ADDRSTRLEN], ip_address[INET6_ADDRSTRLEN]; char rd_str[SRVBUFLEN], misc_str[SRVBUFLEN], tmpbuf[SRVBUFLEN], mongo_database[SRVBUFLEN]; char *str_ptr, *as_path, *bgp_comm, default_table[] = "test.acct"; char default_user[] = "pmacct", default_passwd[] = "arealsmartpwd"; int qn = 0, i, j, stop, db_status, batch_idx, go_to_pending, saved_index = index; time_t stamp, start, duration; char current_table[SRVBUFLEN], elem_table[SRVBUFLEN]; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); #if defined (WITH_NDPI) char ndpi_class[SUPERSHORTBUFLEN]; #endif const bson **bson_batch; bson *bson_elem; if (!index) { Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: 0/0, ET: X) ***\n", config.name, config.type, writer_pid); return; } if (config.sql_host) db_status = mongo_client(&db_conn, config.sql_host, 27017 /* default port */); else db_status = mongo_client(&db_conn, "127.0.0.1", 27017 /* default port */); if (db_status != MONGO_OK) { switch (db_conn.err) { case MONGO_CONN_SUCCESS: Log(LOG_INFO, "INFO ( %s/%s ): Connection succeeded (MONGO_CONN_SUCCESS) to MongoDB\n", config.name, config.type); break; case MONGO_CONN_NO_SOCKET: Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to MongoDB: no socket\n", config.name, config.type); return; case MONGO_CONN_NOT_MASTER: Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to MongoDB: not master\n", config.name, config.type); return; case MONGO_CONN_FAIL: default: Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to MongoDB\n", config.name, config.type); return; } } else Log(LOG_INFO, "INFO ( %s/%s ): Connection succeeded (MONGO_OK) to MongoDB\n", config.name, config.type); empty_pcust = malloc(config.cpptrs.len); if (!empty_pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() empty_pcust. Exiting.\n", config.name, config.type); exit_gracefully(1); } memset(&empty_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&empty_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&empty_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&empty_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(empty_pcust, 0, config.cpptrs.len); memset(mongo_database, 0, sizeof(mongo_database)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); memset(tmpbuf, 0, sizeof(tmpbuf)); if (!config.sql_table || MongoDB_get_database(mongo_database, SRVBUFLEN, config.sql_table)) { config.sql_table = default_table; Log(LOG_INFO, "INFO ( %s/%s ): mongo_table set to '%s'\n", config.name, config.type, default_table); } if (strchr(config.sql_table, '%') || strchr(config.sql_table, '$')) { dyn_table = TRUE; if (!strchr(config.sql_table, '$')) dyn_table_time_only = TRUE; else dyn_table_time_only = FALSE; } else { dyn_table = FALSE; dyn_table_time_only = FALSE; } bson_batch = malloc(sizeof(bson *) * index); if (!bson_batch) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed: bson_batch\n", config.name, config.type); return; } /* If there is any signs of auth in the config, then try to auth */ if (config.sql_user || config.sql_passwd) { if (!config.sql_user) config.sql_user = default_user; if (!config.sql_passwd) config.sql_passwd = default_passwd; db_status = mongo_cmd_authenticate(&db_conn, mongo_database, config.sql_user, config.sql_passwd); if (db_status != MONGO_OK) { Log(LOG_ERR, "ERROR ( %s/%s ): Authentication failed to MongoDB\n", config.name, config.type); return; } else Log(LOG_INFO, "INFO ( %s/%s ): Successful authentication (MONGO_OK) to MongoDB\n", config.name, config.type); } Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); for (j = 0, stop = 0; (!stop) && P_preprocess_funcs[j]; j++) stop = P_preprocess_funcs[j](queue, &index, j); memcpy(pending_queries_queue, queue, index*sizeof(struct db_cache *)); pqq_ptr = index; start: memcpy(queue, pending_queries_queue, pqq_ptr*sizeof(struct db_cache *)); memset(pending_queries_queue, 0, pqq_ptr*sizeof(struct db_cache *)); index = pqq_ptr; pqq_ptr = 0; if (dyn_table) { stamp = queue[0]->basetime.tv_sec; prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[0]); handle_dynname_internal_strings(current_table, SRVBUFLEN, config.sql_table, &prim_ptrs, DYN_STR_MONGODB_TABLE); pm_strftime_same(current_table, SRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (config.sql_table_schema) MongoDB_create_indexes(&db_conn, tmpbuf); } for (j = 0, batch_idx = 0; j < index; j++) { go_to_pending = FALSE; if (queue[j]->valid != PRINT_CACHE_COMMITTED) continue; if (dyn_table && (!dyn_table_time_only || !config.nfacctd_time_new || (config.sql_refresh_time != timeslot))) { time_t stamp = 0; stamp = queue[j]->basetime.tv_sec; prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(elem_table, SRVBUFLEN, config.sql_table, &prim_ptrs, DYN_STR_MONGODB_TABLE); pm_strftime_same(elem_table, SRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (strncmp(current_table, elem_table, SRVBUFLEN)) { pending_queries_queue[pqq_ptr] = queue[j]; pqq_ptr++; go_to_pending = TRUE; } } if (!go_to_pending) { bson_elem = (bson *) malloc(sizeof(bson)); if (!bson_elem) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed: bson_elem (elem# %u batch# %u\n", config.name, config.type, j, batch_idx); return; } bson_init(bson_elem); bson_append_new_oid(bson_elem, "_id" ); data = &queue[j]->primitives; if (queue[j]->pbgp) pbgp = queue[j]->pbgp; else pbgp = &empty_pbgp; if (queue[j]->pnat) pnat = queue[j]->pnat; else pnat = &empty_pnat; if (queue[j]->pmpls) pmpls = queue[j]->pmpls; else pmpls = &empty_pmpls; if (queue[j]->ptun) ptun = queue[j]->ptun; else ptun = &empty_ptun; if (queue[j]->pcust) pcust = queue[j]->pcust; else pcust = empty_pcust; if (queue[j]->pvlen) pvlen = queue[j]->pvlen; else pvlen = NULL; if (queue[j]->valid == PRINT_CACHE_FREE) continue; if (config.what_to_count & COUNT_TAG) bson_append_long(bson_elem, "tag", data->tag); if (config.what_to_count & COUNT_TAG2) bson_append_long(bson_elem, "tag2", data->tag2); if (config.what_to_count_2 & COUNT_LABEL) MongoDB_append_string(bson_elem, "label", pvlen, COUNT_INT_LABEL); if (config.what_to_count & COUNT_CLASS) bson_append_string(bson_elem, "class", ((data->class && class[(data->class)-1].id) ? class[(data->class)-1].protocol : "unknown" )); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) { snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.app_protocol)); bson_append_string(bson_elem, "class", ndpi_class); } #endif #if defined (HAVE_L2) if (config.what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { etheraddr_string(data->eth_shost, src_mac); bson_append_string(bson_elem, "mac_src", src_mac); } if (config.what_to_count & COUNT_DST_MAC) { etheraddr_string(data->eth_dhost, dst_mac); bson_append_string(bson_elem, "mac_dst", dst_mac); } if (config.what_to_count & COUNT_VLAN) { if (config.tmp_vlan_legacy) { bson_append_int(bson_elem, "vlan", data->vlan_id); } else { bson_append_int(bson_elem, "vlan_in", data->vlan_id); } } if (config.what_to_count_2 & COUNT_OUT_VLAN) { bson_append_int(bson_elem, "vlan_out", data->out_vlan_id); } if (config.what_to_count & COUNT_COS) bson_append_int(bson_elem, "cos", data->cos); if (config.what_to_count & COUNT_ETHERTYPE) { sprintf(misc_str, "%x", data->etype); bson_append_string(bson_elem, "etype", misc_str); } #endif if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) bson_append_int(bson_elem, "as_src", data->src_as); if (config.what_to_count & COUNT_DST_AS) bson_append_int(bson_elem, "as_dst", data->dst_as); if (config.what_to_count & COUNT_STD_COMM) { vlen_prims_get(pvlen, COUNT_INT_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "comms", pvlen, COUNT_INT_STD_COMM); } if (config.what_to_count & COUNT_EXT_COMM) { vlen_prims_get(pvlen, COUNT_INT_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "ecomms", pvlen, COUNT_INT_EXT_COMM); } if (config.what_to_count_2 & COUNT_LRG_COMM) { vlen_prims_get(pvlen, COUNT_INT_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "lcomms", pvlen, COUNT_INT_LRG_COMM); } if (config.what_to_count & COUNT_AS_PATH) { vlen_prims_get(pvlen, COUNT_INT_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } MongoDB_append_string(bson_elem, "as_path", pvlen, COUNT_INT_AS_PATH); } if (config.what_to_count & COUNT_LOCAL_PREF) bson_append_int(bson_elem, "local_pref", pbgp->local_pref); if (config.what_to_count & COUNT_MED) bson_append_int(bson_elem, "med", pbgp->med); if (config.what_to_count_2 & COUNT_DST_ROA) bson_append_string(bson_elem, "roa_dst", rpki_roa_print(pbgp->dst_roa)); if (config.what_to_count & COUNT_PEER_SRC_AS) bson_append_int(bson_elem, "peer_as_src", pbgp->peer_src_as); if (config.what_to_count & COUNT_PEER_DST_AS) bson_append_int(bson_elem, "peer_as_dst", pbgp->peer_dst_as); if (config.what_to_count & COUNT_PEER_SRC_IP) { addr_to_str(ip_address, &pbgp->peer_src_ip); bson_append_string(bson_elem, "peer_ip_src", ip_address); } if (config.what_to_count & COUNT_PEER_DST_IP) { addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(queue[j]->flow_type)); bson_append_string(bson_elem, "peer_ip_dst", ip_address); } if (config.what_to_count & COUNT_SRC_STD_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "src_comms", pvlen, COUNT_INT_SRC_STD_COMM); } if (config.what_to_count & COUNT_SRC_EXT_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "src_ecomms", pvlen, COUNT_INT_SRC_EXT_COMM); } if (config.what_to_count_2 & COUNT_SRC_LRG_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } MongoDB_append_string(bson_elem, "src_lcomms", pvlen, COUNT_INT_SRC_LRG_COMM); } if (config.what_to_count & COUNT_SRC_AS_PATH) { vlen_prims_get(pvlen, COUNT_INT_SRC_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } MongoDB_append_string(bson_elem, "src_as_path", pvlen, COUNT_INT_SRC_AS_PATH); } if (config.what_to_count & COUNT_SRC_LOCAL_PREF) bson_append_int(bson_elem, "src_local_pref", pbgp->src_local_pref); if (config.what_to_count & COUNT_SRC_MED) bson_append_int(bson_elem, "src_med", pbgp->src_med); if (config.what_to_count_2 & COUNT_SRC_ROA) bson_append_string(bson_elem, "roa_src", rpki_roa_print(pbgp->src_roa)); if (config.what_to_count & COUNT_IN_IFACE) bson_append_int(bson_elem, "iface_in", data->ifindex_in); if (config.what_to_count & COUNT_OUT_IFACE) bson_append_int(bson_elem, "iface_out", data->ifindex_out); if (config.what_to_count & COUNT_MPLS_VPN_RD) { bgp_rd2str(rd_str, &pbgp->mpls_vpn_rd); bson_append_string(bson_elem, "mpls_vpn_rd", rd_str); } if (config.what_to_count_2 & COUNT_MPLS_PW_ID) bson_append_int(bson_elem, "mpls_pw_id", pbgp->mpls_pw_id); if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { addr_to_str(src_host, &data->src_ip); bson_append_string(bson_elem, "ip_src", src_host); } if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { addr_to_str(src_host, &data->src_net); bson_append_string(bson_elem, "net_src", src_host); } if (config.what_to_count & COUNT_DST_HOST) { addr_to_str(dst_host, &data->dst_ip); bson_append_string(bson_elem, "ip_dst", dst_host); } if (config.what_to_count & COUNT_DST_NET) { addr_to_str(dst_host, &data->dst_net); bson_append_string(bson_elem, "net_dst", dst_host); } if (config.what_to_count & COUNT_SRC_NMASK) bson_append_int(bson_elem, "mask_src", data->src_nmask); if (config.what_to_count & COUNT_DST_NMASK) bson_append_int(bson_elem, "mask_dst", data->dst_nmask); if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) bson_append_int(bson_elem, "port_src", data->src_port); if (config.what_to_count & COUNT_DST_PORT) bson_append_int(bson_elem, "port_dst", data->dst_port); #if defined (WITH_GEOIP) if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) { if (data->src_ip_country.id > 0) bson_append_string(bson_elem, "country_ip_src", GeoIP_code_by_id(data->src_ip_country.id)); else bson_append_null(bson_elem, "country_ip_src"); } if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) { if (data->dst_ip_country.id > 0) bson_append_string(bson_elem, "country_ip_dst", GeoIP_code_by_id(data->dst_ip_country.id)); else bson_append_null(bson_elem, "country_ip_dst"); } #endif #if defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) { if (strlen(data->src_ip_country.str)) bson_append_string(bson_elem, "country_ip_src", data->src_ip_country.str); else bson_append_null(bson_elem, "country_ip_src"); } if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) { if (strlen(data->dst_ip_country.str)) bson_append_string(bson_elem, "country_ip_dst", data->dst_ip_country.str); else bson_append_null(bson_elem, "country_ip_dst"); } if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) { if (strlen(data->src_ip_pocode.str)) bson_append_string(bson_elem, "pocode_ip_src", data->src_ip_pocode.str); else bson_append_null(bson_elem, "pocode_ip_src"); } if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) { if (strlen(data->dst_ip_pocode.str)) bson_append_string(bson_elem, "pocode_ip_dst", data->dst_ip_pocode.str); else bson_append_null(bson_elem, "pocode_ip_dst"); } if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) { bson_append_double(bson_elem, "lat_ip_src", data->src_ip_lat); bson_append_double(bson_elem, "lon_ip_src", data->src_ip_lon); } if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) { bson_append_double(bson_elem, "lat_ip_dst", data->dst_ip_lat); bson_append_double(bson_elem, "lon_ip_dst", data->dst_ip_lon); } #endif if (config.what_to_count & COUNT_TCPFLAGS) { sprintf(misc_str, "%u", queue[j]->tcp_flags); bson_append_string(bson_elem, "tcp_flags", misc_str); } if (config.what_to_count & COUNT_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; bson_append_string(bson_elem, "ip_proto", ip_proto_print(data->proto, proto, PROTO_NUM_STRLEN)); } if (config.what_to_count & COUNT_IP_TOS) bson_append_int(bson_elem, "tos", data->tos); if (config.what_to_count_2 & COUNT_SAMPLING_RATE) bson_append_int(bson_elem, "sampling_rate", data->sampling_rate); if (config.what_to_count_2 & COUNT_SAMPLING_DIRECTION) bson_append_string(bson_elem, "sampling_direction", sampling_direction_print(data->sampling_direction)); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) { addr_to_str(src_host, &pnat->post_nat_src_ip); bson_append_string(bson_elem, "post_nat_ip_src", src_host); } if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) { addr_to_str(dst_host, &pnat->post_nat_dst_ip); bson_append_string(bson_elem, "post_nat_ip_dst", dst_host); } if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) bson_append_int(bson_elem, "post_nat_port_src", pnat->post_nat_src_port); if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) bson_append_int(bson_elem, "post_nat_port_dst", pnat->post_nat_dst_port); if (config.what_to_count_2 & COUNT_NAT_EVENT) bson_append_int(bson_elem, "nat_event", pnat->nat_event); if (config.what_to_count_2 & COUNT_FW_EVENT) bson_append_int(bson_elem, "fw_event", pnat->fw_event); if (config.what_to_count_2 & COUNT_FWD_STATUS) bson_append_int(bson_elem, "fwd_status", pnat->fwd_status); if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) bson_append_int(bson_elem, "mpls_label_top", pmpls->mpls_label_top); if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) bson_append_int(bson_elem, "mpls_label_bottom", pmpls->mpls_label_bottom); if (config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) { char label_stack[MAX_MPLS_LABEL_STACK]; char *label_stack_ptr = NULL; int label_stack_len = 0; memset(label_stack, 0, MAX_MPLS_LABEL_STACK); label_stack_len = vlen_prims_get(pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); if (label_stack_ptr) { mpls_label_stack_to_str(label_stack, sizeof(label_stack), (u_int32_t *)label_stack_ptr, label_stack_len); } bson_append_int(bson_elem, "mpls_label_stack", label_stack); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) { etheraddr_string(ptun->tunnel_eth_shost, src_mac); bson_append_string(bson_elem, "tunnel_mac_src", src_mac); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) { etheraddr_string(ptun->tunnel_eth_dhost, dst_mac); bson_append_string(bson_elem, "tunnel_mac_dst", dst_mac); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) { addr_to_str(src_host, &ptun->tunnel_src_ip); bson_append_string(bson_elem, "tunnel_ip_src", src_host); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) { addr_to_str(dst_host, &ptun->tunnel_dst_ip); bson_append_string(bson_elem, "tunnel_ip_dst", dst_host); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; bson_append_string(bson_elem, "tunnel_ip_proto", ip_proto_print(ptun->tunnel_proto, proto, PROTO_NUM_STRLEN)); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) bson_append_int(bson_elem, "tunnel_tos", ptun->tunnel_tos); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) bson_append_int(bson_elem, "tunnel_port_src", ptun->tunnel_src_port); if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) bson_append_int(bson_elem, "tunnel_port_dst", ptun->tunnel_dst_port); if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) bson_append_int(bson_elem, "tunnel_tcp_flags", data->tunnel_tcp_flags); if (config.what_to_count_2 & COUNT_VXLAN) bson_append_int(bson_elem, "vxlan", ptun->tunnel_id); if (config.what_to_count_2 & COUNT_TIMESTAMP_START) { if (config.timestamps_since_epoch) { char tstamp_str[SRVBUFLEN]; compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_start, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_start", tstamp_str); } else { bson_date_t bdate; bdate = 1000*pnat->timestamp_start.tv_sec; if (pnat->timestamp_start.tv_usec) bdate += (pnat->timestamp_start.tv_usec/1000); bson_append_date(bson_elem, "timestamp_start", bdate); } } if (config.what_to_count_2 & COUNT_TIMESTAMP_END) { if (config.timestamps_since_epoch) { char tstamp_str[SRVBUFLEN]; compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_end, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_end", tstamp_str); } else { bson_date_t bdate; bdate = 1000*pnat->timestamp_end.tv_sec; if (pnat->timestamp_end.tv_usec) bdate += (pnat->timestamp_end.tv_usec/1000); bson_append_date(bson_elem, "timestamp_end", bdate); } } if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) { if (config.timestamps_since_epoch) { char tstamp_str[SRVBUFLEN]; compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_arrival", tstamp_str); } else { bson_date_t bdate; bdate = 1000*pnat->timestamp_arrival.tv_sec; if (pnat->timestamp_arrival.tv_usec) bdate += (pnat->timestamp_arrival.tv_usec/1000); bson_append_date(bson_elem, "timestamp_arrival", bdate); } } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) { if (config.timestamps_since_epoch) { char tstamp_str[SRVBUFLEN]; compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_export, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_export", tstamp_str); } else { bson_date_t bdate; bdate = 1000*pnat->timestamp_export.tv_sec; if (pnat->timestamp_export.tv_usec) bdate += (pnat->timestamp_export.tv_usec/1000); bson_append_date(bson_elem, "timestamp_export", bdate); } } if (config.nfacctd_stitching && queue[j]->stitch) { if (config.timestamps_since_epoch) { char tstamp_str[SRVBUFLEN]; compose_timestamp(tstamp_str, SRVBUFLEN, &queue[j]->stitch->timestamp_min, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_min", tstamp_str); compose_timestamp(tstamp_str, SRVBUFLEN, &queue[j]->stitch->timestamp_max, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); bson_append_string(bson_elem, "timestamp_max", tstamp_str); } else { bson_date_t bdate_min, bdate_max; bdate_min = 1000*queue[j]->stitch->timestamp_min.tv_sec; if (queue[j]->stitch->timestamp_min.tv_usec) bdate_min += (queue[j]->stitch->timestamp_min.tv_usec/1000); bson_append_date(bson_elem, "timestamp_min", bdate_min); bdate_max = 1000*queue[j]->stitch->timestamp_max.tv_sec; if (queue[j]->stitch->timestamp_max.tv_usec) bdate_max += (queue[j]->stitch->timestamp_max.tv_usec/1000); bson_append_date(bson_elem, "timestamp_max", bdate_max); } } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) bson_append_int(bson_elem, "export_proto_seqno", data->export_proto_seqno); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) bson_append_int(bson_elem, "export_proto_version", data->export_proto_version); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) bson_append_int(bson_elem, "export_proto_sysid", data->export_proto_sysid); /* all custom primitives printed here */ { int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], FALSE); bson_append_string(bson_elem, config.cpptrs.primitive[cp_idx].name, cp_str); } else { char *label_ptr = NULL; vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) bson_append_null(bson_elem, config.cpptrs.primitive[cp_idx].name); else bson_append_string(bson_elem, config.cpptrs.primitive[cp_idx].name, label_ptr); } } } if (config.sql_history) { bson_append_date(bson_elem, "stamp_inserted", (bson_date_t) 1000*queue[j]->basetime.tv_sec); bson_append_date(bson_elem, "stamp_updated", (bson_date_t) 1000*time(NULL)); } if (queue[j]->flow_type != NF9_FTYPE_EVENT && queue[j]->flow_type != NF9_FTYPE_OPTION) { bson_append_long(bson_elem, "packets", queue[j]->packet_counter); if (config.what_to_count & COUNT_FLOWS) bson_append_long(bson_elem, "flows", queue[j]->flow_counter); bson_append_long(bson_elem, "bytes", queue[j]->bytes_counter); } bson_finish(bson_elem); bson_batch[batch_idx] = bson_elem; batch_idx++; qn++; if (config.debug) bson_print(bson_elem); if (batch_idx == config.mongo_insert_batch) { if (dyn_table) db_status = mongo_insert_batch(&db_conn, current_table, bson_batch, batch_idx, NULL, MONGO_CONTINUE_ON_ERROR); else db_status = mongo_insert_batch(&db_conn, config.sql_table, bson_batch, batch_idx, NULL, MONGO_CONTINUE_ON_ERROR); if (db_status != MONGO_OK) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to insert all elements in batch: try a smaller mongo_insert_batch value.\n", config.name, config.type); Log(LOG_ERR, "ERROR ( %s/%s ): Server error: %s. (PID: %u, QN: %u/%u)\n", config.name, config.type, db_conn.lasterrstr, writer_pid, qn, saved_index); } for (i = 0; i < batch_idx; i++) { bson_elem = (bson *) bson_batch[i]; bson_destroy(bson_elem); free(bson_elem); } batch_idx = 0; } } } /* last round on the lollipop */ if (batch_idx) { if (dyn_table) db_status = mongo_insert_batch(&db_conn, current_table, bson_batch, batch_idx, NULL, MONGO_CONTINUE_ON_ERROR); else db_status = mongo_insert_batch(&db_conn, config.sql_table, bson_batch, batch_idx, NULL, MONGO_CONTINUE_ON_ERROR); if (db_status != MONGO_OK) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to insert all elements in batch: try a smaller mongo_insert_batch value.\n", config.name, config.type); Log(LOG_ERR, "ERROR ( %s/%s ): Server error: %s. (PID: %u, QN: %u/%u)\n", config.name, config.type, db_conn.lasterrstr, writer_pid, qn, saved_index); } for (i = 0; i < batch_idx; i++) { bson_elem = (bson *) bson_batch[i]; bson_destroy(bson_elem); free(bson_elem); } batch_idx = 0; } /* If we have pending queries then start again */ if (pqq_ptr) goto start; duration = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, qn, saved_index, duration); if (config.sql_trigger_exec && !safe_action) P_trigger_exec(config.sql_trigger_exec); if (empty_pcust) free(empty_pcust); } int MongoDB_get_database(char *db, int dblen, char *db_table) { char *collection_sep = strchr(db_table, '.'); if (!collection_sep) { Log(LOG_WARNING, "WARN ( %s/%s ): mongo_table '%s' is not in . format.\n", config.name, config.type, config.sql_table); return TRUE; } memset(db, 0, dblen); *collection_sep = '\0'; strlcpy(db, db_table, dblen); *collection_sep = '.'; return FALSE; } void MongoDB_create_indexes(mongo *db_conn, const char *table) { bson idx_key[1]; FILE *f; char buf[LARGEBUFLEN]; char *token, *bufptr; f = fopen(config.sql_table_schema, "r"); if (f) { while (!feof(f)) { if (fgets(buf, SRVBUFLEN, f)) { if (!iscomment(buf) && !isblankline(buf)) { trim_all_spaces(buf); bufptr = buf; bson_init(idx_key); while ((token = extract_token(&bufptr, ','))) { bson_append_int(idx_key, token, 1); } bson_finish(idx_key); mongo_create_index(db_conn, table, idx_key, NULL, 0, -1, NULL); bson_destroy(idx_key); } } } fclose(f); } else Log(LOG_WARNING, "WARN ( %s/%s ): mongo_indexes_file '%s' does not exist.\n", config.name, config.type, config.sql_table_schema); } void MongoDB_append_string(bson *bson_elem, char *name, struct pkt_vlen_hdr_primitives *pvlen, pm_cfgreg_t wtc) { char *str_ptr = NULL; vlen_prims_get(pvlen, wtc, &str_ptr); if (str_ptr) bson_append_string(bson_elem, name, str_ptr); else bson_append_null(bson_elem, name); } int MongoDB_oid_fuzz() { struct timeval now; gettimeofday(&now, NULL); srand((int) now.tv_usec); return rand(); } pmacct-1.7.8/src/pmacct-data.h0000644000175000017500000004120714354105275015134 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PMACCT_DATA_H #define PMACCT_DATA_H /* defines */ #define PLUGIN_ID_CORE 0 #define PLUGIN_ID_MEMORY 1 #define PLUGIN_ID_PRINT 2 #define PLUGIN_ID_NFPROBE 3 #define PLUGIN_ID_SFPROBE 4 #define PLUGIN_ID_MYSQL 5 #define PLUGIN_ID_PGSQL 6 #define PLUGIN_ID_SQLITE3 7 #define PLUGIN_ID_TEE 8 #define PLUGIN_ID_MONGODB 9 #define PLUGIN_ID_AMQP 10 #define PLUGIN_ID_KAFKA 11 #define PLUGIN_ID_UNKNOWN 255 /* vars */ extern int protocols_number; /* structures */ static const struct _primitives_matrix_struct _primitives_matrix[] = { /* primitive, pmacctd, uacctd, nfacctd, sfacctd, pmtelemetryd, pmbgpd, pmbmpd */ {"L2", 1, 1, 1, 1, 0, 0, 0, ""}, {"cos", 1, 0, 1, 1, 0, 0, 0, "Ethernet CoS, 802.1P"}, {"etype", 1, 0, 1, 1, 0, 0, 0, "Ethernet Ethertype"}, {"src_mac", 1, 1, 1, 1, 0, 0, 0, "Source MAC address"}, {"dst_mac", 1, 1, 1, 1, 0, 0, 0, "Destination MAC address"}, {"vlan", 1, 1, 1, 1, 0, 0, 0, "Ethernet VLAN, 802.1Q"}, {"in_vlan", 0, 0, 1, 1, 0, 0, 0, "Input Ethernet VLAN, 802.1Q"}, {"out_vlan", 0, 0, 1, 1, 0, 0, 0, "Output Ethernet VLAN, 802.1Q"}, {"L3", 1, 1, 1, 1, 0, 0, 0, ""}, {"src_host", 1, 1, 1, 1, 0, 0, 0, "Source IPv4/IPv6 address"}, {"dst_host", 1, 1, 1, 1, 0, 0, 0, "Destination IPv4/IPv6 address"}, {"src_mask", 1, 1, 1, 1, 0, 0, 0, "Source network mask"}, {"dst_mask", 1, 1, 1, 1, 0, 0, 0, "Destination network mask"}, {"src_net", 1, 1, 1, 1, 0, 0, 0, "Source IPv4/IPv6 prefix"}, {"dst_net", 1, 1, 1, 1, 0, 0, 0, "Destination IPv4/IPv6 prefix"}, {"proto", 1, 1, 1, 1, 0, 0, 0, "IP protocol"}, {"tos", 1, 1, 1, 1, 0, 0, 0, "IP ToS"}, {"L4", 1, 1, 1, 1, 0, 0, 0, ""}, {"src_port", 1, 1, 1, 1, 0, 0, 0, "Source TCP/UDP port"}, {"dst_port", 1, 1, 1, 1, 0, 0, 0, "Destination TCP/UDP port"}, {"tcpflags", 1, 1, 1, 1, 0, 0, 0, "TCP flags"}, {"BGP", 1, 1, 1, 1, 0, 0, 0, ""}, {"src_as", 1, 1, 1, 1, 0, 0, 0, "Source ASN"}, {"dst_as", 1, 1, 1, 1, 0, 0, 0, "Destination ASN"}, {"as_path", 1, 1, 1, 1, 0, 0, 0, "AS PATH"}, {"std_comm", 1, 1, 1, 1, 0, 0, 0, "Standard Communities"}, {"ext_comm", 1, 1, 1, 1, 0, 0, 0, "Extended Communities"}, {"lrg_comm", 1, 1, 1, 1, 0, 0, 0, "Large Communities"}, {"local_pref", 1, 1, 1, 1, 0, 0, 0, "Local Preference"}, {"med", 1, 1, 1, 1, 0, 0, 0, "Multi-Exit Discriminator"}, {"src_as_path", 1, 1, 1, 1, 0, 0, 0, "Source AS PATH (via reverse BGP lookup)"}, {"src_std_comm", 1, 1, 1, 1, 0, 0, 0, "Source Standard Communities (via reverse BGP lookup)"}, {"src_ext_comm", 1, 1, 1, 1, 0, 0, 0, "Source Extended Communities (via reverse BGP lookup)"}, {"src_lrg_comm", 1, 1, 1, 1, 0, 0, 0, "Source Large Communities (via reverse BGP lookup)"}, {"src_local_pref", 1, 1, 1, 1, 0, 0, 0, "Source Local Preference (by default via reverse BGP lookup)"}, {"src_med", 1, 1, 1, 1, 0, 0, 0, "Source MED (by default via reverse BGP lookup)"}, {"peer_src_as", 1, 1, 1, 1, 0, 0, 0, "Source peer ASN (by default via reverse BGP lookup)"}, {"peer_dst_as", 1, 1, 1, 1, 0, 0, 0, "Destination peer ASN"}, {"peer_dst_ip", 1, 1, 1, 1, 0, 0, 0, "BGP next-hop"}, {"NAT", 1, 1, 1, 1, 0, 0, 0, ""}, {"fw_event", 0, 0, 1, 0, 0, 0, 0, "Firewall event ID"}, {"nat_event", 0, 0, 1, 0, 0, 0, 0, "NAT event ID"}, {"post_nat_src_host", 0, 0, 1, 0, 0, 0, 0, "Source IPv4/IPv6 address after NAT translation"}, {"post_nat_dst_host", 0, 0, 1, 0, 0, 0, 0, "Destination IPv4/IPv6 address after NAT translation"}, {"post_nat_src_port", 0, 0, 1, 0, 0, 0, 0, "Source TCP/UDP port after NAT translation"}, {"post_nat_dst_port", 0, 0, 1, 0, 0, 0, 0, "Destination TCP/UDP port after NAT translation"}, {"TUNNEL", 1, 1, 1, 1, 0, 0, 0, ""}, {"vxlan", 1, 1, 1, 1, 0, 0, 0, "VXLAN Network Identifier"}, {"tunnel_src_mac", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Source MAC address"}, {"tunnel_dst_mac", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Destination MAC address"}, {"tunnel_src_host", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Source IPv4/IPv6 address"}, {"tunnel_dst_host", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Destination IPv4/IPv6 address"}, {"tunnel_proto", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner IP protocol"}, {"tunnel_tos", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner IP ToS"}, {"tunnel_src_port", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Source TCP/UDP port"}, {"tunnel_dst_port", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner Destination TCP/UDP port"}, {"tunnel_tcpflags", 1, 1, 0, 1, 0, 0, 0, "Tunnel inner TCP flags"}, {"MPLS", 1, 1, 1, 1, 0, 0, 0, ""}, {"mpls_label_bottom", 1, 1, 1, 0, 0, 0, 0, "Bottom MPLS label"}, {"mpls_label_top", 1, 1, 1, 0, 0, 0, 0, "Top MPLS label"}, {"mpls_label_stack", 1, 1, 1, 0, 0, 0, 0, "MPLS label stack"}, {"mpls_vpn_rd", 0, 0, 1, 1, 0, 0, 0, "MPLS L3 VPN Route Distinguisher"}, {"mpls_pw_id", 0, 0, 1, 1, 0, 0, 0, "MPLS L2 VPN Pseudowire ID"}, {"MISC", 1, 1, 1, 1, 0, 0, 0, ""}, {"class", 1, 1, 1, 1, 0, 0, 0, "L7 protocol classification"}, {"flows", 0, 0, 1, 0, 0, 0, 0, "IP flows"}, {"src_host_country", 1, 1, 1, 1, 0, 0, 0, "Source IP address GeoIP resolution: country"}, {"dst_host_country", 1, 1, 1, 1, 0, 0, 0, "Destination IP address GeoIP resolution: country"}, {"src_host_pocode", 1, 1, 1, 1, 0, 0, 0, "Source IP address GeoIP resolution: postal code"}, {"dst_host_pocode", 1, 1, 1, 1, 0, 0, 0, "Destination IP address GeoIP resolution: postal code"}, {"src_host_coords", 1, 1, 1, 1, 0, 0, 0, "Source IP address GeoIP resolution: lat/lon coordinates"}, {"dst_host_coords", 1, 1, 1, 1, 0, 0, 0, "Destination IP address GeoIP resolution: lat/lon coordinates"}, {"in_iface", 0, 1, 1, 1, 0, 0, 0, "Input interface, SNMP ifIndex"}, {"out_iface", 0, 1, 1, 1, 0, 0, 0, "Output interface, SNMP ifIndex"}, {"peer_src_ip", 0, 0, 1, 1, 0, 0, 0, "IP address or identificator of telemetry exporting device"}, {"sampling_rate", 1, 1, 1, 1, 0, 0, 0, "Sampling rate"}, {"sampling_direction", 0, 0, 1, 0, 0, 0, 0, "Sampling direction (ie. ingress vs egress)"}, {"tag", 1, 1, 1, 1, 0, 0, 0, "Numeric tag, ie. as result of pre_tag_map evaluation"}, {"tag2", 1, 1, 1, 1, 0, 0, 0, "Numeric tag, ie. as result of pre_tag_map evaluation"}, {"label", 1, 1, 1, 1, 0, 0, 0, "String label, ie. as result of pre_tag_map evaluation"}, {"export_proto_seqno", 0, 0, 1, 1, 0, 0, 0, "Export protocol (ie. NetFlow) sequence number"}, {"export_proto_version", 0, 0, 1, 1, 0, 0, 0, "Export protocol (ie. NetFlow) version"}, {"export_proto_sysid", 0, 0, 1, 1, 0, 0, 0, "Export protocol ID (ie. sFlow subAgentID, IPFIX Obs Domain ID)"}, {"src_roa", 1, 1, 1, 1, 0, 0, 0, "RPKI validation status for source IP prefix"}, {"dst_roa", 1, 1, 1, 1, 0, 0, 0, "RPKI validation status for destination IP prefix"}, {"fwd_status", 0, 0, 1, 0, 0, 0, 0, "Forwarding Status"}, {"TIME", 1, 1, 1, 1, 0, 0, 0, ""}, {"timestamp_start", 0, 0, 1, 0, 0, 0, 0, "Flow start time or observation time at the exporter"}, {"timestamp_end", 0, 0, 1, 0, 0, 0, 0, "Flow end time"}, {"timestamp_arrival", 1, 1, 1, 1, 0, 0, 0, "Observation time at the collector"}, {"timestamp_export", 0, 0, 1, 0, 0, 0, 0, "Observation time at the exporter"}, {"", 0, 0, 0, 0, 0, 0, 0, ""} }; static const struct _protocols_struct _protocols[] = { {"0", 0}, {"icmp", 1}, {"igmp", 2}, {"ggp", 3}, {"ipencap", 4}, {"5", 5}, {"tcp", 6}, {"7", 7}, {"egp", 8}, {"igp", 9}, {"10", 10}, {"11", 11}, {"12", 12}, {"13", 13}, {"14", 14}, {"15", 15}, {"16", 16}, {"udp", 17}, {"mux", 18}, {"19", 19}, {"20", 20}, {"21", 21}, {"22", 22}, {"23", 23}, {"24", 24}, {"25", 25}, {"26", 26}, {"27", 27}, {"28", 28}, {"29", 29}, {"30", 30}, {"31", 31}, {"32", 32}, {"33", 33}, {"34", 34}, {"35", 35}, {"36", 36}, {"37", 37}, {"38", 38}, {"39", 39}, {"40", 40}, {"ipv6", 41}, {"42", 42}, {"ipv6-route", 43}, {"ipv6-frag", 44}, {"45", 45}, {"rsvp", 46}, {"gre", 47}, {"48", 48}, {"49", 49}, {"esp", 50}, {"ah", 51}, {"52", 52}, {"53", 53}, {"54", 54}, {"mobile", 55}, {"tlsp", 56}, {"57", 57}, {"ipv6-icmp", 58}, {"ipv6-nonxt", 59}, {"ipv6-opts", 60}, {"61", 61}, {"62", 62}, {"63", 63}, {"64", 64}, {"65", 65}, {"66", 66}, {"67", 67}, {"68", 68}, {"69", 69}, {"70", 70}, {"71", 71}, {"72", 72}, {"73", 73}, {"74", 74}, {"75", 75}, {"76", 76}, {"77", 77}, {"78", 78}, {"79", 79}, {"iso-ip", 80}, {"81", 81}, {"82", 82}, {"vines", 83}, {"84", 84}, {"85", 85}, {"86", 86}, {"87", 87}, {"eigrp", 88}, {"ospf", 89}, {"90", 90}, {"larp", 91}, {"92", 92}, {"ax.25", 93}, {"ipip", 94}, {"95", 95}, {"96", 96}, {"97", 97}, {"encap", 98}, {"99", 99}, {"100", 100}, {"101", 101}, {"pnni", 102}, {"pim", 103}, {"104", 104}, {"105", 105}, {"106", 106}, {"107", 107}, {"IPcomp", 108}, {"109", 109}, {"110", 110}, {"ipx-in-ip", 111}, {"vrrp", 112}, {"113", 113}, {"114", 114}, {"l2tp", 115}, {"116", 116}, {"117", 117}, {"118", 118}, {"119", 119}, {"120", 120}, {"121", 121}, {"122", 122}, {"123", 123}, {"isis", 124}, {"125", 125}, {"126", 126}, {"127", 127}, {"128", 128}, {"129", 129}, {"130", 130}, {"131", 131}, {"sctp", 132}, {"fc", 133}, {"134", 134}, {"135", 135}, {"136", 136}, {"137", 137}, {"138", 138}, {"139", 139}, {"140", 140}, {"141", 141}, {"142", 142}, {"143", 143}, {"144", 144}, {"145", 145}, {"146", 146}, {"147", 147}, {"148", 148}, {"149", 149}, {"150", 150}, {"151", 151}, {"152", 152}, {"153", 153}, {"154", 154}, {"155", 155}, {"156", 156}, {"157", 157}, {"158", 158}, {"159", 159}, {"160", 160}, {"161", 161}, {"162", 162}, {"163", 163}, {"164", 164}, {"165", 165}, {"166", 166}, {"167", 167}, {"168", 168}, {"169", 169}, {"170", 170}, {"171", 171}, {"172", 172}, {"173", 173}, {"174", 174}, {"175", 175}, {"176", 176}, {"177", 177}, {"178", 178}, {"179", 179}, {"180", 180}, {"181", 181}, {"182", 182}, {"183", 183}, {"184", 184}, {"185", 185}, {"186", 186}, {"187", 187}, {"188", 188}, {"189", 189}, {"190", 190}, {"191", 191}, {"192", 192}, {"193", 193}, {"194", 194}, {"195", 195}, {"196", 196}, {"197", 197}, {"198", 198}, {"199", 199}, {"200", 200}, {"201", 201}, {"202", 202}, {"203", 203}, {"204", 204}, {"205", 205}, {"206", 206}, {"207", 207}, {"208", 208}, {"209", 209}, {"210", 210}, {"211", 211}, {"212", 212}, {"213", 213}, {"214", 214}, {"215", 215}, {"216", 216}, {"217", 217}, {"218", 218}, {"219", 219}, {"220", 220}, {"221", 221}, {"222", 222}, {"223", 223}, {"224", 224}, {"225", 225}, {"226", 226}, {"227", 227}, {"228", 228}, {"229", 229}, {"230", 230}, {"231", 231}, {"232", 232}, {"233", 233}, {"234", 234}, {"235", 235}, {"236", 236}, {"237", 237}, {"238", 238}, {"239", 239}, {"240", 240}, {"241", 241}, {"242", 242}, {"243", 243}, {"244", 244}, {"245", 245}, {"246", 246}, {"247", 247}, {"248", 248}, {"249", 249}, {"250", 250}, {"251", 251}, {"252", 252}, {"253", 253}, {"254", 254}, {"others", 255}, /* Reserved value by IANA */ {"", -1}, }; /* cps = custom primitive semantics */ static const char __attribute__((unused)) *cps_type[] = { "", "u", "x", "s", "s", "s", "s" }; static const int __attribute__((unused)) cps_flen[] = { 0, 3, 5, 0, 10, 0, 0, 0, 20 }; static const char __attribute__((unused)) *bgp_origin[] = { "i", "e", "u", "" }; static const char __attribute__((unused)) *bgp_rd_origin[] = { "unknown", "bgp", "bmp", "flow", "" }; static const u_int16_t __attribute__((unused)) lookup_type_to_bgp_rd_origin[] = { RD_ORIGIN_UNKNOWN, RD_ORIGIN_BGP, RD_ORIGIN_BMP }; static const char __attribute__((unused)) *rpki_roa[] = { "u", "i", "v", "V", "U" }; static const char __attribute__((unused)) *sampling_direction[] = { "u", "i", "e" }; static const struct _id_to_string_struct _tools_map[] = { {ACCT_PM, "pmacctd"}, {ACCT_NF, "nfacctd"}, {ACCT_SF, "sfacctd"}, {ACCT_UL, "uacctd"}, {ACCT_PMBGP, "pmbgpd"}, {ACCT_PMBMP, "pmbmpd"}, {ACCT_PMTELE, "pmtelemetryd"}, {0, ""} }; static const struct _id_to_string_struct _primitives_map[] = { {COUNT_INT_SRC_HOST, "src_host"}, {COUNT_INT_DST_HOST, "dst_host"}, {COUNT_INT_SUM_HOST, "sum_host"}, {COUNT_INT_SRC_PORT, "src_port"}, {COUNT_INT_DST_PORT, "dst_port"}, {COUNT_INT_IP_PROTO, "proto"}, {COUNT_INT_SRC_MAC, "src_mac"}, {COUNT_INT_DST_MAC, "dst_mac"}, {COUNT_INT_SRC_NET, "src_net"}, {COUNT_INT_DST_NET, "dst_net"}, {COUNT_INT_TAG, "tag"}, {COUNT_INT_VLAN, "vlan"}, {COUNT_INT_IP_TOS, "tos"}, {COUNT_INT_NONE, "none"}, {COUNT_INT_SRC_AS, "src_as"}, {COUNT_INT_DST_AS, "dst_as"}, {COUNT_INT_SUM_NET, "sum_net"}, {COUNT_INT_SUM_AS, "sum_as"}, {COUNT_INT_SUM_PORT, "sum_port"}, {COUNT_INT_FLOWS, "flows"}, {COUNT_INT_SUM_MAC, "sum_mac"}, {COUNT_INT_CLASS, "class"}, {COUNT_INT_TCPFLAGS, "tcpflags"}, {COUNT_INT_STD_COMM, "std_comm"}, {COUNT_INT_EXT_COMM, "ext_comm"}, {COUNT_INT_AS_PATH, "as_path"}, {COUNT_INT_LOCAL_PREF, "local_pref"}, {COUNT_INT_MED, "med"}, {COUNT_INT_PEER_SRC_AS, "peer_src_as"}, {COUNT_INT_PEER_DST_AS, "peer_dst_as"}, {COUNT_INT_PEER_SRC_IP, "peer_src_ip"}, {COUNT_INT_PEER_DST_IP, "peer_dst_ip"}, {COUNT_INT_TAG2, "tag2"}, {COUNT_INT_SRC_AS_PATH, "src_as_path"}, {COUNT_INT_SRC_STD_COMM, "src_std_comm"}, {COUNT_INT_SRC_EXT_COMM, "src_ext_comm"}, {COUNT_INT_SRC_LOCAL_PREF, "src_local_pref"}, {COUNT_INT_SRC_MED, "src_med"}, {COUNT_INT_MPLS_VPN_RD, "mpls_vpn_rd"}, {COUNT_INT_IN_IFACE, "in_iface"}, {COUNT_INT_OUT_IFACE, "out_iface"}, {COUNT_INT_SRC_NMASK, "src_mask"}, {COUNT_INT_DST_NMASK, "dst_mask"}, {COUNT_INT_COS, "cos"}, {COUNT_INT_ETHERTYPE, "etype"}, {COUNT_INT_SAMPLING_RATE, "sampling_rate"}, {COUNT_INT_SRC_HOST_COUNTRY, "src_host_country"}, {COUNT_INT_DST_HOST_COUNTRY, "dst_host_country"}, {COUNT_INT_EXPORT_PROTO_SYSID, "export_proto_sysid"}, {COUNT_INT_POST_NAT_SRC_HOST, "post_nat_src_host"}, {COUNT_INT_POST_NAT_DST_HOST, "post_nat_dst_host"}, {COUNT_INT_POST_NAT_SRC_PORT, "post_nat_src_port"}, {COUNT_INT_POST_NAT_DST_PORT, "post_nat_dst_port"}, {COUNT_INT_NAT_EVENT, "nat_event"}, {COUNT_INT_TIMESTAMP_START, "timestamp_start"}, {COUNT_INT_TIMESTAMP_END, "timestamp_end"}, {COUNT_INT_TIMESTAMP_ARRIVAL, "timestamp_arrival"}, {COUNT_INT_MPLS_LABEL_TOP, "mpls_label_top"}, {COUNT_INT_MPLS_LABEL_BOTTOM, "mpls_label_bottom"}, {COUNT_INT_LABEL, "label"}, {COUNT_INT_EXPORT_PROTO_SEQNO, "export_proto_seqno"}, {COUNT_INT_EXPORT_PROTO_VERSION, "export_proto_version"}, {COUNT_INT_LRG_COMM, "lrg_comm"}, {COUNT_INT_SRC_LRG_COMM, "src_lrg_comm"}, {COUNT_INT_SRC_HOST_POCODE, "src_host_pocode"}, {COUNT_INT_DST_HOST_POCODE, "dst_host_pocode"}, {COUNT_INT_TUNNEL_SRC_HOST, "tunnel_src_host"}, {COUNT_INT_TUNNEL_DST_HOST, "tunnel_dst_host"}, {COUNT_INT_TUNNEL_IP_PROTO, "tunnel_proto"}, {COUNT_INT_TUNNEL_IP_TOS, "tunnel_tos"}, {COUNT_INT_NDPI_CLASS, "class"}, {COUNT_INT_SRC_HOST_COORDS, "src_host_coords"}, {COUNT_INT_DST_HOST_COORDS, "dst_host_coords"}, {COUNT_INT_SAMPLING_DIRECTION, "sampling_direction"}, {COUNT_INT_MPLS_PW_ID, "mpls_pw_id"}, {COUNT_INT_SRC_ROA, "src_roa"}, {COUNT_INT_DST_ROA, "dst_roa"}, {COUNT_INT_VXLAN, "vxlan"}, {COUNT_INT_TUNNEL_SRC_MAC, "tunnel_src_mac"}, {COUNT_INT_TUNNEL_DST_MAC, "tunnel_dst_mac"}, {COUNT_INT_TUNNEL_SRC_PORT, "tunnel_src_port"}, {COUNT_INT_TUNNEL_DST_PORT, "tunnel_dst_port"}, {COUNT_INT_TIMESTAMP_EXPORT, "timestamp_export"}, {COUNT_INT_FWD_STATUS, "fwd_status"}, {COUNT_INT_MPLS_LABEL_STACK, "label_stack"}, {COUNT_INT_FW_EVENT, "fw_event"}, {COUNT_INT_TUNNEL_TCPFLAGS, "tunnel_tcpflags"}, {COUNT_INT_OUT_VLAN, "out_vlan"}, {0, ""} }; extern struct tunnel_entry tunnel_handlers_list[]; extern struct _devices_struct _devices[]; #endif //PMACCT_DATA_H pmacct-1.7.8/src/strlcpy.c0000644000175000017500000000507114354105275014450 0ustar paolopaolo/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``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 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. */ #if !defined(HAVE_STRLCPY) #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif /* ! __*BSD__ */ pmacct-1.7.8/src/sqlite3_plugin.c0000644000175000017500000007124614354105275015721 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "sql_common.h" #include "sql_common_m.h" #include "sqlite3_plugin.h" char sqlite3_db[] = "/tmp/pmacct.db"; char sqlite3_table[] = "acct"; char sqlite3_table_v2[] = "acct_v2"; char sqlite3_table_v3[] = "acct_v3"; char sqlite3_table_v4[] = "acct_v4"; char sqlite3_table_v5[] = "acct_v5"; char sqlite3_table_v6[] = "acct_v6"; char sqlite3_table_v7[] = "acct_v7"; char sqlite3_table_v8[] = "acct_v8"; char sqlite3_table_bgp[] = "acct_bgp"; /* Functions */ void sqlite3_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; struct pollfd pfd; struct insert_data idata; time_t refresh_deadline; int refresh_timeout; int ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *dataptr; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "SQLite3 Plugin", config.name); memset(&idata, 0, sizeof(idata)); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } sql_set_signals(); sql_init_default_values(&extras); SQLI_init_default_values(&idata); SQLI_set_callbacks(&sqlfunc_cbr); sql_set_insert_func(); /* some LOCAL initialization AFTER setting some default values */ reload_map = FALSE; idata.now = time(NULL); refresh_deadline = idata.now; idata.cfg = &config; sql_init_maps(&extras, &prim_ptrs, &nt, &nc, &pt, &prt, &tost); sql_init_global_buffers(); sql_init_historical_acct(idata.now, &idata); sql_init_triggers(idata.now, &idata); sql_init_refresh_deadline(&refresh_deadline); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; /* building up static SQL clauses */ idata.num_primitives = SQLI_compose_static_queries(); glob_num_primitives = idata.num_primitives; /* setting up environment variables */ SQL_SetENV(); sql_link_backend_descriptors(&bed, &p, &b); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: sql_update_time_reference(&idata); if (idata.now > refresh_deadline) { if (sql_qq_ptr) sql_cache_flush(sql_queries_queue, sql_qq_ptr, &idata, FALSE); sql_cache_handle_flush_event(&idata, &refresh_deadline, &pt, &prt, &tost); } else { if (config.sql_trigger_exec) { while (idata.now > idata.triggertime && idata.t_timeslot > 0) { sql_trigger_exec(config.sql_trigger_exec); idata.triggertime += idata.t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata.t_timeslot = calc_monthly_timeslot(idata.triggertime, config.sql_trigger_time_howmany, ADD); } } } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; idata.now = time(NULL); } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*sql_insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } int SQLI_cache_dbop(struct DBdesc *db, struct db_cache *cache_elem, struct insert_data *idata) { char *ptr_values, *ptr_where, *ptr_mv, *ptr_set; int num=0, num_set=0, ret=0, have_flows=0, len=0; if (idata->mv.last_queue_elem) { ret = sqlite3_exec(db->desc, multi_values_buffer, NULL, NULL, NULL); Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d INSERT statements sent to the SQLite database.\n", config.name, config.type, idata->mv.buffer_elem_num); if (ret) goto signal_error; idata->iqn++; idata->mv.buffer_elem_num = FALSE; idata->mv.buffer_offset = 0; return FALSE; } if (config.what_to_count & COUNT_FLOWS) have_flows = TRUE; /* constructing sql query */ ptr_where = where_clause; ptr_values = values_clause; ptr_set = set_clause; memset(where_clause, 0, sizeof(where_clause)); memset(values_clause, 0, sizeof(values_clause)); memset(set_clause, 0, sizeof(set_clause)); memset(insert_full_clause, 0, sizeof(insert_full_clause)); for (num = 0; num < idata->num_primitives; num++) (*where[num].handler)(cache_elem, idata, num, &ptr_values, &ptr_where); if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { for (num_set = 0; set_event[num_set].type; num_set++) (*set_event[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } else { for (num_set = 0; set[num_set].type; num_set++) (*set[num_set].handler)(cache_elem, idata, num_set, &ptr_set, NULL); } /* sending UPDATE query a) if not switched off and b) if we actually have something to update */ if (!config.sql_dont_try_update && num_set) { strncpy(sql_data, update_clause, SPACELEFT(sql_data)); strncat(sql_data, set_clause, SPACELEFT(sql_data)); strncat(sql_data, where_clause, SPACELEFT(sql_data)); ret = sqlite3_exec(db->desc, sql_data, NULL, NULL, NULL); if (ret) goto signal_error; } if (config.sql_dont_try_update || !num_set || (sqlite3_changes(db->desc) == 0)) { /* UPDATE failed, trying with an INSERT query */ if (cache_elem->flow_type == NF9_FTYPE_EVENT || cache_elem->flow_type == NF9_FTYPE_OPTION) { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_nocounters_clause, SPACELEFT(insert_full_clause)); strncat(ptr_values, ")", SPACELEFT(values_clause)); } else { strncpy(insert_full_clause, insert_clause, SPACELEFT(insert_full_clause)); strncat(insert_full_clause, insert_counters_clause, SPACELEFT(insert_full_clause)); if (have_flows) snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter, cache_elem->flows_counter); else snprintf(ptr_values, SPACELEFT(values_clause), ", %" PRIu64 ", %" PRIu64 ")", cache_elem->packet_counter, cache_elem->bytes_counter); } strncpy(sql_data, insert_full_clause, sizeof(sql_data)); strncat(sql_data, values_clause, SPACELEFT(sql_data)); if (config.sql_multi_values) { multi_values_handling: len = config.sql_multi_values-idata->mv.buffer_offset; if (strlen(values_clause) < len) { if (idata->mv.buffer_elem_num) { strcpy(multi_values_buffer+idata->mv.buffer_offset, "; "); idata->mv.buffer_offset++; idata->mv.buffer_offset++; } ptr_mv = multi_values_buffer+idata->mv.buffer_offset; strcpy(multi_values_buffer+idata->mv.buffer_offset, sql_data); idata->mv.buffer_offset += strlen(ptr_mv); idata->mv.buffer_elem_num++; } else { if (idata->mv.buffer_elem_num) { ret = sqlite3_exec(db->desc, multi_values_buffer, NULL, NULL, NULL); Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d INSERT statements sent to the SQLite database.\n", config.name, config.type, idata->mv.buffer_elem_num); if (ret) goto signal_error; idata->iqn++; idata->mv.buffer_elem_num = FALSE; idata->mv.head_buffer_elem = FALSE; idata->mv.buffer_offset = 0; goto multi_values_handling; } else { Log(LOG_ERR, "ERROR ( %s/%s ): 'sql_multi_values' is too small (%d). Try with a larger value.\n", config.name, config.type, config.sql_multi_values); exit_gracefully(1); } } } else { ret = sqlite3_exec(db->desc, sql_data, NULL, NULL, NULL); Log(LOG_DEBUG, "( %s/%s ): %s\n\n", config.name, config.type, sql_data); if (ret) goto signal_error; idata->iqn++; } } else { Log(LOG_DEBUG, "( %s/%s ): %s\n\n", config.name, config.type, sql_data); idata->uqn++; } idata->een++; // cache_elem->valid = FALSE; /* committed */ return ret; signal_error: if (!idata->mv.buffer_elem_num) Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, sql_data); else { if (!idata->recover || db->type != BE_TYPE_PRIMARY) { /* DB failure: we will rewind the multi-values buffer */ idata->current_queue_elem = idata->mv.head_buffer_elem; idata->mv.buffer_elem_num = 0; } } SQLI_get_errmsg(db); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): %s\n\n", config.name, config.type, db->errmsg); return ret; } void SQLI_cache_purge(struct db_cache *queue[], int index, struct insert_data *idata) { struct db_cache *LastElemCommitted = NULL; time_t start; int j, stop, go_to_pending, saved_index = index; char orig_insert_clause[LONGSRVBUFLEN], orig_update_clause[LONGSRVBUFLEN], orig_lock_clause[LONGSRVBUFLEN]; char tmpbuf[LONGLONGSRVBUFLEN], tmptable[SRVBUFLEN]; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); if (!index) { Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: 0/0, ET: X) ***\n", config.name, config.type, writer_pid); return; } memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); for (j = 0, stop = 0; (!stop) && sql_preprocess_funcs[j]; j++) stop = sql_preprocess_funcs[j](queue, &index, j); if ((config.what_to_count & COUNT_CLASS) || (config.what_to_count_2 & COUNT_NDPI_CLASS)) sql_invalidate_shadow_entries(queue, &index); idata->ten = index; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); /* re-using pending queries queue stuff from parent and saving clauses */ memcpy(sql_pending_queries_queue, queue, index*sizeof(struct db_cache *)); sql_pqq_ptr = index; strlcpy(orig_insert_clause, insert_clause, LONGSRVBUFLEN); strlcpy(orig_update_clause, update_clause, LONGSRVBUFLEN); strlcpy(orig_lock_clause, lock_clause, LONGSRVBUFLEN); start: memset(&idata->mv, 0, sizeof(struct multi_values)); memcpy(queue, sql_pending_queries_queue, sql_pqq_ptr*sizeof(struct db_cache *)); memset(sql_pending_queries_queue, 0, sql_pqq_ptr*sizeof(struct db_cache *)); index = sql_pqq_ptr; sql_pqq_ptr = 0; /* We check for variable substitution in SQL table */ if (idata->dyn_table) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); stamp = queue[0]->basetime; prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[0]); strlcpy(idata->dyn_table_name, config.sql_table, SRVBUFLEN); strlcpy(insert_clause, orig_insert_clause, LONGSRVBUFLEN); strlcpy(update_clause, orig_update_clause, LONGSRVBUFLEN); strlcpy(lock_clause, orig_lock_clause, LONGSRVBUFLEN); handle_dynname_internal_strings_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(update_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); handle_dynname_internal_strings_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(insert_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(update_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(lock_clause, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); pm_strftime_same(idata->dyn_table_name, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); } if (config.sql_table_schema) sql_create_table(bed.p, &queue[0]->basetime, &prim_ptrs); (*sqlfunc_cbr.lock)(bed.p); for (idata->current_queue_elem = 0; idata->current_queue_elem < index; idata->current_queue_elem++) { go_to_pending = FALSE; if (idata->dyn_table && (!idata->dyn_table_time_only || !config.nfacctd_time_new || (config.sql_refresh_time != idata->timeslot))) { time_t stamp = 0; memset(tmpbuf, 0, LONGLONGSRVBUFLEN); // XXX: pedantic? stamp = queue[idata->current_queue_elem]->basetime; strlcpy(tmptable, config.sql_table, SRVBUFLEN); prim_ptrs.data = &dummy_data; primptrs_set_all_from_db_cache(&prim_ptrs, queue[idata->current_queue_elem]); handle_dynname_internal_strings_same(tmptable, LONGSRVBUFLEN, tmpbuf, &prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(tmptable, LONGSRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (strncmp(idata->dyn_table_name, tmptable, SRVBUFLEN)) { sql_pending_queries_queue[sql_pqq_ptr] = queue[idata->current_queue_elem]; sql_pqq_ptr++; go_to_pending = TRUE; } } if (!go_to_pending) { if (queue[idata->current_queue_elem]->valid) sql_query(&bed, queue[idata->current_queue_elem], idata); if (queue[idata->current_queue_elem]->valid == SQL_CACHE_COMMITTED) LastElemCommitted = queue[idata->current_queue_elem]; } } /* multi-value INSERT query: wrap-up */ if (idata->mv.buffer_elem_num) { idata->mv.last_queue_elem = TRUE; sql_query(&bed, LastElemCommitted, idata); idata->qn--; /* increased by sql_query() one time too much */ } /* rewinding stuff */ (*sqlfunc_cbr.unlock)(&bed); if (b.fail) Log(LOG_ALERT, "ALERT ( %s/%s ): recovery for SQLite3 daemon failed.\n", config.name, config.type); /* If we have pending queries then start again */ if (sql_pqq_ptr) goto start; idata->elap_time = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, idata->qn, saved_index, idata->elap_time); if (config.sql_trigger_exec) { if (queue && queue[0]) idata->basetime = queue[0]->basetime; idata->elap_time = time(NULL)-start; SQL_SetENV_child(idata); } } int SQLI_evaluate_history(int primitive) { if (config.sql_history) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, ", ", sizeof(values[primitive].string)); strncat(where[primitive].string, " AND ", sizeof(where[primitive].string)); } if (!config.timestamps_since_epoch) { if (!config.timestamps_utc) strncat(where[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime') = ", SPACELEFT(where[primitive].string)); else strncat(where[primitive].string, "DATETIME(%u, 'unixepoch') = ", SPACELEFT(where[primitive].string)); } else strncat(where[primitive].string, "%u = ", SPACELEFT(where[primitive].string)); strncat(where[primitive].string, "stamp_inserted", SPACELEFT(where[primitive].string)); strncat(insert_clause, "stamp_updated, stamp_inserted", SPACELEFT(insert_clause)); if (!config.timestamps_since_epoch) { if (!config.timestamps_utc) { strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime'), DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else strncat(values[primitive].string, "DATETIME(%u, 'unixepoch'), DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } else { strncat(values[primitive].string, "%u, %u", SPACELEFT(values[primitive].string)); } where[primitive].type = values[primitive].type = TIMESTAMP; values[primitive].handler = where[primitive].handler = count_timestamp_handler; primitive++; } return primitive; } int SQLI_compose_static_queries() { int primitives=0, set_primitives=0, set_event_primitives=0, have_flows=0; if (config.what_to_count & COUNT_FLOWS || (config.sql_table_version >= 4 && config.sql_table_version < SQL_TABLE_VERSION_BGP && !config.sql_optimize_clauses)) { config.what_to_count |= COUNT_FLOWS; have_flows = TRUE; if ((config.sql_table_version < 4 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !config.sql_optimize_clauses) { Log(LOG_ERR, "ERROR ( %s/%s ): The accounting of flows requires SQL table v4. Exiting.\n", config.name, config.type); exit_gracefully(1); } } /* "INSERT INTO ... VALUES ... " and "... WHERE ..." stuff */ strncpy(where[primitives].string, " WHERE ", sizeof(where[primitives].string)); snprintf(insert_clause, sizeof(insert_clause), "INSERT INTO %s (", config.sql_table); strncpy(values[primitives].string, " VALUES (", sizeof(values[primitives].string)); primitives = SQLI_evaluate_history(primitives); primitives = sql_evaluate_primitives(primitives); strncpy(insert_counters_clause, ", packets, bytes", SPACELEFT(insert_counters_clause)); if (have_flows) strncat(insert_counters_clause, ", flows", SPACELEFT(insert_counters_clause)); strncat(insert_counters_clause, ")", SPACELEFT(insert_counters_clause)); strncpy(insert_nocounters_clause, ")", SPACELEFT(insert_nocounters_clause)); /* "LOCK ..." stuff */ if (config.sql_locking_style) Log(LOG_WARNING, "WARN ( %s/%s ): sql_locking_style is not supported. Ignored.\n", config.name, config.type); snprintf(lock_clause, sizeof(lock_clause), "BEGIN"); strncpy(unlock_clause, "COMMIT", sizeof(unlock_clause)); /* "UPDATE ... SET ..." stuff */ snprintf(update_clause, sizeof(update_clause), "UPDATE %s ", config.sql_table); set_primitives = sql_compose_static_set(have_flows); set_event_primitives = sql_compose_static_set_event(); if (config.sql_history) { if (!config.timestamps_since_epoch) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); if (!config.timestamps_utc) { strncat(set[set_primitives].string, "stamp_updated=DATETIME('now', 'localtime')", SPACELEFT(set[set_primitives].string)); } else strncat(set[set_primitives].string, "stamp_updated=DATETIME('now')", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); if (!config.timestamps_utc) { strncat(set_event[set_event_primitives].string, "stamp_updated=DATETIME('now', 'localtime')", SPACELEFT(set_event[set_event_primitives].string)); } else strncat(set_event[set_event_primitives].string, "stamp_updated=DATETIME('now')", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_event_handler; set_event_primitives++; } else { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "stamp_updated=STRFTIME('%%s', 'now')", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = TIMESTAMP; set[set_primitives].handler = count_noop_setclause_handler; set_primitives++; if (set_event_primitives) strncpy(set_event[set_event_primitives].string, ", ", SPACELEFT(set_event[set_event_primitives].string)); else strncpy(set_event[set_event_primitives].string, "SET ", SPACELEFT(set_event[set_event_primitives].string)); strncat(set_event[set_event_primitives].string, "stamp_updated=STRFTIME('%%s', 'now')", SPACELEFT(set_event[set_event_primitives].string)); set_event[set_event_primitives].type = TIMESTAMP; set_event[set_event_primitives].handler = count_noop_setclause_event_handler; set_event_primitives++; } } return primitives; } void SQLI_Lock(struct DBdesc *db) { if (!db->fail) { if (sqlite3_exec(db->desc, lock_clause, NULL, NULL, NULL)) { SQLI_get_errmsg(db); sql_db_errmsg(db); sql_db_fail(db); } } } void SQLI_Unlock(struct BE_descs *bed) { if (bed->p->connected) sqlite3_exec(bed->p->desc, unlock_clause, NULL, NULL, NULL); if (bed->b->connected) sqlite3_exec(bed->b->desc, unlock_clause, NULL, NULL, NULL); } void SQLI_DB_Connect(struct DBdesc *db, char *host) { if (!db->fail) { if (sqlite3_open(db->filename, (sqlite3 **)&db->desc)) { sql_db_fail(db); SQLI_get_errmsg(db); sql_db_errmsg(db); } else sql_db_ok(db); } } void SQLI_DB_Close(struct BE_descs *bed) { if (bed->p->connected) sqlite3_close(bed->p->desc); if (bed->b->connected) sqlite3_close(bed->b->desc); } void SQLI_create_dyn_table(struct DBdesc *db, char *buf) { if (!db->fail) { if (sqlite3_exec(db->desc, buf, NULL, NULL, NULL)) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): FAILED query follows:\n%s\n", config.name, config.type, buf); SQLI_get_errmsg(db); sql_db_warnmsg(db); } } } void SQLI_get_errmsg(struct DBdesc *db) { db->errmsg = (char *) sqlite3_errmsg(db->desc); } void SQLI_create_backend(struct DBdesc *db) { if (db->type == BE_TYPE_PRIMARY) db->filename = config.sql_db; if (db->type == BE_TYPE_BACKUP) db->filename = config.sql_backup_host; } void SQLI_set_callbacks(struct sqlfunc_cb_registry *cbr) { memset(cbr, 0, sizeof(struct sqlfunc_cb_registry)); cbr->connect = SQLI_DB_Connect; cbr->close = SQLI_DB_Close; cbr->lock = SQLI_Lock; cbr->unlock = SQLI_Unlock; cbr->op = SQLI_cache_dbop; cbr->create_table = SQLI_create_dyn_table; cbr->purge = SQLI_cache_purge; cbr->create_backend = SQLI_create_backend; } void SQLI_init_default_values(struct insert_data *idata) { /* Linking database parameters */ if (!config.sql_db) config.sql_db = sqlite3_db; if (!config.sql_table) { if (config.sql_table_version == (SQL_TABLE_VERSION_BGP+1)) config.sql_table = sqlite3_table_bgp; else if (config.sql_table_version == 8) config.sql_table = sqlite3_table_v8; else if (config.sql_table_version == 7) config.sql_table = sqlite3_table_v7; else if (config.sql_table_version == 6) config.sql_table = sqlite3_table_v6; else if (config.sql_table_version == 5) config.sql_table = sqlite3_table_v5; else if (config.sql_table_version == 4) config.sql_table = sqlite3_table_v4; else if (config.sql_table_version == 3) config.sql_table = sqlite3_table_v3; else if (config.sql_table_version == 2) config.sql_table = sqlite3_table_v2; else config.sql_table = sqlite3_table; } if (strchr(config.sql_table, '%') || strchr(config.sql_table, '$')) { idata->dyn_table = TRUE; if (!strchr(config.sql_table, '$')) idata->dyn_table_time_only = TRUE; } glob_dyn_table = idata->dyn_table; glob_dyn_table_time_only = idata->dyn_table_time_only; if (config.sql_backup_host) idata->recover = TRUE; if (config.sql_multi_values) { multi_values_buffer = malloc(config.sql_multi_values); if (!multi_values_buffer) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to get enough room (%d) for multi value queries.\n", config.name, config.type, config.sql_multi_values); config.sql_multi_values = FALSE; } memset(multi_values_buffer, 0, config.sql_multi_values); } if (config.sql_locking_style) idata->locks = sql_select_locking_style(config.sql_locking_style); } void SQLI_sqlite3_get_version() { printf("sqlite3 %s\n", sqlite3_libversion()); } pmacct-1.7.8/src/pmacct.c0000644000175000017500000047752014354105275014233 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include /* include */ #include "pmacct.h" #include "pmacct-data.h" #include "imt_plugin.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "rpki/rpki.h" //Freaking mess with _XOPEN_SOURCE and non-std int types, so fwd decl extern char *strptime(const char *s, const char *format, struct tm *tm); /* prototypes */ int Recv(int, unsigned char **); void print_ex_options_error(); void write_status_header_formatted(); void write_status_header_csv(); void write_class_table_header(); char *write_sep(char *, int *); int CHECK_Q_TYPE(int); int check_data_sizes(struct query_header *, struct pkt_data *); void client_counters_merge_sort(void *, int, int, int, int); void client_counters_merge(void *, int, int, int, int, int); int pmc_sanitize_buf(char *); void pmc_trim_all_spaces(char *); char *pmc_extract_token(char **, int); u_int16_t pmc_bgp_rd_type_get(u_int16_t); int pmc_bgp_rd2str(char *, rd_t *); int pmc_bgp_str2rd(rd_t *, char *); char *pmc_compose_json(u_int64_t, u_int64_t, u_int8_t, struct pkt_primitives *, struct pkt_bgp_primitives *, struct pkt_legacy_bgp_primitives *, struct pkt_nat_primitives *, struct pkt_mpls_primitives *, struct pkt_tunnel_primitives *, u_char *, struct pkt_vlen_hdr_primitives *, pm_counter_t, pm_counter_t, pm_counter_t, u_int8_t, u_int8_t, struct timeval *, int, int); void pmc_append_rfc3339_timezone(char *, int, const struct tm *); void pmc_compose_timestamp(char *, int, struct timeval *, int, int, int); void pmc_custom_primitive_header_print(char *, int, struct imt_custom_primitive_entry *, int); void pmc_custom_primitive_value_print(char *, int, u_char *, struct imt_custom_primitive_entry *, int); void pmc_vlen_prims_get(struct pkt_vlen_hdr_primitives *, pm_cfgreg_t, char **); void pmc_printf_csv_label(struct pkt_vlen_hdr_primitives *, pm_cfgreg_t, char *, char *); void pmc_lower_string(char *); char *pmc_ndpi_get_proto_name(u_int16_t); const char *pmc_rpki_roa_print(u_int8_t); u_int8_t pmc_rpki_str2roa(char *); const char *pmc_sampling_direction_print(u_int8_t); u_int8_t pmc_sampling_direction_str2id(char *); /* vars */ struct imt_custom_primitives pmc_custom_primitives_registry; struct stripped_class *class_table = NULL; int want_ipproto_num, ct_idx, ct_num; /* functions */ int CHECK_Q_TYPE(int type) { if (!type) return 0; if (type & WANT_RESET) type ^= WANT_RESET; if (type & WANT_ERASE) type ^= WANT_ERASE; if (type & WANT_LOCK_OP) type ^= WANT_LOCK_OP; return type; } void usage_client(char *prog) { printf("%s %s (%s)\n", PMACCT_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [query]\n\n", prog); printf("Queries:\n"); printf(" -h\tShow this page\n"); printf(" -s\tShow statistics\n"); printf(" -N\t[';'] | 'file:' \n\tMatch primitives; print counters only (requires -c)\n"); printf(" -M\t[';'] | 'file:' \n\tMatch primitives; print formatted table (requires -c)\n"); printf(" -n\t \n\tSelect the counters to print (applies to -N)\n"); printf(" -S\tSum counters instead of returning a single counter for each request (applies to -N)\n"); printf(" -a\tDisplay all table fields (even those currently unused)\n"); printf(" -c\t< src_mac | dst_mac | vlan | out_vlan | cos | src_host | dst_host | src_net | dst_net | src_mask | dst_mask | \n\t src_port | dst_port | tos | proto | src_as | dst_as | sum_mac | sum_host | sum_net | sum_as | \n\t sum_port | in_iface | out_iface | tag | tag2 | flows | class | std_comm | ext_comm | lrg_comm | \n\t med | local_pref | as_path | dst_roa | peer_src_ip | peer_dst_ip | peer_src_as | peer_dst_as | \n\t src_as_path | src_std_comm | src_ext_comm | src_lrg_comm | src_med | src_local_pref | src_roa | \n\t mpls_vpn_rd | mpls_pw_id | etype | sampling_rate | sampling_direction | post_nat_src_host | \n\t post_nat_dst_host | post_nat_src_port | post_nat_dst_port | nat_event | fw_event | fwd_status | \n\t tunnel_src_mac | tunnel_dst_mac | tunnel_src_host | tunnel_dst_host | tunnel_protocol | \n\t tunnel_tos | tunnel_src_port | tunnel_dst_port | vxlan | timestamp_start | timestamp_end | \n\t timestamp_arrival | mpls_label_top | mpls_label_bottom | label | \n\t src_host_country | dst_host_country | export_proto_seqno | export_proto_version | \n\t export_proto_sysid | src_host_pocode | dst_host_pocode | src_host_coords | dst_host_coords > \n\tSelect primitives to match (required by -N and -M)\n"); printf(" -T\t,[<# how many>] \n\tOutput top N statistics (applies to -M and -s)\n"); printf(" -e\tClear statistics\n"); printf(" -i\tShow time (in seconds) since statistics were last cleared (ie. pmacct -e)\n"); printf(" -r\tReset counters (applies to -N and -M)\n"); printf(" -l\tPerform locking of the table\n"); printf(" -t\tShow memory table status\n"); printf(" -C\tShow classifiers table\n"); printf(" -U\tShow custom primitives table\n"); printf(" -p\t \n\tSocket for client-server communication (DEFAULT: /tmp/collect.pipe)\n"); printf(" -O\tSet output < formatted | csv | json | event_formatted | event_csv > (applies to -M and -s)\n"); printf(" -E\tSet sparator for CSV format\n"); printf(" -I\tSet timestamps in 'since Epoch' format\n"); printf(" -u\tLeave IP protocols in numerical format\n"); printf(" -0\tAlways set timestamps to UTC (even if the timezone configured on the system is different)\n"); printf(" -V\tPrint version and exit\n"); printf("\n"); printf(" See QUICKSTART file in the distribution for examples\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } void version_client(char *prog) { printf("%s %s (%s)\n", PMACCT_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("%s\n\n", PMACCT_COMPILE_ARGS); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int pmc_sanitize_buf(char *buf) { int x = 0, valid_char = 0; pmc_trim_all_spaces(buf); while (x < strlen(buf)) { if (!isspace(buf[x])) valid_char++; x++; } if (!valid_char) return TRUE; if (buf[0] == '!') return TRUE; return FALSE; } void pmc_trim_all_spaces(char *buf) { int i = 0, len; len = strlen(buf); /* trimming all spaces */ while (i <= len) { if (isspace(buf[i])) { strlcpy(&buf[i], &buf[i+1], len); len--; } else i++; } } void print_ex_options_error() { printf("ERROR: -s, -t, -N, -M and -C options are each mutually exclusive.\n\n"); exit(1); } void write_stats_header_formatted(pm_cfgreg_t what_to_count, pm_cfgreg_t what_to_count_2, u_int8_t have_wtc, int is_event) { if (!have_wtc) { printf("TAG "); printf("TAG2 "); printf("CLASS "); printf("IN_IFACE "); printf("OUT_IFACE "); #if defined HAVE_L2 printf("SRC_MAC "); printf("DST_MAC "); printf("VLAN "); printf("OUT_VLAN "); printf("COS "); printf("ETYPE "); #endif printf("SRC_AS "); printf("DST_AS "); printf("COMMS "); printf("SRC_COMMS "); printf("AS_PATH "); printf("SRC_AS_PATH "); printf("PREF "); printf("SRC_PREF "); printf("MED "); printf("SRC_MED "); printf("SRC_ROA "); printf("DST_ROA "); printf("PEER_SRC_AS "); printf("PEER_DST_AS "); printf("PEER_SRC_IP "); printf("PEER_DST_IP "); printf("SRC_IP "); printf("DST_IP "); printf("SRC_MASK "); printf("DST_MASK "); printf("SRC_PORT "); printf("DST_PORT "); printf("TCP_FLAGS "); printf("PROTOCOL "); printf("TOS "); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) printf("SH_COUNTRY "); printf("DH_COUNTRY "); #endif #if defined (WITH_GEOIPV2) printf("SH_POCODE "); printf("DH_POCODE "); printf("SH_LAT "); printf("SH_LON "); printf("DH_LAT "); printf("DH_LON "); #endif printf("SAMPLING_RATE "); printf("SAMPLING_DIRECTION "); printf("POST_NAT_SRC_IP "); printf("POST_NAT_DST_IP "); printf("POST_NAT_SRC_PORT "); printf("POST_NAT_DST_PORT "); printf("NAT_EVENT "); printf("FW_EVENT "); printf("FWD_STATUS "); printf("MPLS_LABEL_TOP "); printf("MPLS_LABEL_BOTTOM "); printf("TUNNEL_SRC_MAC "); printf("TUNNEL_DST_MAC "); printf("TUNNEL_SRC_IP "); printf("TUNNEL_DST_IP "); printf("TUNNEL_PROTOCOL "); printf("TUNNEL_TOS "); printf("TUNNEL_SRC_PORT "); printf("TUNNEL_DST_PORT "); printf("TIMESTAMP_START "); printf("TIMESTAMP_END "); printf("TIMESTAMP_ARRIVAL "); printf("TIMESTAMP_EXPORT "); printf("EXPORT_PROTO_SEQNO "); printf("EXPORT_PROTO_VERSION "); printf("EXPORT_PROTO_SYSID "); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { pmc_custom_primitive_header_print(cp_str, SRVBUFLEN, &pmc_custom_primitives_registry.primitive[cp_idx], TRUE); printf("%s ", cp_str); } } if (!is_event) { printf("PACKETS "); printf("FLOWS "); printf("BYTES\n"); } else printf("\n"); } else { if (what_to_count & COUNT_TAG) printf("TAG "); if (what_to_count & COUNT_TAG2) printf("TAG2 "); if (what_to_count & COUNT_CLASS) printf("CLASS "); #if defined (WITH_NDPI) if (what_to_count_2 & COUNT_NDPI_CLASS) printf("CLASS "); #endif if (what_to_count & COUNT_IN_IFACE) printf("IN_IFACE "); if (what_to_count & COUNT_OUT_IFACE) printf("OUT_IFACE "); #if defined HAVE_L2 if (what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) printf("SRC_MAC "); if (what_to_count & COUNT_DST_MAC) printf("DST_MAC "); if (what_to_count & COUNT_VLAN) printf("VLAN "); if (what_to_count_2 & COUNT_OUT_VLAN) printf("OUT_VLAN "); if (what_to_count & COUNT_COS) printf("COS "); if (what_to_count & COUNT_ETHERTYPE) printf("ETYPE "); #endif if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) printf("SRC_AS "); if (what_to_count & COUNT_DST_AS) printf("DST_AS "); if (what_to_count & COUNT_STD_COMM) printf("COMMS "); if (what_to_count & COUNT_EXT_COMM) printf("ECOMMS "); if (what_to_count & COUNT_SRC_STD_COMM) printf("SRC_COMMS "); if (what_to_count & COUNT_SRC_EXT_COMM) printf("SRC_ECOMMS "); if (what_to_count_2 & COUNT_LRG_COMM) printf("LCOMMS "); if (what_to_count_2 & COUNT_SRC_LRG_COMM) printf("SRC_LCOMMS "); if (what_to_count & COUNT_AS_PATH) printf("AS_PATH "); if (what_to_count & COUNT_SRC_AS_PATH) printf("SRC_AS_PATH "); if (what_to_count & COUNT_LOCAL_PREF) printf("PREF "); if (what_to_count & COUNT_SRC_LOCAL_PREF) printf("SRC_PREF "); if (what_to_count & COUNT_MED) printf("MED "); if (what_to_count & COUNT_SRC_MED) printf("SRC_MED "); if (what_to_count_2 & COUNT_SRC_ROA) printf("SRC_ROA "); if (what_to_count_2 & COUNT_DST_ROA) printf("DST_ROA "); if (what_to_count & COUNT_PEER_SRC_AS) printf("PEER_SRC_AS "); if (what_to_count & COUNT_PEER_DST_AS) printf("PEER_DST_AS "); if (what_to_count & COUNT_PEER_SRC_IP) printf("PEER_SRC_IP "); if (what_to_count & COUNT_PEER_DST_IP) printf("PEER_DST_IP "); if (what_to_count & COUNT_MPLS_VPN_RD) printf("MPLS_VPN_RD "); if (what_to_count_2 & COUNT_MPLS_PW_ID) printf("MPLS_PW_ID "); if (what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) printf("SRC_IP "); if (what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) printf("SRC_NET "); if (what_to_count & COUNT_DST_HOST) printf("DST_IP "); if (what_to_count & COUNT_DST_NET) printf("DST_NET "); if (what_to_count & COUNT_SRC_NMASK) printf("SRC_MASK "); if (what_to_count & COUNT_DST_NMASK) printf("DST_MASK "); if (what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) printf("SRC_PORT "); if (what_to_count & COUNT_DST_PORT) printf("DST_PORT "); if (what_to_count & COUNT_TCPFLAGS) printf("TCP_FLAGS "); if (what_to_count & COUNT_IP_PROTO) printf("PROTOCOL "); if (what_to_count & COUNT_IP_TOS) printf("TOS "); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_COUNTRY) printf("SH_COUNTRY "); if (what_to_count_2 & COUNT_DST_HOST_COUNTRY) printf("DH_COUNTRY "); #endif #if defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_POCODE) printf("SH_POCODE "); if (what_to_count_2 & COUNT_DST_HOST_POCODE) printf("DH_POCODE "); if (what_to_count_2 & COUNT_SRC_HOST_COORDS) { printf("SH_LAT "); printf("SH_LON "); } if (what_to_count_2 & COUNT_DST_HOST_COORDS) { printf("DH_LAT "); printf("DH_LON "); } #endif if (what_to_count_2 & COUNT_SAMPLING_RATE) printf("SAMPLING_RATE "); if (what_to_count_2 & COUNT_SAMPLING_DIRECTION) printf("SAMPLING_DIRECTION "); if (what_to_count_2 & COUNT_POST_NAT_SRC_HOST) printf("POST_NAT_SRC_IP "); if (what_to_count_2 & COUNT_POST_NAT_DST_HOST) printf("POST_NAT_DST_IP "); if (what_to_count_2 & COUNT_POST_NAT_SRC_PORT) printf("POST_NAT_SRC_PORT "); if (what_to_count_2 & COUNT_POST_NAT_DST_PORT) printf("POST_NAT_DST_PORT "); if (what_to_count_2 & COUNT_NAT_EVENT) printf("NAT_EVENT "); if (what_to_count_2 & COUNT_FW_EVENT) printf("FW_EVENT "); if (what_to_count_2 & COUNT_FWD_STATUS) printf("FWD_STATUS "); if (what_to_count_2 & COUNT_MPLS_LABEL_TOP) printf("MPLS_LABEL_TOP "); if (what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) printf("MPLS_LABEL_BOTTOM "); if (what_to_count_2 & COUNT_TUNNEL_SRC_MAC) printf("TUNNEL_SRC_MAC "); if (what_to_count_2 & COUNT_TUNNEL_DST_MAC) printf("TUNNEL_DST_MAC "); if (what_to_count_2 & COUNT_TUNNEL_SRC_HOST) printf("TUNNEL_SRC_IP "); if (what_to_count_2 & COUNT_TUNNEL_DST_HOST) printf("TUNNEL_DST_IP "); if (what_to_count_2 & COUNT_TUNNEL_IP_PROTO) printf("TUNNEL_PROTOCOL "); if (what_to_count_2 & COUNT_TUNNEL_IP_TOS) printf("TUNNEL_TOS "); if (what_to_count_2 & COUNT_TUNNEL_SRC_PORT) printf("TUNNEL_SRC_PORT "); if (what_to_count_2 & COUNT_TUNNEL_DST_PORT) printf("TUNNEL_DST_PORT "); if (what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) printf("TUNNEL_TCP_FLAGS "); if (what_to_count_2 & COUNT_VXLAN) printf("VXLAN "); if (what_to_count_2 & COUNT_TIMESTAMP_START) printf("TIMESTAMP_START "); if (what_to_count_2 & COUNT_TIMESTAMP_END) printf("TIMESTAMP_END "); if (what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) printf("TIMESTAMP_ARRIVAL "); if (what_to_count_2 & COUNT_EXPORT_PROTO_TIME) printf("TIMESTAMP_EXPORT "); if (what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) printf("EXPORT_PROTO_SEQNO "); if (what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) printf("EXPORT_PROTO_VERSION "); if (what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) printf("EXPORT_PROTO_SYSID "); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { pmc_custom_primitive_header_print(cp_str, SRVBUFLEN, &pmc_custom_primitives_registry.primitive[cp_idx], TRUE); printf("%s ", cp_str); } } if (!is_event) { printf("PACKETS "); if (what_to_count & COUNT_FLOWS) printf("FLOWS "); printf("BYTES\n"); } else printf("\n"); } } void write_stats_header_csv(pm_cfgreg_t what_to_count, pm_cfgreg_t what_to_count_2, u_int8_t have_wtc, char *sep, int is_event) { int count = 0; if (!have_wtc) { printf("%sTAG", write_sep(sep, &count)); printf("%sTAG2", write_sep(sep, &count)); printf("%sLABEL", write_sep(sep, &count)); printf("%sCLASS", write_sep(sep, &count)); printf("%sIN_IFACE", write_sep(sep, &count)); printf("%sOUT_IFACE", write_sep(sep, &count)); #if defined HAVE_L2 printf("%sSRC_MAC", write_sep(sep, &count)); printf("%sDST_MAC", write_sep(sep, &count)); printf("%sVLAN", write_sep(sep, &count)); printf("%sOUT_VLAN", write_sep(sep, &count)); printf("%sCOS", write_sep(sep, &count)); printf("%sETYPE", write_sep(sep, &count)); #endif printf("%sSRC_AS", write_sep(sep, &count)); printf("%sDST_AS", write_sep(sep, &count)); printf("%sCOMMS", write_sep(sep, &count)); printf("%sSRC_COMMS", write_sep(sep, &count)); printf("%sAS_PATH", write_sep(sep, &count)); printf("%sSRC_AS_PATH", write_sep(sep, &count)); printf("%sPREF", write_sep(sep, &count)); printf("%sSRC_PREF", write_sep(sep, &count)); printf("%sMED", write_sep(sep, &count)); printf("%sSRC_MED", write_sep(sep, &count)); printf("%sSRC_ROA", write_sep(sep, &count)); printf("%sDST_ROA", write_sep(sep, &count)); printf("%sPEER_SRC_AS", write_sep(sep, &count)); printf("%sPEER_DST_AS", write_sep(sep, &count)); printf("%sPEER_SRC_IP", write_sep(sep, &count)); printf("%sPEER_DST_IP", write_sep(sep, &count)); printf("%sSRC_IP", write_sep(sep, &count)); printf("%sDST_IP", write_sep(sep, &count)); printf("%sSRC_MASK", write_sep(sep, &count)); printf("%sDST_MASK", write_sep(sep, &count)); printf("%sSRC_PORT", write_sep(sep, &count)); printf("%sDST_PORT", write_sep(sep, &count)); printf("%sTCP_FLAGS", write_sep(sep, &count)); printf("%sPROTOCOL", write_sep(sep, &count)); printf("%sTOS", write_sep(sep, &count)); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) printf("%sSH_COUNTRY", write_sep(sep, &count)); printf("%sDH_COUNTRY", write_sep(sep, &count)); #endif #if defined (WITH_GEOIPV2) printf("%sSH_POCODE", write_sep(sep, &count)); printf("%sDH_POCODE", write_sep(sep, &count)); printf("%sSH_LAT", write_sep(sep, &count)); printf("%sSH_LON", write_sep(sep, &count)); printf("%sDH_LAT", write_sep(sep, &count)); printf("%sDH_LON", write_sep(sep, &count)); #endif printf("%sSAMPLING_RATE", write_sep(sep, &count)); printf("%sSAMPLING_DIRECTION", write_sep(sep, &count)); printf("%sPOST_NAT_SRC_IP", write_sep(sep, &count)); printf("%sPOST_NAT_DST_IP", write_sep(sep, &count)); printf("%sPOST_NAT_SRC_PORT", write_sep(sep, &count)); printf("%sPOST_NAT_DST_PORT", write_sep(sep, &count)); printf("%sNAT_EVENT", write_sep(sep, &count)); printf("%sFW_EVENT", write_sep(sep, &count)); printf("%sFWD_STATUS", write_sep(sep, &count)); printf("%sMPLS_LABEL_TOP", write_sep(sep, &count)); printf("%sMPLS_LABEL_BOTTOM", write_sep(sep, &count)); printf("%sTUNNEL_SRC_MAC", write_sep(sep, &count)); printf("%sTUNNEL_DST_MAC", write_sep(sep, &count)); printf("%sTUNNEL_SRC_IP", write_sep(sep, &count)); printf("%sTUNNEL_DST_IP", write_sep(sep, &count)); printf("%sTUNNEL_PROTOCOL", write_sep(sep, &count)); printf("%sTUNNEL_TOS", write_sep(sep, &count)); printf("%sTUNNEL_SRC_PORT", write_sep(sep, &count)); printf("%sTUNNEL_DST_PORT", write_sep(sep, &count)); printf("%sTIMESTAMP_START", write_sep(sep, &count)); printf("%sTIMESTAMP_END", write_sep(sep, &count)); printf("%sTIMESTAMP_ARRIVAL", write_sep(sep, &count)); printf("%sTIMESTAMP_EXPORT", write_sep(sep, &count)); printf("%sEXPORT_PROTO_SEQNO", write_sep(sep, &count)); printf("%sEXPORT_PROTO_VERSION", write_sep(sep, &count)); printf("%sEXPORT_PROTO_SYSID", write_sep(sep, &count)); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { pmc_custom_primitive_header_print(cp_str, SRVBUFLEN, &pmc_custom_primitives_registry.primitive[cp_idx], FALSE); printf("%s%s", write_sep(sep, &count), cp_str); } } if (!is_event) { printf("%sPACKETS", write_sep(sep, &count)); printf("%sFLOWS", write_sep(sep, &count)); printf("%sBYTES\n", write_sep(sep, &count)); } else printf("\n"); } else { if (what_to_count & COUNT_TAG) printf("%sTAG", write_sep(sep, &count)); if (what_to_count & COUNT_TAG2) printf("%sTAG2", write_sep(sep, &count)); if (what_to_count_2 & COUNT_LABEL) printf("%sLABEL", write_sep(sep, &count)); if (what_to_count & COUNT_CLASS) printf("%sCLASS", write_sep(sep, &count)); #if defined (WITH_NDPI) if (what_to_count_2 & COUNT_NDPI_CLASS) printf("%sCLASS", write_sep(sep, &count)); #endif if (what_to_count & COUNT_IN_IFACE) printf("%sIN_IFACE", write_sep(sep, &count)); if (what_to_count & COUNT_OUT_IFACE) printf("%sOUT_IFACE", write_sep(sep, &count)); #if defined HAVE_L2 if (what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) printf("%sSRC_MAC", write_sep(sep, &count)); if (what_to_count & COUNT_DST_MAC) printf("%sDST_MAC", write_sep(sep, &count)); if (what_to_count & COUNT_VLAN) printf("%sVLAN", write_sep(sep, &count)); if (what_to_count_2 & COUNT_OUT_VLAN) printf("%sOUT_VLAN", write_sep(sep, &count)); if (what_to_count & COUNT_COS) printf("%sCOS", write_sep(sep, &count)); if (what_to_count & COUNT_ETHERTYPE) printf("%sETYPE", write_sep(sep, &count)); #endif if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) printf("%sSRC_AS", write_sep(sep, &count)); if (what_to_count & COUNT_DST_AS) printf("%sDST_AS", write_sep(sep, &count)); if (what_to_count & COUNT_STD_COMM) printf("%sCOMMS", write_sep(sep, &count)); if (what_to_count & COUNT_EXT_COMM) printf("%sECOMMS", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_STD_COMM) printf("%sSRC_COMMS", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_EXT_COMM) printf("%sSRC_ECOMMS", write_sep(sep, &count)); if (what_to_count_2 & COUNT_LRG_COMM) printf("%sLCOMMS", write_sep(sep, &count)); if (what_to_count_2 & COUNT_SRC_LRG_COMM) printf("%sSRC_LCOMMS", write_sep(sep, &count)); if (what_to_count & COUNT_AS_PATH) printf("%sAS_PATH", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_AS_PATH) printf("%sSRC_AS_PATH", write_sep(sep, &count)); if (what_to_count & COUNT_LOCAL_PREF) printf("%sPREF", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_LOCAL_PREF) printf("%sSRC_PREF", write_sep(sep, &count)); if (what_to_count & COUNT_MED) printf("%sMED", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_MED) printf("%sSRC_MED", write_sep(sep, &count)); if (what_to_count_2 & COUNT_SRC_ROA) printf("%sSRC_ROA", write_sep(sep, &count)); if (what_to_count_2 & COUNT_DST_ROA) printf("%sDST_ROA", write_sep(sep, &count)); if (what_to_count & COUNT_PEER_SRC_AS) printf("%sPEER_SRC_AS", write_sep(sep, &count)); if (what_to_count & COUNT_PEER_DST_AS) printf("%sPEER_DST_AS", write_sep(sep, &count)); if (what_to_count & COUNT_PEER_SRC_IP) printf("%sPEER_SRC_IP", write_sep(sep, &count)); if (what_to_count & COUNT_PEER_DST_IP) printf("%sPEER_DST_IP", write_sep(sep, &count)); if (what_to_count & COUNT_MPLS_VPN_RD) printf("%sMPLS_VPN_RD", write_sep(sep, &count)); if (what_to_count_2 & COUNT_MPLS_PW_ID) printf("%sMPLS_PW_ID", write_sep(sep, &count)); if (what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) printf("%sSRC_IP", write_sep(sep, &count)); if (what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) printf("%sSRC_NET", write_sep(sep, &count)); if (what_to_count & COUNT_DST_HOST) printf("%sDST_IP", write_sep(sep, &count)); if (what_to_count & COUNT_DST_NET) printf("%sDST_NET", write_sep(sep, &count)); if (what_to_count & COUNT_SRC_NMASK) printf("%sSRC_MASK", write_sep(sep, &count)); if (what_to_count & COUNT_DST_NMASK) printf("%sDST_MASK", write_sep(sep, &count)); if (what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) printf("%sSRC_PORT", write_sep(sep, &count)); if (what_to_count & COUNT_DST_PORT) printf("%sDST_PORT", write_sep(sep, &count)); if (what_to_count & COUNT_TCPFLAGS) printf("%sTCP_FLAGS", write_sep(sep, &count)); if (what_to_count & COUNT_IP_PROTO) printf("%sPROTOCOL", write_sep(sep, &count)); if (what_to_count & COUNT_IP_TOS) printf("%sTOS", write_sep(sep, &count)); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_COUNTRY) printf("%sSH_COUNTRY", write_sep(sep, &count)); if (what_to_count_2 & COUNT_DST_HOST_COUNTRY) printf("%sDH_COUNTRY", write_sep(sep, &count)); #endif #if defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_POCODE) printf("%sSH_POCODE", write_sep(sep, &count)); if (what_to_count_2 & COUNT_DST_HOST_POCODE) printf("%sDH_POCODE", write_sep(sep, &count)); if (what_to_count_2 & COUNT_SRC_HOST_COORDS) { printf("%sSH_LAT", write_sep(sep, &count)); printf("%sSH_LON", write_sep(sep, &count)); } if (what_to_count_2 & COUNT_DST_HOST_COORDS) { printf("%sDH_LAT", write_sep(sep, &count)); printf("%sDH_LON", write_sep(sep, &count)); } #endif if (what_to_count_2 & COUNT_SAMPLING_RATE) printf("%sSAMPLING_RATE", write_sep(sep, &count)); if (what_to_count_2 & COUNT_SAMPLING_DIRECTION) printf("%sSAMPLING_DIRECTION", write_sep(sep, &count)); if (what_to_count_2 & COUNT_POST_NAT_SRC_HOST) printf("%sPOST_NAT_SRC_IP", write_sep(sep, &count)); if (what_to_count_2 & COUNT_POST_NAT_DST_HOST) printf("%sPOST_NAT_DST_IP", write_sep(sep, &count)); if (what_to_count_2 & COUNT_POST_NAT_SRC_PORT) printf("%sPOST_NAT_SRC_PORT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_POST_NAT_DST_PORT) printf("%sPOST_NAT_DST_PORT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_NAT_EVENT) printf("%sNAT_EVENT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_FW_EVENT) printf("%sFW_EVENT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_FWD_STATUS) printf("%sFWD_STATUS", write_sep(sep, &count)); if (what_to_count_2 & COUNT_MPLS_LABEL_TOP) printf("%sMPLS_LABEL_TOP", write_sep(sep, &count)); if (what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) printf("%sMPLS_LABEL_BOTTOM", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_SRC_MAC) printf("%sTUNNEL_SRC_MAC", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_DST_MAC) printf("%sTUNNEL_DST_MAC", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_SRC_HOST) printf("%sTUNNEL_SRC_IP", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_DST_HOST) printf("%sTUNNEL_DST_IP", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_IP_PROTO) printf("%sTUNNEL_PROTOCOL", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_IP_TOS) printf("%sTUNNEL_TOS", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_SRC_PORT) printf("%sTUNNEL_SRC_PORT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_DST_PORT) printf("%sTUNNEL_DST_PORT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) printf("%sTUNNEL_TCP_FLAGS", write_sep(sep, &count)); if (what_to_count_2 & COUNT_VXLAN) printf("%sVXLAN", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TIMESTAMP_START) printf("%sTIMESTAMP_START", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TIMESTAMP_END) printf("%sTIMESTAMP_END", write_sep(sep, &count)); if (what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) printf("%sTIMESTAMP_ARRIVAL", write_sep(sep, &count)); if (what_to_count_2 & COUNT_EXPORT_PROTO_TIME) printf("%sTIMESTAMP_EXPORT", write_sep(sep, &count)); if (what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) printf("%sEXPORT_PROTO_SEQNO", write_sep(sep, &count)); if (what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) printf("%sEXPORT_PROTO_VERSION", write_sep(sep, &count)); if (what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) printf("%sEXPORT_PROTO_SYSID", write_sep(sep, &count)); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { pmc_custom_primitive_header_print(cp_str, SRVBUFLEN, &pmc_custom_primitives_registry.primitive[cp_idx], FALSE); printf("%s%s", write_sep(sep, &count), cp_str); } } if (!is_event) { printf("%sPACKETS", write_sep(sep, &count)); if (what_to_count & COUNT_FLOWS) printf("%sFLOWS", write_sep(sep, &count)); printf("%sBYTES\n", write_sep(sep, &count)); } else printf("\n"); } } void write_status_header() { printf("* = element\n\n"); printf("BUCKET\tCHAIN_STATUS\n"); } void write_class_table_header() { printf("CLASS_ID\tCLASS_NAME\n"); } int build_query_client(char *path_ptr) { struct sockaddr_un cAddr; int sd, rc, cLen; sd = socket(AF_UNIX, SOCK_STREAM, 0); if (sd < 0) { printf("ERROR: Unable to open socket.\n"); exit(1); } cAddr.sun_family = AF_UNIX; strcpy(cAddr.sun_path, path_ptr); cLen = sizeof(cAddr); rc = connect(sd, (struct sockaddr *) &cAddr, cLen); if (rc < 0) { if (errno == ECONNREFUSED) { printf("INFO: Connection refused while trying to connect to '%s'\n\n", path_ptr); exit(1); } else { printf("ERROR: Unable to connect to '%s'\n\n", path_ptr); exit(1); } } return sd; } int main(int argc,char **argv) { int clibufsz = (MAX_QUERIES*sizeof(struct query_entry))+sizeof(struct query_header)+2; struct pkt_data *acc_elem = NULL; struct bucket_desc *bd; struct query_header q; struct pkt_primitives empty_addr; struct pkt_bgp_primitives empty_pbgp; struct pkt_legacy_bgp_primitives empty_plbgp; struct pkt_nat_primitives empty_pnat; struct pkt_mpls_primitives empty_pmpls; struct pkt_tunnel_primitives empty_ptun; struct pkt_vlen_hdr_primitives empty_pvlen; struct query_entry request; struct pkt_bgp_primitives *pbgp = NULL; struct pkt_legacy_bgp_primitives *plbgp = NULL; struct pkt_nat_primitives *pnat = NULL; struct pkt_mpls_primitives *pmpls = NULL; struct pkt_tunnel_primitives *ptun = NULL; struct pkt_vlen_hdr_primitives *pvlen = NULL; u_char *pcust = NULL; char *clibuf, *bufptr; unsigned char *largebuf, *elem, *ct, *cpt; char ethernet_address[18], ip_address[INET6_ADDRSTRLEN]; #if defined (WITH_NDPI) char ndpi_class[SUPERSHORTBUFLEN]; #endif char path[SRVBUFLEN], file[SRVBUFLEN], password[9], rd_str[SRVBUFLEN], tmpbuf[SRVBUFLEN]; char *as_path, empty_aspath[] = "^$", empty_string[] = "", *bgp_comm; int sd, buflen, unpacked, printed; int counter=0, sep_len=0, is_event; char *sep_ptr = NULL, sep[10], spacing_sep[2]; struct imt_custom_primitives custom_primitives_input; /* mrtg stuff */ char match_string[LARGEBUFLEN], *match_string_token, *match_string_ptr; char count[SRVBUFLEN], *count_token[N_PRIMITIVES], *count_ptr; int count_index = 0, match_string_index = 0, index = 0; pm_cfgreg_t count_token_int[N_PRIMITIVES]; /* getopt() stuff */ extern char *optarg; extern int optind, opterr, optopt; int errflag, cp, want_stats, want_erase, want_reset, want_class_table; int want_status, want_mrtg, want_counter, want_match, want_all_fields; int want_output, want_custom_primitives_table; int want_erase_last_tstamp, want_tstamp_since_epoch, want_tstamp_utc; int which_counter, topN_counter, fetch_from_file, sum_counters, num_counters; int topN_howmany, topN_printed; int datasize; pm_cfgreg_t what_to_count, what_to_count_2, have_wtc; u_int32_t tmpnum; struct extra_primitives extras; char *topN_howmany_ptr, *endptr; /* Administrativia */ clibuf = malloc(clibufsz); memset(&q, 0, sizeof(struct query_header)); memset(&empty_addr, 0, sizeof(struct pkt_primitives)); memset(&empty_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&empty_plbgp, 0, sizeof(struct pkt_legacy_bgp_primitives)); memset(&empty_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&empty_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&empty_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(&empty_pvlen, 0, sizeof(struct pkt_vlen_hdr_primitives)); memset(count, 0, sizeof(count)); memset(password, 0, sizeof(password)); memset(sep, 0, sizeof(sep)); memset(&pmc_custom_primitives_registry, 0, sizeof(pmc_custom_primitives_registry)); memset(&custom_primitives_input, 0, sizeof(custom_primitives_input)); strcpy(path, "/tmp/collect.pipe"); unpacked = 0; printed = 0; errflag = 0; buflen = 0; protocols_number = 0; want_stats = FALSE; want_erase = FALSE; want_erase_last_tstamp = FALSE; want_status = FALSE; want_counter = FALSE; want_mrtg = FALSE; want_match = FALSE; want_all_fields = FALSE; want_reset = FALSE; want_class_table = FALSE; want_ipproto_num = FALSE; want_custom_primitives_table = FALSE; which_counter = FALSE; topN_counter = FALSE; topN_howmany = FALSE; sum_counters = FALSE; num_counters = FALSE; fetch_from_file = FALSE; what_to_count = FALSE; what_to_count_2 = FALSE; have_wtc = FALSE; want_output = PRINT_OUTPUT_FORMATTED; is_event = FALSE; want_tstamp_since_epoch = FALSE; want_tstamp_utc = FALSE; PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); while (!errflag && ((cp = getopt(argc, argv, ARGS_PMACCT)) != -1)) { switch (cp) { case 's': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); q.type |= WANT_STATS; q.num = 1; want_stats = TRUE; break; case 'c': strlcpy(count, optarg, sizeof(count)); pmc_lower_string(count); count_ptr = count; while ((*count_ptr != '\0') && (count_index <= N_PRIMITIVES-1)) { count_token[count_index] = pmc_extract_token(&count_ptr, ','); if (!strcmp(count_token[count_index], "src_host")) { count_token_int[count_index] = COUNT_INT_SRC_HOST; what_to_count |= COUNT_SRC_HOST; } else if (!strcmp(count_token[count_index], "dst_host")) { count_token_int[count_index] = COUNT_INT_DST_HOST; what_to_count |= COUNT_DST_HOST; } else if (!strcmp(count_token[count_index], "src_net")) { count_token_int[count_index] = COUNT_INT_SRC_NET; what_to_count |= COUNT_SRC_NET; } else if (!strcmp(count_token[count_index], "dst_net")) { count_token_int[count_index] = COUNT_INT_DST_NET; what_to_count |= COUNT_DST_NET; } else if (!strcmp(count_token[count_index], "sum")) { count_token_int[count_index] = COUNT_INT_SUM_HOST; what_to_count |= COUNT_SUM_HOST; } else if (!strcmp(count_token[count_index], "src_port")) { count_token_int[count_index] = COUNT_INT_SRC_PORT; what_to_count |= COUNT_SRC_PORT; } else if (!strcmp(count_token[count_index], "dst_port")) { count_token_int[count_index] = COUNT_INT_DST_PORT; what_to_count |= COUNT_DST_PORT; } else if (!strcmp(count_token[count_index], "proto")) { count_token_int[count_index] = COUNT_INT_IP_PROTO; what_to_count |= COUNT_IP_PROTO; } #if defined HAVE_L2 else if (!strcmp(count_token[count_index], "src_mac")) { count_token_int[count_index] = COUNT_INT_SRC_MAC; what_to_count |= COUNT_SRC_MAC; } else if (!strcmp(count_token[count_index], "dst_mac")) { count_token_int[count_index] = COUNT_INT_DST_MAC; what_to_count |= COUNT_DST_MAC; } else if (!strcmp(count_token[count_index], "vlan")) { count_token_int[count_index] = COUNT_INT_VLAN; what_to_count |= COUNT_VLAN; } else if (!strcmp(count_token[count_index], "out_vlan")) { count_token_int[count_index] = COUNT_INT_OUT_VLAN; what_to_count_2 |= COUNT_OUT_VLAN; } else if (!strcmp(count_token[count_index], "cos")) { count_token_int[count_index] = COUNT_INT_COS; what_to_count |= COUNT_COS; } else if (!strcmp(count_token[count_index], "etype")) { count_token_int[count_index] = COUNT_INT_ETHERTYPE; what_to_count |= COUNT_ETHERTYPE; } else if (!strcmp(count_token[count_index], "sum_mac")) { count_token_int[count_index] = COUNT_INT_SUM_MAC; what_to_count |= COUNT_SUM_MAC; } #endif else if (!strcmp(count_token[count_index], "in_iface")) { count_token_int[count_index] = COUNT_INT_IN_IFACE; what_to_count |= COUNT_IN_IFACE; } else if (!strcmp(count_token[count_index], "out_iface")) { count_token_int[count_index] = COUNT_INT_OUT_IFACE; what_to_count |= COUNT_OUT_IFACE; } else if (!strcmp(count_token[count_index], "tos")) { count_token_int[count_index] = COUNT_INT_IP_TOS; what_to_count |= COUNT_IP_TOS; } #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) else if (!strcmp(count_token[count_index], "src_host_country")) { count_token_int[count_index] = COUNT_INT_SRC_HOST_COUNTRY; what_to_count_2 |= COUNT_SRC_HOST_COUNTRY; } else if (!strcmp(count_token[count_index], "dst_host_country")) { count_token_int[count_index] = COUNT_INT_DST_HOST_COUNTRY; what_to_count_2 |= COUNT_DST_HOST_COUNTRY; } #endif #if defined (WITH_GEOIPV2) else if (!strcmp(count_token[count_index], "src_host_pocode")) { count_token_int[count_index] = COUNT_INT_SRC_HOST_POCODE; what_to_count_2 |= COUNT_SRC_HOST_POCODE; } else if (!strcmp(count_token[count_index], "dst_host_pocode")) { count_token_int[count_index] = COUNT_INT_DST_HOST_POCODE; what_to_count_2 |= COUNT_DST_HOST_POCODE; } else if (!strcmp(count_token[count_index], "src_host_coords")) { count_token_int[count_index] = COUNT_INT_SRC_HOST_COORDS; what_to_count_2 |= COUNT_SRC_HOST_COORDS; } else if (!strcmp(count_token[count_index], "dst_host_coords")) { count_token_int[count_index] = COUNT_INT_DST_HOST_COORDS; what_to_count_2 |= COUNT_DST_HOST_COORDS; } #endif else if (!strcmp(count_token[count_index], "sampling_rate")) { count_token_int[count_index] = COUNT_INT_SAMPLING_RATE; what_to_count_2 |= COUNT_SAMPLING_RATE; } else if (!strcmp(count_token[count_index], "sampling_direction")) { count_token_int[count_index] = COUNT_INT_SAMPLING_DIRECTION; what_to_count_2 |= COUNT_SAMPLING_DIRECTION; } else if (!strcmp(count_token[count_index], "none")) { count_token_int[count_index] = COUNT_INT_NONE; what_to_count |= COUNT_NONE; } else if (!strcmp(count_token[count_index], "src_as")) { count_token_int[count_index] = COUNT_INT_SRC_AS; what_to_count |= COUNT_SRC_AS; } else if (!strcmp(count_token[count_index], "dst_as")) { count_token_int[count_index] = COUNT_INT_DST_AS; what_to_count |= COUNT_DST_AS; } else if (!strcmp(count_token[count_index], "src_net")) { count_token_int[count_index] = COUNT_INT_SRC_NET; what_to_count |= COUNT_SRC_NET; } else if (!strcmp(count_token[count_index], "dst_net")) { count_token_int[count_index] = COUNT_INT_DST_NET; what_to_count |= COUNT_DST_NET; } else if (!strcmp(count_token[count_index], "sum_host")) { count_token_int[count_index] = COUNT_INT_SUM_HOST; what_to_count |= COUNT_SUM_HOST; } else if (!strcmp(count_token[count_index], "sum_net")) { count_token_int[count_index] = COUNT_INT_SUM_NET; what_to_count |= COUNT_SUM_NET; } else if (!strcmp(count_token[count_index], "sum_as")) { count_token_int[count_index] = COUNT_INT_SUM_AS; what_to_count |= COUNT_SUM_AS; } else if (!strcmp(count_token[count_index], "sum_port")) { count_token_int[count_index] = COUNT_INT_SUM_PORT; what_to_count |= COUNT_SUM_PORT; } else if (!strcmp(count_token[count_index], "src_mask")) { count_token_int[count_index] = COUNT_INT_SRC_NMASK; what_to_count |= COUNT_SRC_NMASK; } else if (!strcmp(count_token[count_index], "dst_mask")) { count_token_int[count_index] = COUNT_INT_DST_NMASK; what_to_count |= COUNT_DST_NMASK; } else if (!strcmp(count_token[count_index], "tag")) { count_token_int[count_index] = COUNT_INT_TAG; what_to_count |= COUNT_TAG; } else if (!strcmp(count_token[count_index], "tag2")) { count_token_int[count_index] = COUNT_INT_TAG2; what_to_count |= COUNT_TAG2; } else if (!strcmp(count_token[count_index], "class")) { count_token_int[count_index] = COUNT_INT_NDPI_CLASS; what_to_count_2 |= COUNT_NDPI_CLASS; } else if (!strcmp(count_token[count_index], "std_comm")) { count_token_int[count_index] = COUNT_INT_STD_COMM; what_to_count |= COUNT_STD_COMM; } else if (!strcmp(count_token[count_index], "src_std_comm")) { count_token_int[count_index] = COUNT_INT_SRC_STD_COMM; what_to_count |= COUNT_SRC_STD_COMM; } else if (!strcmp(count_token[count_index], "ext_comm")) { count_token_int[count_index] = COUNT_INT_EXT_COMM; what_to_count |= COUNT_EXT_COMM; } else if (!strcmp(count_token[count_index], "src_ext_comm")) { count_token_int[count_index] = COUNT_INT_SRC_EXT_COMM; what_to_count |= COUNT_SRC_EXT_COMM; } else if (!strcmp(count_token[count_index], "lrg_comm")) { count_token_int[count_index] = COUNT_INT_LRG_COMM; what_to_count_2 |= COUNT_LRG_COMM; } else if (!strcmp(count_token[count_index], "src_lrg_comm")) { count_token_int[count_index] = COUNT_INT_SRC_LRG_COMM; what_to_count_2 |= COUNT_SRC_LRG_COMM; } else if (!strcmp(count_token[count_index], "as_path")) { count_token_int[count_index] = COUNT_INT_AS_PATH; what_to_count |= COUNT_AS_PATH; } else if (!strcmp(count_token[count_index], "src_as_path")) { count_token_int[count_index] = COUNT_INT_SRC_AS_PATH; what_to_count |= COUNT_SRC_AS_PATH; } else if (!strcmp(count_token[count_index], "local_pref")) { count_token_int[count_index] = COUNT_INT_LOCAL_PREF; what_to_count |= COUNT_LOCAL_PREF; } else if (!strcmp(count_token[count_index], "src_local_pref")) { count_token_int[count_index] = COUNT_INT_SRC_LOCAL_PREF; what_to_count |= COUNT_SRC_LOCAL_PREF; } else if (!strcmp(count_token[count_index], "med")) { count_token_int[count_index] = COUNT_INT_MED; what_to_count |= COUNT_MED; } else if (!strcmp(count_token[count_index], "src_med")) { count_token_int[count_index] = COUNT_INT_SRC_MED; what_to_count |= COUNT_SRC_MED; } else if (!strcmp(count_token[count_index], "src_roa")) { count_token_int[count_index] = COUNT_INT_SRC_ROA; what_to_count_2 |= COUNT_SRC_ROA; } else if (!strcmp(count_token[count_index], "dst_roa")) { count_token_int[count_index] = COUNT_INT_DST_ROA; what_to_count_2 |= COUNT_DST_ROA; } else if (!strcmp(count_token[count_index], "peer_src_as")) { count_token_int[count_index] = COUNT_INT_PEER_SRC_AS; what_to_count |= COUNT_PEER_SRC_AS; } else if (!strcmp(count_token[count_index], "peer_dst_as")) { count_token_int[count_index] = COUNT_INT_PEER_DST_AS; what_to_count |= COUNT_PEER_DST_AS; } else if (!strcmp(count_token[count_index], "peer_src_ip")) { count_token_int[count_index] = COUNT_INT_PEER_SRC_IP; what_to_count |= COUNT_PEER_SRC_IP; } else if (!strcmp(count_token[count_index], "peer_dst_ip")) { count_token_int[count_index] = COUNT_INT_PEER_DST_IP; what_to_count |= COUNT_PEER_DST_IP; } else if (!strcmp(count_token[count_index], "mpls_vpn_rd")) { count_token_int[count_index] = COUNT_INT_MPLS_VPN_RD; what_to_count |= COUNT_MPLS_VPN_RD; } else if (!strcmp(count_token[count_index], "mpls_pw_id")) { count_token_int[count_index] = COUNT_INT_MPLS_PW_ID; what_to_count_2 |= COUNT_MPLS_PW_ID; } else if (!strcmp(count_token[count_index], "post_nat_src_host")) { count_token_int[count_index] = COUNT_INT_POST_NAT_SRC_HOST; what_to_count_2 |= COUNT_POST_NAT_SRC_HOST; } else if (!strcmp(count_token[count_index], "post_nat_dst_host")) { count_token_int[count_index] = COUNT_INT_POST_NAT_DST_HOST; what_to_count_2 |= COUNT_POST_NAT_DST_HOST; } else if (!strcmp(count_token[count_index], "post_nat_src_port")) { count_token_int[count_index] = COUNT_INT_POST_NAT_SRC_PORT; what_to_count_2 |= COUNT_POST_NAT_SRC_PORT; } else if (!strcmp(count_token[count_index], "post_nat_dst_port")) { count_token_int[count_index] = COUNT_INT_POST_NAT_DST_PORT; what_to_count_2 |= COUNT_POST_NAT_DST_HOST; } else if (!strcmp(count_token[count_index], "nat_event")) { count_token_int[count_index] = COUNT_INT_NAT_EVENT; what_to_count_2 |= COUNT_NAT_EVENT; } else if (!strcmp(count_token[count_index], "fw_event")) { count_token_int[count_index] = COUNT_INT_FW_EVENT; what_to_count_2 |= COUNT_FW_EVENT; } else if (!strcmp(count_token[count_index], "fwd_status")) { count_token_int[count_index] = COUNT_INT_FWD_STATUS; what_to_count_2 |= COUNT_FWD_STATUS; } else if (!strcmp(count_token[count_index], "mpls_label_top")) { count_token_int[count_index] = COUNT_INT_MPLS_LABEL_TOP; what_to_count_2 |= COUNT_MPLS_LABEL_TOP; } else if (!strcmp(count_token[count_index], "mpls_label_bottom")) { count_token_int[count_index] = COUNT_INT_MPLS_LABEL_BOTTOM; what_to_count_2 |= COUNT_MPLS_LABEL_BOTTOM; } else if (!strcmp(count_token[count_index], "timestamp_start")) { count_token_int[count_index] = COUNT_INT_TIMESTAMP_START; what_to_count_2 |= COUNT_TIMESTAMP_START; } else if (!strcmp(count_token[count_index], "timestamp_end")) { count_token_int[count_index] = COUNT_INT_TIMESTAMP_END; what_to_count_2 |= COUNT_TIMESTAMP_END; } else if (!strcmp(count_token[count_index], "timestamp_arrival")) { count_token_int[count_index] = COUNT_INT_TIMESTAMP_ARRIVAL; what_to_count_2 |= COUNT_TIMESTAMP_ARRIVAL; } else if (!strcmp(count_token[count_index], "timestamp_export")) { count_token_int[count_index] = COUNT_INT_EXPORT_PROTO_TIME; what_to_count_2 |= COUNT_EXPORT_PROTO_TIME; } else if (!strcmp(count_token[count_index], "export_proto_seqno")) { count_token_int[count_index] = COUNT_INT_EXPORT_PROTO_SEQNO; what_to_count_2 |= COUNT_EXPORT_PROTO_SEQNO; } else if (!strcmp(count_token[count_index], "export_proto_version")) { count_token_int[count_index] = COUNT_INT_EXPORT_PROTO_VERSION; what_to_count_2 |= COUNT_EXPORT_PROTO_VERSION; } else if (!strcmp(count_token[count_index], "export_proto_sysid")) { count_token_int[count_index] = COUNT_INT_EXPORT_PROTO_SYSID; what_to_count_2 |= COUNT_EXPORT_PROTO_SYSID; } else if (!strcmp(count_token[count_index], "label")) { count_token_int[count_index] = COUNT_INT_LABEL; what_to_count_2 |= COUNT_LABEL; } else { strlcpy(custom_primitives_input.primitive[custom_primitives_input.num].name, count_token[count_index], MAX_CUSTOM_PRIMITIVE_NAMELEN); custom_primitives_input.num++; } what_to_count |= COUNT_COUNTERS; /* we always count counters ;-) */ count_index++; } break; case 'C': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); q.type |= WANT_CLASS_TABLE; q.num = 1; want_class_table = TRUE; break; case 'U': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); q.type |= WANT_CUSTOM_PRIMITIVES_TABLE; q.num = 1; want_custom_primitives_table = TRUE; break; case 'e': q.type |= WANT_ERASE; want_erase = TRUE; break; case 'i': q.type |= WANT_ERASE_LAST_TSTAMP; want_erase_last_tstamp = TRUE; break; case 't': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); q.type |= WANT_STATUS; want_status = TRUE; break; case 'I': want_tstamp_since_epoch = TRUE; break; case '0': want_tstamp_utc = TRUE; break; case 'l': q.type |= WANT_LOCK_OP; break; case 'm': /* obsoleted */ want_mrtg = TRUE; (void)want_mrtg; case 'N': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); strlcpy(match_string, optarg, sizeof(match_string)); match_string[LARGEBUFLEN-1] = '\0'; q.type |= WANT_COUNTER; want_counter = TRUE; break; case 'n': strlcpy(tmpbuf, optarg, sizeof(tmpbuf)); pmc_lower_string(tmpbuf); if (!strcmp(tmpbuf, "bytes")) which_counter = 0; else if (!strcmp(tmpbuf, "packets")) which_counter = 1; else if (!strcmp(tmpbuf, "flows")) which_counter = 3; else if (!strcmp(tmpbuf, "all")) which_counter = 2; else printf("WARN: -n, ignoring unknown counter type: %s.\n", tmpbuf); break; case 'T': strlcpy(tmpbuf, optarg, sizeof(tmpbuf)); pmc_lower_string(tmpbuf); topN_howmany_ptr = strchr(tmpbuf, ','); if (topN_howmany_ptr) { *topN_howmany_ptr = '\0'; topN_howmany_ptr++; topN_howmany = strtoul(topN_howmany_ptr, &endptr, 10); } if (!strcmp(tmpbuf, "bytes")) topN_counter = 1; else if (!strcmp(tmpbuf, "packets")) topN_counter = 2; else if (!strcmp(tmpbuf, "flows")) topN_counter = 3; else printf("WARN: -T, ignoring unknown counter type: %s.\n", tmpbuf); break; case 'S': sum_counters = TRUE; break; case 'M': if (CHECK_Q_TYPE(q.type)) print_ex_options_error(); strlcpy(match_string, optarg, sizeof(match_string)); match_string[LARGEBUFLEN-1] = '\0'; q.type |= WANT_MATCH; want_match = TRUE; break; case 'p': strlcpy(path, optarg, sizeof(path)); break; case 'P': strlcpy(password, optarg, sizeof(password)); break; case 'a': want_all_fields = TRUE; break; case 'r': q.type |= WANT_RESET; want_reset = TRUE; break; case 'O': strlcpy(tmpbuf, optarg, sizeof(tmpbuf)); pmc_lower_string(tmpbuf); if (!strcmp(tmpbuf, "formatted")) want_output = PRINT_OUTPUT_FORMATTED; else if (!strcmp(tmpbuf, "csv")) want_output = PRINT_OUTPUT_CSV; else if (!strcmp(tmpbuf, "json")) { #ifdef WITH_JANSSON want_output = PRINT_OUTPUT_JSON; #else want_output = PRINT_OUTPUT_JSON; printf("WARN: -O set to json but will produce no output (missing --enable-jansson).\n"); #endif } else if (!strcmp(tmpbuf, "event_formatted")) { want_output = PRINT_OUTPUT_FORMATTED; want_output |= PRINT_OUTPUT_EVENT; } else if (!strcmp(tmpbuf, "event_csv")) { want_output = PRINT_OUTPUT_CSV; want_output |= PRINT_OUTPUT_EVENT; } else printf("WARN: -O, ignoring unknown output value: '%s'.\n", tmpbuf); break; case 'E': strlcpy(sep, optarg, sizeof(sep)); break; case 'u': want_ipproto_num = TRUE; break; case 'h': usage_client(argv[0]); exit(0); break; case 'V': version_client(argv[0]); exit(0); break; default: printf("ERROR: parameter %c unknown! \n Exiting...\n\n", cp); usage_client(argv[0]); exit(1); break; } } /* first off let's fetch the list of custom primitives loaded at the server we are connecting to */ { struct query_header qhdr; memset(&qhdr, 0, sizeof(struct query_header)); qhdr.type = WANT_CUSTOM_PRIMITIVES_TABLE; qhdr.num = 1; memcpy(clibuf, &qhdr, sizeof(struct query_header)); buflen = sizeof(struct query_header); buflen++; clibuf[buflen] = '\x4'; /* EOT */ buflen++; // XXX: transfer entry by entry like class tables assert(sizeof(struct imt_custom_primitives)+sizeof(struct query_header) < LARGEBUFLEN); sd = build_query_client(path); send(sd, clibuf, buflen, 0); unpacked = Recv(sd, &cpt); if (unpacked) { memcpy(&pmc_custom_primitives_registry, cpt+sizeof(struct query_header), sizeof(struct imt_custom_primitives)); if (want_custom_primitives_table) { int idx; /* table header */ printf("NAME "); printf("LEN "); printf("OFF\n"); for (idx = 0; idx < pmc_custom_primitives_registry.num; idx++) { printf("%-32s %-5u %-5u\n", pmc_custom_primitives_registry.primitive[idx].name, pmc_custom_primitives_registry.primitive[idx].len, pmc_custom_primitives_registry.primitive[idx].off); } exit(1); } /* if we were invoked with -c, let's check we do not have unknown primitives */ if (custom_primitives_input.num) { int idx, idx2, found; for (idx = 0; idx < custom_primitives_input.num; idx++) { found = FALSE; for (idx2 = 0; idx2 < pmc_custom_primitives_registry.num; idx2++) { if (!strcmp(custom_primitives_input.primitive[idx].name, pmc_custom_primitives_registry.primitive[idx2].name)) { found = TRUE; break; } } if (!found) { printf("ERROR: unknown primitive '%s'\n", custom_primitives_input.primitive[idx].name); exit(1); } } } } else { printf("ERROR: missing EOF from server (1)\n"); exit(1); } } /* some post-getopt-processing task */ if (want_output & PRINT_OUTPUT_EVENT) is_event = TRUE; if (!q.type) { printf("ERROR: no options specified. Either -s, -e, -t, -M, -N or -C must be supplied. \n Exiting...\n\n"); usage_client(argv[0]); exit(1); } if ((want_counter || want_match) && (!what_to_count && !what_to_count_2)) { printf("ERROR: -N or -M selected but -c has not been specified or is invalid.\n Exiting...\n\n"); usage_client(argv[0]); exit(1); } if (want_reset && !(want_counter || want_match)) { printf("ERROR: -r selected but either -N or -M has not been specified.\n Exiting...\n\n"); usage_client(argv[0]); exit(1); } if ((which_counter||sum_counters) && !want_counter) { printf("ERROR: -n and -S options apply only to -N\n Exiting...\n\n"); usage_client(argv[0]); exit(1); } if (topN_counter && (!want_match && !want_stats)) { printf("ERROR: -T option apply only to -M or -s\n Exiting...\n\n"); usage_client(argv[0]); exit(1); } if (want_counter || want_match) { char *ptr = match_string, prefix[] = "file:"; while(isspace(*ptr)) ptr++; if (!strncmp(ptr, prefix, strlen(prefix))) { fetch_from_file = TRUE; ptr += strlen(prefix); strlcpy(file, ptr, sizeof(file)); } } sep_len = strlen(sep); if (!sep_len) sep_ptr = DEFAULT_SEP; else if (sep_len == 1) sep_ptr = sep; else { if (!strcmp(sep, "\\t")) { spacing_sep[0] = '\t'; spacing_sep[1] = '\0'; sep_ptr = spacing_sep; } else if (!strcmp(sep, "\\s")) { spacing_sep[0] = ' '; spacing_sep[1] = '\0'; sep_ptr = spacing_sep; } else { printf("ERROR: -E option expects a single char as separator\n Exiting...\n\n"); exit(1); } } memcpy(q.passwd, password, sizeof(password)); /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; if (want_counter || want_match) { FILE *f; int strnum; char **strings, *tptr1, *tptr2, tmpstr[SRVBUFLEN]; char *tmpbuf, *tmpbufptr; /* 1st step: count how many queries we will have */ if (!fetch_from_file) { for (strnum = 0, tptr1 = match_string; tptr1 && (strnum < MAX_QUERIES); strnum++) { tptr2 = tptr1; tptr1 = strchr(tptr1, ';'); if (tptr1) { if (*tptr2 == *tptr1) strnum--; /* void string */ tptr1++; } } } else { if ((f = fopen(file, "r")) == NULL) { printf("ERROR: file '%s' not found\n", file); exit(1); } else { strnum = 0; while (!feof(f) && (strnum < MAX_QUERIES)) { if (fgets(tmpstr, SRVBUFLEN, f)) { if (!pmc_sanitize_buf(tmpstr)) strnum++; } } } } strings = malloc((strnum+1)*sizeof(char *)); if (!strings) { printf("ERROR: Unable to allocate sufficient memory.\n"); exit(1); } memset(strings, 0, (strnum+1)*sizeof(char *)); if (fetch_from_file) { tmpbuf = malloc((strnum+1)*SRVBUFLEN); if (!tmpbuf) { printf("ERROR: Unable to allocate sufficient memory.\n"); exit(1); } memset(tmpbuf, 0, (strnum+1)*SRVBUFLEN); } /* 2nd step: tokenize the whole string */ if (!fetch_from_file) { for (strnum = 0, tptr1 = match_string; tptr1 && (strnum < MAX_QUERIES); strnum++) { tptr2 = tptr1; tptr1 = strchr(tptr1, ';'); if (tptr1) *tptr1 = '\0'; if (strlen(tptr2)) strings[strnum] = tptr2; else strnum--; /* void string */ if (tptr1) tptr1++; } } else { if (!freopen(file, "r", f)) { printf("ERROR: freopen() failed: %s\n", strerror(errno)); exit(1); } strnum = 0; tmpbufptr = tmpbuf; while (!feof(f) && (strnum < MAX_QUERIES)) { if (fgets(tmpbufptr, SRVBUFLEN, f)) { tmpbufptr[SRVBUFLEN-1] = '\0'; if (!pmc_sanitize_buf(tmpbufptr)) { strings[strnum] = tmpbufptr; strnum++; tmpbufptr += SRVBUFLEN; } } } fclose(f); } bufptr = clibuf; bufptr += sizeof(struct query_header); /* 4th step: build queries */ for (q.num = 0; (q.num < strnum) && (q.num < MAX_QUERIES); q.num++) { match_string_ptr = strings[q.num]; match_string_index = 0; memset(&request, 0, sizeof(struct query_entry)); request.what_to_count = what_to_count; request.what_to_count_2 = what_to_count_2; while ((*match_string_ptr != '\0') && (match_string_index < count_index)) { match_string_token = pmc_extract_token(&match_string_ptr, ','); /* Handling wildcards meaningfully */ if (!strcmp(match_string_token, "*")) { pm_cfgreg_t index = (count_token_int[match_string_index] >> COUNT_REGISTRY_BITS) & COUNT_INDEX_MASK; if (index == 1) request.what_to_count ^= count_token_int[match_string_index]; else if (index == 2) request.what_to_count_2 ^= count_token_int[match_string_index]; match_string_index++; continue; } if (!strcmp(count_token[match_string_index], "src_host") || !strcmp(count_token[match_string_index], "sum_host")) { if (!str_to_addr(match_string_token, &request.data.src_ip)) { printf("ERROR: src_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "src_net") || !strcmp(count_token[match_string_index], "sum_net")) { if (!str_to_addr(match_string_token, &request.data.src_net)) { printf("ERROR: src_host: Invalid IP network: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "dst_host")) { if (!str_to_addr(match_string_token, &request.data.dst_ip)) { printf("ERROR: dst_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "dst_net")) { if (!str_to_addr(match_string_token, &request.data.dst_net)) { printf("ERROR: dst_host: Invalid IP network: '%s'\n", match_string_token); exit(1); } } #if defined (HAVE_L2) else if (!strcmp(count_token[match_string_index], "src_mac") || !strcmp(count_token[match_string_index], "sum_mac")) { unsigned char ethaddr[ETH_ADDR_LEN]; int res; res = string_etheraddr(match_string_token, ethaddr); if (res) { printf("ERROR: src_mac: Invalid MAC address: '%s'\n", match_string_token); exit(1); } else memcpy(&request.data.eth_shost, ethaddr, ETH_ADDR_LEN); } else if (!strcmp(count_token[match_string_index], "dst_mac")) { unsigned char ethaddr[ETH_ADDR_LEN]; int res; res = string_etheraddr(match_string_token, ethaddr); if (res) { printf("ERROR: dst_mac: Invalid MAC address: '%s'\n", match_string_token); exit(1); } else memcpy(&request.data.eth_dhost, ethaddr, ETH_ADDR_LEN); } else if (!strcmp(count_token[match_string_index], "vlan")) { request.data.vlan_id = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "out_vlan")) { request.data.out_vlan_id = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "cos")) { request.data.cos = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "etype")) { sscanf(match_string_token, "%hx", &request.data.etype); } #endif else if (!strcmp(count_token[match_string_index], "in_iface")) { char *endptr; request.data.ifindex_in = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "out_iface")) { char *endptr; request.data.ifindex_out = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "src_mask")) { char *endptr; u_int32_t src_mask; src_mask = strtoul(match_string_token, &endptr, 10); request.data.src_nmask = src_mask; } else if (!strcmp(count_token[match_string_index], "dst_mask")) { char *endptr; u_int32_t dst_mask; dst_mask = strtoul(match_string_token, &endptr, 10); request.data.dst_nmask = dst_mask; } else if (!strcmp(count_token[match_string_index], "src_port") || !strcmp(count_token[match_string_index], "sum_port")) { request.data.src_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "dst_port")) { request.data.dst_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "tos")) { tmpnum = atoi(match_string_token); request.data.tos = (u_int8_t) tmpnum; } #if defined WITH_GEOIP else if (!strcmp(count_token[match_string_index], "src_host_country")) { request.data.src_ip_country.id = GeoIP_id_by_code(match_string_token); } else if (!strcmp(count_token[match_string_index], "dst_host_country")) { request.data.dst_ip_country.id = GeoIP_id_by_code(match_string_token); } #endif #if defined WITH_GEOIPV2 else if (!strcmp(count_token[match_string_index], "src_host_country")) { strlcpy(request.data.src_ip_country.str, match_string_token, PM_COUNTRY_T_STRLEN); } else if (!strcmp(count_token[match_string_index], "dst_host_country")) { strlcpy(request.data.dst_ip_country.str, match_string_token, PM_COUNTRY_T_STRLEN); } else if (!strcmp(count_token[match_string_index], "src_host_pocode")) { strlcpy(request.data.src_ip_pocode.str, match_string_token, PM_POCODE_T_STRLEN); } else if (!strcmp(count_token[match_string_index], "dst_host_pocode")) { strlcpy(request.data.dst_ip_pocode.str, match_string_token, PM_POCODE_T_STRLEN); } else if (!strcmp(count_token[match_string_index], "src_host_coords")) { char *lat_token, *lon_token, *coord_str = strdup(match_string_token), coord_delim[] = ":"; lat_token = strtok(coord_str, coord_delim); lon_token = strtok(NULL, coord_delim); if (!lat_token || !lon_token) { printf("ERROR: src_host_coords: Invalid coordinates: '%s'.\n", match_string_token); printf("ERROR: Expected format: :\n"); exit(1); } request.data.src_ip_lat = atof(lat_token); request.data.src_ip_lon = atof(lon_token); free(coord_str); } else if (!strcmp(count_token[match_string_index], "dst_host_coords")) { char *lat_token, *lon_token, *coord_str = strdup(match_string_token), coord_delim[] = ":"; lat_token = strtok(coord_str, coord_delim); lon_token = strtok(NULL, coord_delim); if (!lat_token || !lon_token) { printf("ERROR: dst_host_coords: Invalid coordinates: '%s'.\n", match_string_token); printf("ERROR: Expected format: :\n"); exit(1); } request.data.dst_ip_lat = atof(lat_token); request.data.dst_ip_lon = atof(lon_token); free(coord_str); } #endif else if (!strcmp(count_token[match_string_index], "sampling_rate")) { request.data.sampling_rate = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "sampling_direction")) { request.data.sampling_direction = sampling_direction_str2id(match_string_token); } else if (!strcmp(count_token[match_string_index], "proto")) { int proto = 0; if (!want_ipproto_num) { for (index = 0; _protocols[index].number != -1; index++) { if (!strcmp(_protocols[index].name, match_string_token)) { proto = _protocols[index].number; break; } } if (proto <= 0) { proto = atoi(match_string_token); if ((proto <= 0) || (proto > 255)) { printf("ERROR: invalid protocol: '%s'\n", match_string_token); exit(1); } } } else { proto = atoi(match_string_token); if ((proto <= 0) || (proto > 255)) { printf("ERROR: invalid protocol: '%s'\n", match_string_token); exit(1); } } request.data.proto = proto; } else if (!strcmp(count_token[match_string_index], "none")); else if (!strcmp(count_token[match_string_index], "src_as") || !strcmp(count_token[match_string_index], "sum_as")) { char *endptr; request.data.src_as = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "dst_as")) { char *endptr; request.data.dst_as = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "tag")) { char *endptr = NULL; u_int32_t value; value = strtoull(match_string_token, &endptr, 10); request.data.tag = value; } else if (!strcmp(count_token[match_string_index], "tag2")) { char *endptr = NULL; u_int32_t value; value = strtoull(match_string_token, &endptr, 10); request.data.tag2 = value; } else if (!strcmp(count_token[match_string_index], "class")) { struct query_header qhdr; char sclass[MAX_PROTOCOL_LEN]; pm_class_t value = 0; memset(sclass, 0, sizeof(sclass)); strlcpy(sclass, match_string_token, MAX_PROTOCOL_LEN); sclass[MAX_PROTOCOL_LEN-1] = '\0'; if (!strcmp("unknown", sclass)) request.data.class = 0; else { memset(&qhdr, 0, sizeof(struct query_header)); qhdr.type = WANT_CLASS_TABLE; qhdr.num = 1; memcpy(clibuf, &qhdr, sizeof(struct query_header)); buflen = sizeof(struct query_header); buflen++; clibuf[buflen] = '\x4'; /* EOT */ buflen++; sd = build_query_client(path); send(sd, clibuf, buflen, 0); unpacked = Recv(sd, &ct); if (unpacked) { ct_num = ((struct query_header *)ct)->num; elem = ct+sizeof(struct query_header); class_table = (struct stripped_class *) elem; ct_idx = 0; while (ct_idx < ct_num) { class_table[ct_idx].protocol[MAX_PROTOCOL_LEN-1] = '\0'; if (!strcasecmp(class_table[ct_idx].protocol, sclass)) { value = class_table[ct_idx].id; break; } ct_idx++; } if (!value) { printf("ERROR: Server has not loaded any classifier for '%s'.\n", sclass); exit(1); } else { #if defined (WITH_NDPI) request.data.ndpi_class.master_protocol = FALSE; request.data.ndpi_class.app_protocol = class_table[ct_idx].id; request.data.ndpi_class.category = class_table[ct_idx].category; #endif } /* in case we did hit the break */ ct_idx = (ct_num - 1); } else { printf("ERROR: missing EOF from server (2)\n"); exit(1); } } } else if (!strcmp(count_token[match_string_index], "std_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.std_comms, 0, MAX_BGP_STD_COMMS); else { strlcpy(request.plbgp.std_comms, match_string_token, MAX_BGP_STD_COMMS); bgp_comm = request.plbgp.std_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.std_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "src_std_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.src_std_comms, 0, MAX_BGP_STD_COMMS); else { strlcpy(request.plbgp.src_std_comms, match_string_token, MAX_BGP_STD_COMMS); bgp_comm = request.plbgp.src_std_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.src_std_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "ext_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.ext_comms, 0, MAX_BGP_EXT_COMMS); else { strlcpy(request.plbgp.ext_comms, match_string_token, MAX_BGP_EXT_COMMS); bgp_comm = request.plbgp.ext_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.ext_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "src_ext_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.src_ext_comms, 0, MAX_BGP_EXT_COMMS); else { strlcpy(request.plbgp.src_ext_comms, match_string_token, MAX_BGP_EXT_COMMS); bgp_comm = request.plbgp.src_ext_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.src_ext_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "lrg_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.lrg_comms, 0, MAX_BGP_LRG_COMMS); else { strlcpy(request.plbgp.lrg_comms, match_string_token, MAX_BGP_LRG_COMMS); bgp_comm = request.plbgp.lrg_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.lrg_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "src_lrg_comm")) { if (!strcmp(match_string_token, "0")) memset(request.plbgp.src_lrg_comms, 0, MAX_BGP_LRG_COMMS); else { strlcpy(request.plbgp.src_lrg_comms, match_string_token, MAX_BGP_LRG_COMMS); bgp_comm = request.plbgp.src_lrg_comms; while (bgp_comm) { bgp_comm = strchr(request.plbgp.src_lrg_comms, '_'); if (bgp_comm) *bgp_comm = ' '; } } } else if (!strcmp(count_token[match_string_index], "as_path")) { if (!strcmp(match_string_token, "^$")) memset(request.plbgp.as_path, 0, MAX_BGP_ASPATH); else { strlcpy(request.plbgp.as_path, match_string_token, MAX_BGP_ASPATH); as_path = request.plbgp.as_path; while (as_path) { as_path = strchr(request.plbgp.as_path, '_'); if (as_path) *as_path = ' '; } } } else if (!strcmp(count_token[match_string_index], "src_as_path")) { if (!strcmp(match_string_token, "^$")) memset(request.plbgp.src_as_path, 0, MAX_BGP_ASPATH); else { strlcpy(request.plbgp.src_as_path, match_string_token, MAX_BGP_ASPATH); as_path = request.plbgp.src_as_path; while (as_path) { as_path = strchr(request.plbgp.src_as_path, '_'); if (as_path) *as_path = ' '; } } } else if (!strcmp(count_token[match_string_index], "local_pref")) { char *endptr; request.pbgp.local_pref = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "src_local_pref")) { char *endptr; request.pbgp.src_local_pref = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "med")) { char *endptr; request.pbgp.med = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "src_med")) { char *endptr; request.pbgp.src_med = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "src_roa")) { request.pbgp.src_roa = pmc_rpki_str2roa(match_string_token); } else if (!strcmp(count_token[match_string_index], "dst_roa")) { request.pbgp.dst_roa = pmc_rpki_str2roa(match_string_token); } else if (!strcmp(count_token[match_string_index], "peer_src_as")) { char *endptr; request.pbgp.peer_src_as = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "peer_dst_as")) { char *endptr; request.pbgp.peer_dst_as = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "peer_src_ip")) { if (!str_to_addr(match_string_token, &request.pbgp.peer_src_ip)) { printf("ERROR: peer_src_ip: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "peer_dst_ip")) { if (!str_to_addr(match_string_token, &request.pbgp.peer_dst_ip)) { printf("ERROR: peer_dst_ip: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "mpls_vpn_rd")) { if (!pmc_bgp_str2rd((rd_t *) &request.pbgp.mpls_vpn_rd, match_string_token)) { printf("ERROR: mpls_vpn_rd: Invalid MPLS VPN RD value: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "mpls_pw_id")) { char *endptr; request.pbgp.mpls_pw_id = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "post_nat_src_host")) { if (!str_to_addr(match_string_token, &request.pnat.post_nat_src_ip)) { printf("ERROR: post_nat_src_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "post_nat_dst_host")) { if (!str_to_addr(match_string_token, &request.pnat.post_nat_dst_ip)) { printf("ERROR: post_nat_dst_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "post_nat_src_port")) { request.pnat.post_nat_src_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "post_nat_dst_port")) { request.pnat.post_nat_dst_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "nat_event")) { request.pnat.nat_event = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "fw_event")) { request.pnat.fw_event = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "mpls_label_top")) { request.pmpls.mpls_label_top = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "mpls_label_bottom")) { request.pmpls.mpls_label_bottom = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "tunnel_src_mac")) { unsigned char ethaddr[ETH_ADDR_LEN]; int res; res = string_etheraddr(match_string_token, ethaddr); if (res) { printf("ERROR: tunnel_src_mac: Invalid MAC address: '%s'\n", match_string_token); exit(1); } else memcpy(&request.ptun.tunnel_eth_shost, ethaddr, ETH_ADDR_LEN); } else if (!strcmp(count_token[match_string_index], "tunnel_dst_mac")) { unsigned char ethaddr[ETH_ADDR_LEN]; int res; res = string_etheraddr(match_string_token, ethaddr); if (res) { printf("ERROR: tunnel_dst_mac: Invalid MAC address: '%s'\n", match_string_token); exit(1); } else memcpy(&request.ptun.tunnel_eth_dhost, ethaddr, ETH_ADDR_LEN); } else if (!strcmp(count_token[match_string_index], "tunnel_src_host")) { if (!str_to_addr(match_string_token, &request.ptun.tunnel_src_ip)) { printf("ERROR: tunnel_src_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "tunnel_dst_host")) { if (!str_to_addr(match_string_token, &request.ptun.tunnel_dst_ip)) { printf("ERROR: tunnel_dst_host: Invalid IP address: '%s'\n", match_string_token); exit(1); } } else if (!strcmp(count_token[match_string_index], "tunnel_proto")) { int proto = 0; if (!want_ipproto_num) { for (index = 0; _protocols[index].number != -1; index++) { if (!strcmp(_protocols[index].name, match_string_token)) { proto = _protocols[index].number; break; } } if (proto <= 0) { proto = atoi(match_string_token); if ((proto <= 0) || (proto > 255)) { printf("ERROR: invalid protocol: '%s'\n", match_string_token); exit(1); } } } else { proto = atoi(match_string_token); if ((proto <= 0) || (proto > 255)) { printf("ERROR: invalid protocol: '%s'\n", match_string_token); exit(1); } } request.ptun.tunnel_proto = proto; } else if (!strcmp(count_token[match_string_index], "tunnel_tos")) { tmpnum = atoi(match_string_token); request.ptun.tunnel_tos = (u_int8_t) tmpnum; } else if (!strcmp(count_token[match_string_index], "tunnel_src_port")) { request.ptun.tunnel_src_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "tunnel_dst_port")) { request.ptun.tunnel_dst_port = atoi(match_string_token); } else if (!strcmp(count_token[match_string_index], "vxlan")) { tmpnum = atoi(match_string_token); request.ptun.tunnel_id = tmpnum; } else if (!strcmp(count_token[match_string_index], "timestamp_start")) { struct tm tmp; char *delim = strchr(match_string_token, '.'); u_int32_t residual = 0; if (delim) { /* we have residual time after secs */ *delim = '\0'; delim++; residual = strtol(delim, NULL, 0); } strptime(match_string_token, "%Y-%m-%dT%H:%M:%S", &tmp); request.pnat.timestamp_start.tv_sec = mktime(&tmp); request.pnat.timestamp_start.tv_usec = residual; } else if (!strcmp(count_token[match_string_index], "timestamp_end")) { struct tm tmp; char *delim = strchr(match_string_token, '.'); u_int32_t residual = 0; if (delim) { /* we have residual time after secs */ *delim = '\0'; delim++; residual = strtol(delim, NULL, 0); } strptime(match_string_token, "%Y-%m-%dT%H:%M:%S", &tmp); request.pnat.timestamp_end.tv_sec = mktime(&tmp); request.pnat.timestamp_end.tv_usec = residual; } else if (!strcmp(count_token[match_string_index], "timestamp_arrival")) { struct tm tmp; char *delim = strchr(match_string_token, '.'); u_int32_t residual = 0; if (delim) { /* we have residual time after secs */ *delim = '\0'; delim++; residual = strtol(delim, NULL, 0); } strptime(match_string_token, "%Y-%m-%dT%H:%M:%S", &tmp); request.pnat.timestamp_arrival.tv_sec = mktime(&tmp); request.pnat.timestamp_arrival.tv_usec = residual; } else if (!strcmp(count_token[match_string_index], "export_proto_seqno")) { char *endptr; request.data.export_proto_seqno = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "export_proto_version")) { char *endptr; request.data.export_proto_version = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "export_proto_sysid")) { char *endptr; request.data.export_proto_sysid = strtoul(match_string_token, &endptr, 10); } else if (!strcmp(count_token[match_string_index], "label")) { // XXX: to be supported in future printf("ERROR: -M and -N are not supported (yet) against variable-length primitives (ie. label)\n"); exit(1); } else { int idx, found; for (idx = 0, found = FALSE; idx < pmc_custom_primitives_registry.num; idx++) { if (!strcmp(count_token[match_string_index], pmc_custom_primitives_registry.primitive[idx].name)) { found = TRUE; break; } } if (!found) { printf("ERROR: unknown primitive '%s'\n", count_token[match_string_index]); exit(1); } else { // XXX: to be supported in future printf("ERROR: -M and -N are not supported (yet) against custom primitives\n"); exit(1); } } match_string_index++; } memcpy(bufptr, &request, sizeof(struct query_entry)); bufptr += sizeof(struct query_entry); } } /* arranging header and size of buffer to send */ memcpy(clibuf, &q, sizeof(struct query_header)); buflen = sizeof(struct query_header)+(q.num*sizeof(struct query_entry)); buflen++; clibuf[buflen] = '\x4'; /* EOT */ buflen++; sd = build_query_client(path); send(sd, clibuf, buflen, 0); /* reading results */ if (want_stats || want_match) { unpacked = Recv(sd, &largebuf); if (!unpacked) { printf("ERROR: missing EOF from server (4)\n"); exit(1); } if (want_all_fields) have_wtc = FALSE; else have_wtc = TRUE; what_to_count = ((struct query_header *)largebuf)->what_to_count; what_to_count_2 = ((struct query_header *)largebuf)->what_to_count_2; datasize = ((struct query_header *)largebuf)->datasize; memcpy(&extras, &((struct query_header *)largebuf)->extras, sizeof(struct extra_primitives)); if (check_data_sizes((struct query_header *)largebuf, acc_elem)) exit(1); /* Before going on with the output, we need to retrieve the class strings from the server */ if (((what_to_count & COUNT_CLASS) || (what_to_count_2 & COUNT_NDPI_CLASS)) && !class_table) { struct query_header qhdr; int unpacked_class; memset(&qhdr, 0, sizeof(struct query_header)); qhdr.type = WANT_CLASS_TABLE; qhdr.num = 1; memcpy(clibuf, &qhdr, sizeof(struct query_header)); buflen = sizeof(struct query_header); buflen++; clibuf[buflen] = '\x4'; /* EOT */ buflen++; sd = build_query_client(path); send(sd, clibuf, buflen, 0); unpacked_class = Recv(sd, &ct); if (unpacked_class) { ct_num = ((struct query_header *)ct)->num; elem = ct+sizeof(struct query_header); class_table = (struct stripped_class *) elem; while (ct_idx < ct_num) { class_table[ct_idx].protocol[MAX_PROTOCOL_LEN-1] = '\0'; ct_idx++; } } else { printf("ERROR: missing EOF from server (5)\n"); exit(1); } } if (want_output & PRINT_OUTPUT_FORMATTED) write_stats_header_formatted(what_to_count, what_to_count_2, have_wtc, is_event); else if (want_output & PRINT_OUTPUT_CSV) write_stats_header_csv(what_to_count, what_to_count_2, have_wtc, sep_ptr, is_event); elem = largebuf+sizeof(struct query_header); unpacked -= sizeof(struct query_header); acc_elem = (struct pkt_data *) elem; topN_printed = 0; if (topN_counter) { int num = unpacked/datasize; client_counters_merge_sort((void *)acc_elem, 0, num, datasize, topN_counter); } while (printed < unpacked && (!topN_howmany || topN_printed < topN_howmany)) { int count = 0; topN_printed++; acc_elem = (struct pkt_data *) elem; if (extras.off_pkt_bgp_primitives) pbgp = (struct pkt_bgp_primitives *) ((u_char *)elem + extras.off_pkt_bgp_primitives); else pbgp = &empty_pbgp; if (extras.off_pkt_lbgp_primitives) plbgp = (struct pkt_legacy_bgp_primitives *) ((u_char *)elem + extras.off_pkt_lbgp_primitives); else plbgp = &empty_plbgp; if (extras.off_pkt_nat_primitives) pnat = (struct pkt_nat_primitives *) ((u_char *)elem + extras.off_pkt_nat_primitives); else pnat = &empty_pnat; if (extras.off_pkt_mpls_primitives) pmpls = (struct pkt_mpls_primitives *) ((u_char *)elem + extras.off_pkt_mpls_primitives); else pmpls = &empty_pmpls; if (extras.off_pkt_tun_primitives) ptun = (struct pkt_tunnel_primitives *) ((u_char *)elem + extras.off_pkt_tun_primitives); else ptun = &empty_ptun; if (extras.off_custom_primitives) pcust = ((u_char *)elem + extras.off_custom_primitives); else pcust = NULL; if (extras.off_pkt_vlen_hdr_primitives) pvlen = (struct pkt_vlen_hdr_primitives *) ((u_char *)elem + extras.off_pkt_vlen_hdr_primitives); else pvlen = &empty_pvlen; if (memcmp(acc_elem, &empty_addr, sizeof(struct pkt_primitives)) != 0 || memcmp(pbgp, &empty_pbgp, sizeof(struct pkt_bgp_primitives)) != 0 || memcmp(plbgp, &empty_plbgp, sizeof(struct pkt_legacy_bgp_primitives)) != 0 || memcmp(pnat, &empty_pnat, sizeof(struct pkt_nat_primitives)) != 0 || memcmp(pmpls, &empty_pmpls, sizeof(struct pkt_mpls_primitives)) != 0 || memcmp(ptun, &empty_ptun, sizeof(struct pkt_tunnel_primitives)) != 0 || pmc_custom_primitives_registry.len || memcmp(pvlen, &empty_pvlen, sizeof(struct pkt_vlen_hdr_primitives)) != 0) { if (!have_wtc || (what_to_count & COUNT_TAG)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10" PRIu64 " ", acc_elem->primitives.tag); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%" PRIu64 "", write_sep(sep_ptr, &count), acc_elem->primitives.tag); } if (!have_wtc || (what_to_count & COUNT_TAG2)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10" PRIu64 " ", acc_elem->primitives.tag2); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%" PRIu64 "", write_sep(sep_ptr, &count), acc_elem->primitives.tag2); } if (!have_wtc || (what_to_count & COUNT_CLASS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-16s ", (acc_elem->primitives.class == 0 || acc_elem->primitives.class > ct_idx || !class_table[acc_elem->primitives.class-1].id) ? "unknown" : class_table[acc_elem->primitives.class-1].protocol); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), (acc_elem->primitives.class == 0 || acc_elem->primitives.class > ct_idx || !class_table[acc_elem->primitives.class-1].id) ? "unknown" : class_table[acc_elem->primitives.class-1].protocol); } #if defined (WITH_NDPI) if (!have_wtc || (what_to_count_2 & COUNT_NDPI_CLASS)) { snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", pmc_ndpi_get_proto_name(acc_elem->primitives.ndpi_class.master_protocol), pmc_ndpi_get_proto_name(acc_elem->primitives.ndpi_class.app_protocol)); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-16s ", ndpi_class); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ndpi_class); } #endif if (!have_wtc || (what_to_count_2 & COUNT_LABEL)) { if (want_output & PRINT_OUTPUT_FORMATTED); /* case not supported */ else if (want_output & PRINT_OUTPUT_CSV) pmc_printf_csv_label(pvlen, COUNT_INT_LABEL, write_sep(sep_ptr, &count), empty_string); } if (!have_wtc || (what_to_count & COUNT_IN_IFACE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", acc_elem->primitives.ifindex_in); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.ifindex_in); } if (!have_wtc || (what_to_count & COUNT_OUT_IFACE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", acc_elem->primitives.ifindex_out); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.ifindex_out); } #if defined (HAVE_L2) if (!have_wtc || (what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC))) { etheraddr_string(acc_elem->primitives.eth_shost, ethernet_address); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-17s ", ethernet_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ethernet_address); } if (!have_wtc || (what_to_count & COUNT_DST_MAC)) { etheraddr_string(acc_elem->primitives.eth_dhost, ethernet_address); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-17s ", ethernet_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ethernet_address); } if (!have_wtc || (what_to_count & COUNT_VLAN)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", acc_elem->primitives.vlan_id); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.vlan_id); } if (!have_wtc || (what_to_count_2 & COUNT_OUT_VLAN)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", acc_elem->primitives.out_vlan_id); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.out_vlan_id); } if (!have_wtc || (what_to_count & COUNT_COS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-2u ", acc_elem->primitives.cos); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.cos); } if (!have_wtc || (what_to_count & COUNT_ETHERTYPE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5x ", acc_elem->primitives.etype); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%x", write_sep(sep_ptr, &count), acc_elem->primitives.etype); } #endif if (!have_wtc || (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS))) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", acc_elem->primitives.src_as); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.src_as); } if (!have_wtc || (what_to_count & COUNT_DST_AS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", acc_elem->primitives.dst_as); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.dst_as); } if (!have_wtc || (what_to_count & COUNT_STD_COMM)) { bgp_comm = plbgp->std_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->std_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->std_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->std_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->std_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_SRC_STD_COMM)) { bgp_comm = plbgp->src_std_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_std_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_std_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->src_std_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->src_std_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (what_to_count & COUNT_EXT_COMM) { bgp_comm = plbgp->ext_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->ext_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->ext_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->ext_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->ext_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (what_to_count & COUNT_SRC_EXT_COMM) { bgp_comm = plbgp->src_ext_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_ext_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_ext_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->src_ext_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->src_ext_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (what_to_count_2 & COUNT_LRG_COMM) { bgp_comm = plbgp->lrg_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->lrg_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->lrg_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->lrg_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->lrg_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (what_to_count_2 & COUNT_SRC_LRG_COMM) { bgp_comm = plbgp->src_lrg_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_lrg_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_lrg_comms)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->src_lrg_comms); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->src_lrg_comms); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_AS_PATH)) { as_path = plbgp->as_path; while (as_path) { as_path = strchr(plbgp->as_path, ' '); if (as_path) *as_path = '_'; } if (strlen(plbgp->as_path)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->as_path); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->as_path); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", empty_aspath); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->as_path); } } if (!have_wtc || (what_to_count & COUNT_SRC_AS_PATH)) { as_path = plbgp->src_as_path; while (as_path) { as_path = strchr(plbgp->src_as_path, ' '); if (as_path) *as_path = '_'; } if (strlen(plbgp->src_as_path)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", plbgp->src_as_path); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->src_as_path); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-22s ", empty_aspath); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), plbgp->src_as_path); } } if (!have_wtc || (what_to_count & COUNT_LOCAL_PREF)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-7u ", pbgp->local_pref); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->local_pref); } if (!have_wtc || (what_to_count & COUNT_SRC_LOCAL_PREF)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-7u ", pbgp->src_local_pref); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->src_local_pref); } if (!have_wtc || (what_to_count & COUNT_MED)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-6u ", pbgp->med); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->med); } if (!have_wtc || (what_to_count & COUNT_SRC_MED)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-6u ", pbgp->src_med); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->src_med); } if (!have_wtc || (what_to_count_2 & COUNT_SRC_ROA)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-6s ", pmc_rpki_roa_print(pbgp->src_roa)); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), pmc_rpki_roa_print(pbgp->src_roa)); } if (!have_wtc || (what_to_count_2 & COUNT_DST_ROA)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-6s ", pmc_rpki_roa_print(pbgp->dst_roa)); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), pmc_rpki_roa_print(pbgp->dst_roa)); } if (!have_wtc || (what_to_count & COUNT_PEER_SRC_AS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", pbgp->peer_src_as); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->peer_src_as); } if (!have_wtc || (what_to_count & COUNT_PEER_DST_AS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", pbgp->peer_dst_as); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->peer_dst_as); } if (!have_wtc || (what_to_count & COUNT_PEER_SRC_IP)) { addr_to_str(ip_address, &pbgp->peer_src_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_PEER_DST_IP)) { addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(acc_elem->flow_type)); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_MPLS_VPN_RD)) { pmc_bgp_rd2str(rd_str, (rd_t *) &pbgp->mpls_vpn_rd); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-18s ", rd_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), rd_str); } if (!have_wtc || (what_to_count_2 & COUNT_MPLS_PW_ID)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", pbgp->mpls_pw_id); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pbgp->mpls_pw_id); } if (!have_wtc || (what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST))) { addr_to_str(ip_address, &acc_elem->primitives.src_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET))) { addr_to_str(ip_address, &acc_elem->primitives.src_net); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_DST_HOST)) { addr_to_str(ip_address, &acc_elem->primitives.dst_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_DST_NET)) { addr_to_str(ip_address, &acc_elem->primitives.dst_net); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count & COUNT_SRC_NMASK)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", acc_elem->primitives.src_nmask); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.src_nmask); } if (!have_wtc || (what_to_count & COUNT_DST_NMASK)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", acc_elem->primitives.dst_nmask); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.dst_nmask); } if (!have_wtc || (what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT))) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", acc_elem->primitives.src_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.src_port); } if (!have_wtc || (what_to_count & COUNT_DST_PORT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", acc_elem->primitives.dst_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.dst_port); } if (!have_wtc || (what_to_count & COUNT_TCPFLAGS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-6u ", acc_elem->tcp_flags); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->tcp_flags); } if (!have_wtc || (what_to_count & COUNT_IP_PROTO)) { if (acc_elem->primitives.proto < protocols_number && !want_ipproto_num) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10s ", _protocols[acc_elem->primitives.proto].name); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), _protocols[acc_elem->primitives.proto].name); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", acc_elem->primitives.proto); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.proto); } } if (!have_wtc || (what_to_count & COUNT_IP_TOS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", acc_elem->primitives.tos); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.tos); } #if defined WITH_GEOIP if (!have_wtc || (what_to_count_2 & COUNT_SRC_HOST_COUNTRY)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5s ", GeoIP_code_by_id(acc_elem->primitives.src_ip_country.id)); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), GeoIP_code_by_id(acc_elem->primitives.src_ip_country.id)); } if (!have_wtc || (what_to_count_2 & COUNT_DST_HOST_COUNTRY)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5s ", GeoIP_code_by_id(acc_elem->primitives.dst_ip_country.id)); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), GeoIP_code_by_id(acc_elem->primitives.dst_ip_country.id)); } #endif #if defined WITH_GEOIPV2 if (!have_wtc || (what_to_count_2 & COUNT_SRC_HOST_COUNTRY)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5s ", acc_elem->primitives.src_ip_country.str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), acc_elem->primitives.src_ip_country.str); } if (!have_wtc || (what_to_count_2 & COUNT_DST_HOST_COUNTRY)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5s ", acc_elem->primitives.dst_ip_country.str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), acc_elem->primitives.dst_ip_country.str); } if (!have_wtc || (what_to_count_2 & COUNT_SRC_HOST_POCODE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-12s ", acc_elem->primitives.src_ip_pocode.str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), acc_elem->primitives.src_ip_pocode.str); } if (!have_wtc || (what_to_count_2 & COUNT_DST_HOST_POCODE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-12s ", acc_elem->primitives.dst_ip_pocode.str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), acc_elem->primitives.dst_ip_pocode.str); } if (!have_wtc || (what_to_count_2 & COUNT_SRC_HOST_COORDS)) { if (want_output & PRINT_OUTPUT_FORMATTED) { printf("%-12f ", acc_elem->primitives.src_ip_lat); printf("%-12f ", acc_elem->primitives.src_ip_lon); } else if (want_output & PRINT_OUTPUT_CSV) { printf("%s%f", write_sep(sep_ptr, &count), acc_elem->primitives.src_ip_lat); printf("%s%f", write_sep(sep_ptr, &count), acc_elem->primitives.src_ip_lon); } } if (!have_wtc || (what_to_count_2 & COUNT_DST_HOST_COORDS)) { if (want_output & PRINT_OUTPUT_FORMATTED) { printf("%-12f ", acc_elem->primitives.dst_ip_lat); printf("%-12f ", acc_elem->primitives.dst_ip_lon); } else if (want_output & PRINT_OUTPUT_CSV) { printf("%s%f", write_sep(sep_ptr, &count), acc_elem->primitives.dst_ip_lat); printf("%s%f", write_sep(sep_ptr, &count), acc_elem->primitives.dst_ip_lon); } } #endif if (!have_wtc || (what_to_count_2 & COUNT_SAMPLING_RATE)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-7u ", acc_elem->primitives.sampling_rate); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.sampling_rate); } if (!have_wtc || (what_to_count_2 & COUNT_SAMPLING_DIRECTION)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-1s ", pmc_sampling_direction_print(acc_elem->primitives.sampling_direction)); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), sampling_direction_print(acc_elem->primitives.sampling_direction)); } if (!have_wtc || (what_to_count_2 & COUNT_POST_NAT_SRC_HOST)) { addr_to_str(ip_address, &pnat->post_nat_src_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count_2 & COUNT_POST_NAT_DST_HOST)) { addr_to_str(ip_address, &pnat->post_nat_dst_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count_2 & COUNT_POST_NAT_SRC_PORT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", pnat->post_nat_src_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pnat->post_nat_src_port); } if (!have_wtc || (what_to_count_2 & COUNT_POST_NAT_DST_PORT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", pnat->post_nat_dst_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pnat->post_nat_dst_port); } if (!have_wtc || (what_to_count_2 & COUNT_NAT_EVENT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", pnat->nat_event); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pnat->nat_event); } if (!have_wtc || (what_to_count_2 & COUNT_FW_EVENT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", pnat->fw_event); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pnat->fw_event); } if (!have_wtc || (what_to_count_2 & COUNT_FWD_STATUS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", pnat->fwd_status); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pnat->fwd_status); } if (!have_wtc || (what_to_count_2 & COUNT_MPLS_LABEL_TOP)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-7u ", pmpls->mpls_label_top); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pmpls->mpls_label_top); } if (!have_wtc || (what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-7u ", pmpls->mpls_label_bottom); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), pmpls->mpls_label_bottom); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_SRC_MAC)) { etheraddr_string(ptun->tunnel_eth_shost, ethernet_address); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-17s ", ethernet_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ethernet_address); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_DST_MAC)) { etheraddr_string(ptun->tunnel_eth_dhost, ethernet_address); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-17s ", ethernet_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ethernet_address); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_SRC_HOST)) { addr_to_str(ip_address, &ptun->tunnel_src_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_DST_HOST)) { addr_to_str(ip_address, &ptun->tunnel_dst_ip); if (strlen(ip_address)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45s ", ip_address); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), ip_address); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-45u ", 0); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), empty_string); } } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_IP_PROTO)) { if (ptun->tunnel_proto < protocols_number && !want_ipproto_num) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10s ", _protocols[ptun->tunnel_proto].name); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), _protocols[ptun->tunnel_proto].name); } else { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-10u ", ptun->tunnel_proto); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), ptun->tunnel_proto); } } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_IP_TOS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", ptun->tunnel_tos); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), ptun->tunnel_tos); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_SRC_PORT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", ptun->tunnel_src_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), ptun->tunnel_src_port); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_DST_PORT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-5u ", ptun->tunnel_dst_port); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), ptun->tunnel_dst_port); } if (!have_wtc || (what_to_count_2 & COUNT_TUNNEL_TCPFLAGS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-3u ", acc_elem->tunnel_tcp_flags); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->tunnel_tcp_flags); } if (!have_wtc || (what_to_count_2 & COUNT_VXLAN)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-8u ", ptun->tunnel_id); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), ptun->tunnel_id); } if (!have_wtc || (what_to_count_2 & COUNT_TIMESTAMP_START)) { char tstamp_str[SRVBUFLEN]; pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_start, TRUE, want_tstamp_since_epoch, want_tstamp_utc); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-30s ", tstamp_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), tstamp_str); } if (!have_wtc || (what_to_count_2 & COUNT_TIMESTAMP_END)) { char tstamp_str[SRVBUFLEN]; pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_end, TRUE, want_tstamp_since_epoch, want_tstamp_utc); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-30s ", tstamp_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), tstamp_str); } if (!have_wtc || (what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL)) { char tstamp_str[SRVBUFLEN]; pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_arrival, TRUE, want_tstamp_since_epoch, want_tstamp_utc); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-30s ", tstamp_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), tstamp_str); } if (!have_wtc || (what_to_count_2 & COUNT_EXPORT_PROTO_TIME)) { char tstamp_str[SRVBUFLEN]; pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_export, TRUE, want_tstamp_since_epoch, want_tstamp_utc); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-30s ", tstamp_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), tstamp_str); } if (!have_wtc || (what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-18u ", acc_elem->primitives.export_proto_seqno); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.export_proto_seqno); } if (!have_wtc || (what_to_count_2 & COUNT_EXPORT_PROTO_VERSION)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-20u ", acc_elem->primitives.export_proto_version); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.export_proto_version); } if (!have_wtc || (what_to_count_2 & COUNT_EXPORT_PROTO_SYSID)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-18u ", acc_elem->primitives.export_proto_sysid); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%u", write_sep(sep_ptr, &count), acc_elem->primitives.export_proto_sysid); } /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { pmc_custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &pmc_custom_primitives_registry.primitive[cp_idx], want_output & PRINT_OUTPUT_FORMATTED ? 1 : 0); if (want_output & PRINT_OUTPUT_FORMATTED) printf("%s ", cp_str); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%s", write_sep(sep_ptr, &count), cp_str); } } if (!(want_output & PRINT_OUTPUT_EVENT)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-20" PRIu64 " ", acc_elem->pkt_num); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%" PRIu64 "", write_sep(sep_ptr, &count), acc_elem->pkt_num); if (!have_wtc || (what_to_count & COUNT_FLOWS)) { if (want_output & PRINT_OUTPUT_FORMATTED) printf("%-20" PRIu64 " ", acc_elem->flo_num); else if (want_output & PRINT_OUTPUT_CSV) printf("%s%" PRIu64 "", write_sep(sep_ptr, &count), acc_elem->flo_num); } if (want_output & (PRINT_OUTPUT_FORMATTED|PRINT_OUTPUT_CSV)) printf("%s%" PRIu64 "\n", write_sep(sep_ptr, &count), acc_elem->pkt_len); } else printf("\n"); if (want_output & PRINT_OUTPUT_JSON) { char *json_str; json_str = pmc_compose_json(what_to_count, what_to_count_2, acc_elem->flow_type, &acc_elem->primitives, pbgp, plbgp, pnat, pmpls, ptun, pcust, pvlen, acc_elem->pkt_len, acc_elem->pkt_num, acc_elem->flo_num, acc_elem->tcp_flags, acc_elem->tunnel_tcp_flags, NULL, want_tstamp_since_epoch, want_tstamp_utc); if (json_str) { printf("%s\n", json_str); free(json_str); } } counter++; } elem += datasize; printed += datasize; } if (want_output & PRINT_OUTPUT_FORMATTED) printf("\nFor a total of: %d entries\n", counter); } else if (want_erase) printf("OK: Clearing stats.\n"); else if (want_erase_last_tstamp) { struct timeval cycle_stamp, table_reset_stamp; gettimeofday(&cycle_stamp, NULL); unpacked = Recv(sd, &largebuf); if (unpacked == (sizeof(struct query_header) + sizeof(struct timeval))) { memcpy(&table_reset_stamp, (largebuf + sizeof(struct query_header)), sizeof(struct timeval)); if (table_reset_stamp.tv_sec) printf("%ld\n", (long)(cycle_stamp.tv_sec - table_reset_stamp.tv_sec)); else printf("never\n"); } } else if (want_status) { unpacked = Recv(sd, &largebuf); if (unpacked) { write_status_header(); elem = largebuf+sizeof(struct query_header); unpacked -= sizeof(struct query_header); while (printed < unpacked) { bd = (struct bucket_desc *) elem; printf("%u\t", bd->num); while (bd->howmany > 0) { printf("*"); bd->howmany--; } printf("\n"); elem += sizeof(struct bucket_desc); printed += sizeof(struct bucket_desc); } } else { printf("ERROR: missing EOF from server (7)\n"); exit(1); } } else if (want_counter) { unsigned char *base; u_int64_t bcnt = 0, pcnt = 0, fcnt = 0; int printed; unpacked = Recv(sd, &largebuf); if (!unpacked) { printf("ERROR: missing EOF from server (8)\n"); exit(1); } base = largebuf+sizeof(struct query_header); if (check_data_sizes((struct query_header *)largebuf, acc_elem)) exit(1); acc_elem = (struct pkt_data *) base; for (printed = sizeof(struct query_header); printed < unpacked; printed += sizeof(struct pkt_data), acc_elem++) { if (sum_counters) { pcnt += acc_elem->pkt_num; fcnt += acc_elem->flo_num; bcnt += acc_elem->pkt_len; num_counters += acc_elem->time_start.tv_sec; /* XXX: this field is used here to count how much entries we are accumulating */ } else { /* print bytes */ if (which_counter == 0) printf("%" PRIu64 "\n", acc_elem->pkt_len); /* print packets */ else if (which_counter == 1) printf("%" PRIu64 "\n", acc_elem->pkt_num); /* print packets+bytes+flows+num */ else if (which_counter == 2) printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %lu\n", acc_elem->pkt_num, acc_elem->pkt_len, acc_elem->flo_num, acc_elem->time_start.tv_sec); /* print flows */ else if (which_counter == 3) printf("%" PRIu64 "\n", acc_elem->flo_num); } } if (sum_counters) { if (which_counter == 0) printf("%" PRIu64 "\n", bcnt); /* print bytes */ else if (which_counter == 1) printf("%" PRIu64 "\n", pcnt); /* print packets */ else if (which_counter == 2) printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %u\n", pcnt, bcnt, fcnt, num_counters); /* print packets+bytes+flows+num */ else if (which_counter == 3) printf("%" PRIu64 "\n", fcnt); /* print flows */ } } else if (want_class_table) { int ct_eff=0; unpacked = Recv(sd, &ct); if (unpacked) { write_class_table_header(); ct_num = ((struct query_header *)ct)->num; elem = ct+sizeof(struct query_header); class_table = (struct stripped_class *) elem; while (ct_idx < ct_num) { class_table[ct_idx].protocol[MAX_PROTOCOL_LEN-1] = '\0'; if (class_table[ct_idx].id) { printf("%u\t\t%s\n", class_table[ct_idx].id, class_table[ct_idx].protocol); ct_eff++; } ct_idx++; } printf("\nFor a total of: %d classifiers\n", ct_eff); } else { printf("ERROR: missing EOF from server (9)\n"); exit(1); } } else { usage_client(argv[0]); exit(1); } close(sd); return 0; } char *pmc_extract_token(char **string, int delim) { char *token, *delim_ptr; if ((delim_ptr = strchr(*string, delim))) { *delim_ptr = '\0'; token = *string; *string = delim_ptr+1; } else { token = *string; *string += strlen(*string); } return token; } int Recv(int sd, unsigned char **buf) { int num, unpacked = 0, round = 0, eof_received = 0; unsigned char rxbuf[LARGEBUFLEN], emptybuf[LARGEBUFLEN], *elem = NULL; *buf = (unsigned char *) malloc(LARGEBUFLEN); if (!(*buf)) { printf("ERROR: malloc() out of memory (Recv)\n"); exit(1); } memset(*buf, 0, LARGEBUFLEN); memset(rxbuf, 0, LARGEBUFLEN); memset(emptybuf, 0, LARGEBUFLEN); do { num = recv(sd, rxbuf, LARGEBUFLEN, 0); if (num > 0) { if (!memcmp(rxbuf, emptybuf, LARGEBUFLEN)) { eof_received = TRUE; } else { /* check: enough space in allocated buffer */ if (unpacked+num >= round*LARGEBUFLEN) { round++; *buf = realloc((unsigned char *) *buf, round*LARGEBUFLEN); if (!(*buf)) { printf("ERROR: realloc() out of memory (Recv)\n"); exit(1); } /* ensuring realloc() didn't move somewhere else our memory area */ elem = *buf; elem += unpacked; } memcpy(elem, rxbuf, num); unpacked += num; elem += num; } } } while (num > 0); if (eof_received) return unpacked; else return 0; } int check_data_sizes(struct query_header *qh, struct pkt_data *acc_elem) { if (!acc_elem) return FALSE; if (qh->cnt_sz != sizeof(acc_elem->pkt_len)) { printf("ERROR: Counter sizes mismatch: daemon: %d client: %d\n", qh->cnt_sz*8, (int)sizeof(acc_elem->pkt_len)*8); printf("ERROR: It's very likely that a 64bit package has been mixed with a 32bit one.\n\n"); printf("ERROR: Please fix the issue before trying again.\n"); return (qh->cnt_sz-sizeof(acc_elem->pkt_len)); } if (qh->ip_sz != sizeof(acc_elem->primitives.src_ip)) { printf("ERROR: IP address sizes mismatch. daemon: %d client: %d\n", qh->ip_sz, (int)sizeof(acc_elem->primitives.src_ip)); printf("ERROR: It's very likely that an IPv6-enabled package has been mixed with a IPv4-only one.\n\n"); printf("ERROR: Please fix the issue before trying again.\n"); return (qh->ip_sz-sizeof(acc_elem->primitives.src_ip)); } return FALSE; } /* sort the (sub)array v from start to end */ void client_counters_merge_sort(void *table, int start, int end, int size, int order) { int middle; /* no elements to sort */ if ((start == end) || (start == end-1)) return; /* find the middle of the array, splitting it into two subarrays */ middle = (start+end)/2; /* sort the subarray from start..middle */ client_counters_merge_sort(table, start, middle, size, order); /* sort the subarray from middle..end */ client_counters_merge_sort(table, middle, end, size, order); /* merge the two sorted halves */ client_counters_merge(table, start, middle, end, size, order); } /* merge the subarray v[start..middle] with v[middle..end], placing the result back into v. */ void client_counters_merge(void *table, int start, int middle, int end, int size, int order) { void *v1, *v2; int v1_n, v2_n, v1_index, v2_index, i, s = size; struct pkt_data data1, data2; v1_n = middle-start; v2_n = end-middle; v1 = malloc(v1_n*s); v2 = malloc(v2_n*s); if ((!v1) || (!v2)) { printf("ERROR: Memory sold out while sorting statistics.\n"); exit(1); } for (i=0; itype); switch (type) { case RD_TYPE_AS: rda = (struct rd_as *) rd; sprintf(str, "%u:%u:%u", type, rda->as, rda->val); break; case RD_TYPE_IP: rdi = (struct rd_ip *) rd; a.family = AF_INET; a.address.ipv4.s_addr = rdi->ip.s_addr; addr_to_str(ip_address, &a); sprintf(str, "%u:%s:%u", type, ip_address, rdi->val); break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) rd; sprintf(str, "%u:%u:%u", type, rda4->as, rda4->val); break; case RD_TYPE_VRFID: rda = (struct rd_as *) rd; sprintf(str, "vrfid:%u", rda->val); break; default: sprintf(str, "unknown"); break; } return TRUE; } int pmc_bgp_str2rd(rd_t *output, char *value) { struct host_addr a; char *endptr, *token; u_int32_t tmp32; struct rd_ip *rdi; struct rd_as *rda; struct rd_as4 *rda4; int idx = 0; rd_t rd; memset(&a, 0, sizeof(a)); memset(&rd, 0, sizeof(rd)); /* type:RD_subfield1:RD_subfield2 */ while ( (token = pmc_extract_token(&value, ':')) && idx < 3) { if (idx == 0) { tmp32 = strtoul(token, &endptr, 10); rd.type = tmp32; switch (rd.type) { case RD_TYPE_AS: rda = (struct rd_as *) &rd; break; case RD_TYPE_IP: rdi = (struct rd_ip *) &rd; break; case RD_TYPE_AS4: rda4 = (struct rd_as4 *) &rd; break; default: printf("ERROR: Invalid RD type specified\n"); return FALSE; } } if (idx == 1) { switch (rd.type) { case RD_TYPE_AS: tmp32 = strtoul(token, &endptr, 10); rda->as = tmp32; break; case RD_TYPE_IP: memset(&a, 0, sizeof(a)); str_to_addr(token, &a); if (a.family == AF_INET) rdi->ip.s_addr = a.address.ipv4.s_addr; break; case RD_TYPE_AS4: tmp32 = strtoul(token, &endptr, 10); rda4->as = tmp32; break; } } if (idx == 2) { switch (rd.type) { case RD_TYPE_AS: tmp32 = strtoul(token, &endptr, 10); rda->val = tmp32; break; case RD_TYPE_IP: tmp32 = strtoul(token, &endptr, 10); rdi->val = tmp32; break; case RD_TYPE_AS4: tmp32 = strtoul(token, &endptr, 10); rda4->val = tmp32; break; } } idx++; } memcpy(output, &rd, sizeof(rd)); return TRUE; } #ifdef WITH_JANSSON char *pmc_compose_json(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_legacy_bgp_primitives *plbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, u_char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int8_t tcp_flags, u_int8_t tunnel_tcp_flags, struct timeval *basetime, int tstamp_since_epoch, int tstamp_utc) { char src_mac[18], dst_mac[18], src_host[INET6_ADDRSTRLEN], dst_host[INET6_ADDRSTRLEN], ip_address[INET6_ADDRSTRLEN]; char rd_str[SRVBUFLEN], misc_str[SRVBUFLEN], *as_path, *bgp_comm, empty_string[] = "", *tmpbuf; char tstamp_str[SRVBUFLEN], *label_ptr; json_t *obj = json_object(); if (wtc & COUNT_TAG) json_object_set_new_nocheck(obj, "tag", json_integer((json_int_t)pbase->tag)); if (wtc & COUNT_TAG2) json_object_set_new_nocheck(obj, "tag2", json_integer((json_int_t)pbase->tag2)); if (wtc_2 & COUNT_LABEL) { pmc_vlen_prims_get(pvlen, COUNT_INT_LABEL, &label_ptr); if (!label_ptr) label_ptr = empty_string; json_object_set_new_nocheck(obj, "label", json_string(label_ptr)); } if (wtc & COUNT_CLASS) json_object_set_new_nocheck(obj, "class", json_string((pbase->class && class_table[(pbase->class)-1].id) ? class_table[(pbase->class)-1].protocol : "unknown")); #if defined (WITH_NDPI) char ndpi_class[SUPERSHORTBUFLEN]; if (wtc_2 & COUNT_NDPI_CLASS) { snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", pmc_ndpi_get_proto_name(pbase->ndpi_class.master_protocol), pmc_ndpi_get_proto_name(pbase->ndpi_class.app_protocol)); json_object_set_new_nocheck(obj, "class", json_string(ndpi_class)); } #endif #if defined (HAVE_L2) if (wtc & COUNT_SRC_MAC) { etheraddr_string(pbase->eth_shost, src_mac); json_object_set_new_nocheck(obj, "mac_src", json_string(src_mac)); } if (wtc & COUNT_DST_MAC) { etheraddr_string(pbase->eth_dhost, dst_mac); json_object_set_new_nocheck(obj, "mac_dst", json_string(dst_mac)); } if (wtc & COUNT_VLAN) json_object_set_new_nocheck(obj, "vlan", json_integer((json_int_t)pbase->vlan_id)); if (wtc_2 & COUNT_OUT_VLAN) json_object_set_new_nocheck(obj, "vlan_out", json_integer((json_int_t)pbase->out_vlan_id)); if (wtc & COUNT_COS) json_object_set_new_nocheck(obj, "cos", json_integer((json_int_t)pbase->cos)); if (wtc & COUNT_ETHERTYPE) { sprintf(misc_str, "%x", pbase->etype); json_object_set_new_nocheck(obj, "etype", json_string(misc_str)); } #endif if (wtc & COUNT_SRC_AS) json_object_set_new_nocheck(obj, "as_src", json_integer((json_int_t)pbase->src_as)); if (wtc & COUNT_DST_AS) json_object_set_new_nocheck(obj, "as_dst", json_integer((json_int_t)pbase->dst_as)); if (wtc & COUNT_STD_COMM) { bgp_comm = plbgp->std_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->std_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->std_comms)) json_object_set_new_nocheck(obj, "comms", json_string(plbgp->std_comms)); else json_object_set_new_nocheck(obj, "comms", json_string(empty_string)); } if (wtc & COUNT_EXT_COMM) { bgp_comm = plbgp->ext_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->ext_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->ext_comms)) json_object_set_new_nocheck(obj, "ecomms", json_string(plbgp->ext_comms)); else json_object_set_new_nocheck(obj, "ecomms", json_string(empty_string)); } if (wtc_2 & COUNT_LRG_COMM) { bgp_comm = plbgp->lrg_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->lrg_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->lrg_comms)) json_object_set_new_nocheck(obj, "lcomms", json_string(plbgp->lrg_comms)); else json_object_set_new_nocheck(obj, "lcomms", json_string(empty_string)); } if (wtc & COUNT_AS_PATH) { as_path = plbgp->as_path; while (as_path) { as_path = strchr(plbgp->as_path, ' '); if (as_path) *as_path = '_'; } if (strlen(plbgp->as_path)) json_object_set_new_nocheck(obj, "as_path", json_string(plbgp->as_path)); else json_object_set_new_nocheck(obj, "as_path", json_string(empty_string)); } if (wtc & COUNT_LOCAL_PREF) json_object_set_new_nocheck(obj, "local_pref", json_integer((json_int_t)pbgp->local_pref)); if (wtc & COUNT_MED) json_object_set_new_nocheck(obj, "med", json_integer((json_int_t)pbgp->med)); if (wtc_2 & COUNT_DST_ROA) json_object_set_new_nocheck(obj, "roa_dst", json_string(pmc_rpki_roa_print(pbgp->dst_roa))); if (wtc & COUNT_PEER_SRC_AS) json_object_set_new_nocheck(obj, "peer_as_src", json_integer((json_int_t)pbgp->peer_src_as)); if (wtc & COUNT_PEER_DST_AS) json_object_set_new_nocheck(obj, "peer_as_dst", json_integer((json_int_t)pbgp->peer_dst_as)); if (wtc & COUNT_PEER_SRC_IP) { addr_to_str(ip_address, &pbgp->peer_src_ip); json_object_set_new_nocheck(obj, "peer_ip_src", json_string(ip_address)); } if (wtc & COUNT_PEER_DST_IP) { addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(flow_type)); json_object_set_new_nocheck(obj, "peer_ip_dst", json_string(ip_address)); } if (wtc & COUNT_SRC_STD_COMM) { bgp_comm = plbgp->src_std_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_std_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_std_comms)) json_object_set_new_nocheck(obj, "src_comms", json_string(plbgp->src_std_comms)); else json_object_set_new_nocheck(obj, "src_comms", json_string(empty_string)); } if (wtc & COUNT_SRC_EXT_COMM) { bgp_comm = plbgp->src_ext_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_ext_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_ext_comms)) json_object_set_new_nocheck(obj, "src_ecomms", json_string(plbgp->src_ext_comms)); else json_object_set_new_nocheck(obj, "src_ecomms", json_string(empty_string)); } if (wtc_2 & COUNT_SRC_LRG_COMM) { bgp_comm = plbgp->src_lrg_comms; while (bgp_comm) { bgp_comm = strchr(plbgp->src_lrg_comms, ' '); if (bgp_comm) *bgp_comm = '_'; } if (strlen(plbgp->src_lrg_comms)) json_object_set_new_nocheck(obj, "src_lcomms", json_string(plbgp->src_lrg_comms)); else json_object_set_new_nocheck(obj, "src_lcomms", json_string(empty_string)); } if (wtc & COUNT_SRC_AS_PATH) { as_path = plbgp->src_as_path; while (as_path) { as_path = strchr(plbgp->src_as_path, ' '); if (as_path) *as_path = '_'; } if (strlen(plbgp->src_as_path)) json_object_set_new_nocheck(obj, "src_as_path", json_string(plbgp->src_as_path)); else json_object_set_new_nocheck(obj, "src_as_path", json_string(empty_string)); } if (wtc & COUNT_SRC_LOCAL_PREF) json_object_set_new_nocheck(obj, "src_local_pref", json_integer((json_int_t)pbgp->src_local_pref)); if (wtc & COUNT_SRC_MED) json_object_set_new_nocheck(obj, "src_med", json_integer((json_int_t)pbgp->src_med)); if (wtc_2 & COUNT_SRC_ROA) json_object_set_new_nocheck(obj, "roa_src", json_string(pmc_rpki_roa_print(pbgp->src_roa))); if (wtc & COUNT_IN_IFACE) json_object_set_new_nocheck(obj, "iface_in", json_integer((json_int_t)pbase->ifindex_in)); if (wtc & COUNT_OUT_IFACE) json_object_set_new_nocheck(obj, "iface_out", json_integer((json_int_t)pbase->ifindex_out)); if (wtc & COUNT_MPLS_VPN_RD) { pmc_bgp_rd2str(rd_str, &pbgp->mpls_vpn_rd); json_object_set_new_nocheck(obj, "mpls_vpn_rd", json_string(rd_str)); } if (wtc_2 & COUNT_MPLS_PW_ID) json_object_set_new_nocheck(obj, "mpls_pw_id", json_integer((json_int_t)pbgp->mpls_pw_id)); if (wtc & COUNT_SRC_HOST) { addr_to_str(src_host, &pbase->src_ip); json_object_set_new_nocheck(obj, "ip_src", json_string(src_host)); } if (wtc & COUNT_SRC_NET) { addr_to_str(src_host, &pbase->src_net); json_object_set_new_nocheck(obj, "net_src", json_string(src_host)); } if (wtc & COUNT_DST_HOST) { addr_to_str(dst_host, &pbase->dst_ip); json_object_set_new_nocheck(obj, "ip_dst", json_string(dst_host)); } if (wtc & COUNT_DST_NET) { addr_to_str(dst_host, &pbase->dst_net); json_object_set_new_nocheck(obj, "net_dst", json_string(dst_host)); } if (wtc & COUNT_SRC_NMASK) json_object_set_new_nocheck(obj, "mask_src", json_integer((json_int_t)pbase->src_nmask)); if (wtc & COUNT_DST_NMASK) json_object_set_new_nocheck(obj, "mask_dst", json_integer((json_int_t)pbase->dst_nmask)); if (wtc & COUNT_SRC_PORT) json_object_set_new_nocheck(obj, "port_src", json_integer((json_int_t)pbase->src_port)); if (wtc & COUNT_DST_PORT) json_object_set_new_nocheck(obj, "port_dst", json_integer((json_int_t)pbase->dst_port)); #if defined (WITH_GEOIP) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { if (pbase->src_ip_country.id > 0) json_object_set_new_nocheck(obj, "country_ip_src", json_string(GeoIP_code_by_id(pbase->src_ip_country.id))); else json_object_set_new_nocheck(obj, "country_ip_src", json_string(empty_string)); } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { if (pbase->dst_ip_country.id > 0) json_object_set_new_nocheck(obj, "country_ip_dst", json_string(GeoIP_code_by_id(pbase->dst_ip_country.id))); else json_object_set_new_nocheck(obj, "country_ip_dst", json_string(empty_string)); } #endif #if defined (WITH_GEOIPV2) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { if (strlen(pbase->src_ip_country.str)) json_object_set_new_nocheck(obj, "country_ip_src", json_string(pbase->src_ip_country.str)); else json_object_set_new_nocheck(obj, "country_ip_src", json_string(empty_string)); } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { if (strlen(pbase->dst_ip_country.str)) json_object_set_new_nocheck(obj, "country_ip_dst", json_string(pbase->dst_ip_country.str)); else json_object_set_new_nocheck(obj, "country_ip_dst", json_string(empty_string)); } if (wtc_2 & COUNT_SRC_HOST_POCODE) { if (strlen(pbase->src_ip_pocode.str)) json_object_set_new_nocheck(obj, "pocode_ip_src", json_string(pbase->src_ip_pocode.str)); else json_object_set_new_nocheck(obj, "pocode_ip_src", json_string(empty_string)); } if (wtc_2 & COUNT_DST_HOST_POCODE) { if (strlen(pbase->dst_ip_pocode.str)) json_object_set_new_nocheck(obj, "pocode_ip_dst", json_string(pbase->dst_ip_pocode.str)); else json_object_set_new_nocheck(obj, "pocode_ip_dst", json_string(empty_string)); } if (wtc_2 & COUNT_SRC_HOST_COORDS) { json_object_set_new_nocheck(obj, "lat_ip_src", json_real(pbase->src_ip_lat)); json_object_set_new_nocheck(obj, "lat_ip_src", json_real(pbase->src_ip_lon)); } if (wtc_2 & COUNT_DST_HOST_COORDS) { json_object_set_new_nocheck(obj, "lat_ip_dst", json_real(pbase->dst_ip_lat)); json_object_set_new_nocheck(obj, "lat_ip_dst", json_real(pbase->dst_ip_lon)); } #endif if (wtc & COUNT_TCPFLAGS) { sprintf(misc_str, "%u", tcp_flags); json_object_set_new_nocheck(obj, "tcp_flags", json_string(misc_str)); } if (wtc & COUNT_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; if (!want_ipproto_num) json_object_set_new_nocheck(obj, "ip_proto", json_string(_protocols[pbase->proto].name)); else { snprintf(proto, PROTO_NUM_STRLEN, "%u", pbase->proto); json_object_set_new_nocheck(obj, "ip_proto", json_string(proto)); } } if (wtc & COUNT_IP_TOS) json_object_set_new_nocheck(obj, "tos", json_integer((json_int_t)pbase->tos)); if (wtc_2 & COUNT_SAMPLING_RATE) json_object_set_new_nocheck(obj, "sampling_rate", json_integer((json_int_t)pbase->sampling_rate)); if (wtc_2 & COUNT_SAMPLING_DIRECTION) json_object_set_new_nocheck(obj, "sampling_direction", json_string(sampling_direction_print(pbase->sampling_direction))); if (wtc_2 & COUNT_POST_NAT_SRC_HOST) { addr_to_str(src_host, &pnat->post_nat_src_ip); json_object_set_new_nocheck(obj, "post_nat_ip_src", json_string(src_host)); } if (wtc_2 & COUNT_POST_NAT_DST_HOST) { addr_to_str(dst_host, &pnat->post_nat_dst_ip); json_object_set_new_nocheck(obj, "post_nat_ip_dst", json_string(dst_host)); } if (wtc_2 & COUNT_POST_NAT_SRC_PORT) json_object_set_new_nocheck(obj, "post_nat_port_src", json_integer((json_int_t)pnat->post_nat_src_port)); if (wtc_2 & COUNT_POST_NAT_DST_PORT) json_object_set_new_nocheck(obj, "post_nat_port_dst", json_integer((json_int_t)pnat->post_nat_dst_port)); if (wtc_2 & COUNT_NAT_EVENT) json_object_set_new_nocheck(obj, "nat_event", json_integer((json_int_t)pnat->nat_event)); if (wtc_2 & COUNT_FW_EVENT) json_object_set_new_nocheck(obj, "fw_event", json_integer((json_int_t)pnat->fw_event)); if (wtc_2 & COUNT_FWD_STATUS) json_object_set_new_nocheck(obj, "fwd_status", json_integer((json_int_t)pnat->fwd_status)); if (wtc_2 & COUNT_MPLS_LABEL_TOP) json_object_set_new_nocheck(obj, "mpls_label_top", json_integer((json_int_t)pmpls->mpls_label_top)); if (wtc_2 & COUNT_MPLS_LABEL_BOTTOM) json_object_set_new_nocheck(obj, "mpls_label_bottom", json_integer((json_int_t)pmpls->mpls_label_bottom)); if (wtc_2 & COUNT_TUNNEL_SRC_MAC) { etheraddr_string(ptun->tunnel_eth_shost, src_mac); json_object_set_new_nocheck(obj, "tunnel_mac_src", json_string(src_mac)); } if (wtc_2 & COUNT_TUNNEL_DST_MAC) { etheraddr_string(ptun->tunnel_eth_dhost, dst_mac); json_object_set_new_nocheck(obj, "tunnel_mac_dst", json_string(dst_mac)); } if (wtc_2 & COUNT_TUNNEL_SRC_HOST) { addr_to_str(src_host, &ptun->tunnel_src_ip); json_object_set_new_nocheck(obj, "tunnel_ip_src", json_string(src_host)); } if (wtc_2 & COUNT_TUNNEL_DST_HOST) { addr_to_str(dst_host, &ptun->tunnel_dst_ip); json_object_set_new_nocheck(obj, "tunnel_ip_dst", json_string(dst_host)); } if (wtc_2 & COUNT_TUNNEL_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; if (!want_ipproto_num) json_object_set_new_nocheck(obj, "tunnel_ip_proto", json_string(_protocols[ptun->tunnel_proto].name)); else { snprintf(proto, PROTO_NUM_STRLEN, "%u", ptun->tunnel_proto); json_object_set_new_nocheck(obj, "tunnel_ip_proto", json_string(proto)); } } if (wtc_2 & COUNT_TUNNEL_IP_TOS) json_object_set_new_nocheck(obj, "tunnel_tos", json_integer((json_int_t)ptun->tunnel_tos)); if (wtc_2 & COUNT_TUNNEL_SRC_PORT) json_object_set_new_nocheck(obj, "tunnel_port_src", json_integer((json_int_t)ptun->tunnel_src_port)); if (wtc_2 & COUNT_TUNNEL_DST_PORT) json_object_set_new_nocheck(obj, "tunnel_port_dst", json_integer((json_int_t)ptun->tunnel_dst_port)); if (wtc_2 & COUNT_TUNNEL_TCPFLAGS) { sprintf(misc_str, "%u", tunnel_tcp_flags); json_object_set_new_nocheck(obj, "tunnel_tcp_flags", json_string(misc_str)); } if (wtc_2 & COUNT_VXLAN) json_object_set_new_nocheck(obj, "vxlan", json_integer((json_int_t)ptun->tunnel_id)); if (wtc_2 & COUNT_TIMESTAMP_START) { pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_start, TRUE, tstamp_since_epoch, tstamp_utc); json_object_set_new_nocheck(obj, "timestamp_start", json_string(tstamp_str)); } if (wtc_2 & COUNT_TIMESTAMP_END) { pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_end, TRUE, tstamp_since_epoch, tstamp_utc); json_object_set_new_nocheck(obj, "timestamp_end", json_string(tstamp_str)); } if (wtc_2 & COUNT_TIMESTAMP_ARRIVAL) { pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_arrival, TRUE, tstamp_since_epoch, tstamp_utc); json_object_set_new_nocheck(obj, "timestamp_arrival", json_string(tstamp_str)); } if (wtc_2 & COUNT_EXPORT_PROTO_TIME) { pmc_compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_export, TRUE, tstamp_since_epoch, tstamp_utc); json_object_set_new_nocheck(obj, "timestamp_export", json_string(tstamp_str)); } if (wtc_2 & COUNT_EXPORT_PROTO_SEQNO) json_object_set_new_nocheck(obj, "export_proto_seqno", json_integer((json_int_t)pbase->export_proto_seqno)); if (wtc_2 & COUNT_EXPORT_PROTO_VERSION) json_object_set_new_nocheck(obj, "export_proto_version", json_integer((json_int_t)pbase->export_proto_version)); if (wtc_2 & COUNT_EXPORT_PROTO_SYSID) json_object_set_new_nocheck(obj, "export_proto_sysid", json_integer((json_int_t)pbase->export_proto_sysid)); /* all custom primitives printed here */ { int cp_idx; for (cp_idx = 0; cp_idx < pmc_custom_primitives_registry.num; cp_idx++) { if (pmc_custom_primitives_registry.primitive[cp_idx].len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; pmc_custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &pmc_custom_primitives_registry.primitive[cp_idx], FALSE); json_object_set_new_nocheck(obj, pmc_custom_primitives_registry.primitive[cp_idx].name, json_string(cp_str)); } else { char *label_ptr = NULL; pmc_vlen_prims_get(pvlen, pmc_custom_primitives_registry.primitive[cp_idx].type, &label_ptr); if (!label_ptr) label_ptr = empty_string; json_object_set_new_nocheck(obj, pmc_custom_primitives_registry.primitive[cp_idx].name, json_string(label_ptr)); } } } if (flow_type != NF9_FTYPE_EVENT && flow_type != NF9_FTYPE_OPTION) { json_object_set_new_nocheck(obj, "packets", json_integer((json_int_t)packet_counter)); if (wtc & COUNT_FLOWS) json_object_set_new_nocheck(obj, "flows", json_integer((json_int_t)flow_counter)); json_object_set_new_nocheck(obj, "bytes", json_integer((json_int_t)bytes_counter)); } tmpbuf = json_dumps(obj, JSON_PRESERVE_ORDER); json_decref(obj); return tmpbuf; } #else char *pmc_compose_json(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_legacy_bgp_primitives *plbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, u_char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int8_t tcp_flags, u_int8_t tunnel_tcp_flags, struct timeval *basetime, int tstamp_since_epoch, int tstamp_utc) { return NULL; } #endif void pmc_append_rfc3339_timezone(char *s, int slen, const struct tm *nowtm) { int len = strlen(s), max = (slen - len); char buf[8], zulu[] = "Z"; strftime(buf, 8, "%z", nowtm); if (!strcmp(buf, "+0000")) { if (max) strcat(s, zulu); } else { if (max >= 7) { s[len] = buf[0]; len++; s[len] = buf[1]; len++; s[len] = buf[2]; len++; s[len] = ':'; len++; s[len] = buf[3]; len++; s[len] = buf[4]; len++; s[len] = '\0'; } } } void pmc_compose_timestamp(char *buf, int buflen, struct timeval *tv, int usec, int tstamp_since_epoch, int tstamp_utc) { int slen; time_t time1; struct tm *time2; if (tstamp_since_epoch) { if (usec) snprintf(buf, buflen, "%ld.%.6ld", tv->tv_sec, (long)tv->tv_usec); else snprintf(buf, buflen, "%ld", tv->tv_sec); } else { time1 = tv->tv_sec; if (!tstamp_utc) time2 = localtime(&time1); else time2 = gmtime(&time1); slen = strftime(buf, buflen, "%Y-%m-%dT%H:%M:%S", time2); if (usec) snprintf((buf + slen), (buflen - slen), ".%.6ld", (long)tv->tv_usec); pmc_append_rfc3339_timezone(buf, buflen, time2); } } void pmc_custom_primitive_header_print(char *out, int outlen, struct imt_custom_primitive_entry *cp_entry, int formatted) { char format[SRVBUFLEN]; if (out && cp_entry) { memset(out, 0, outlen); if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_UINT || cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) { if (formatted) { snprintf(format, SRVBUFLEN, "%%-%d", cps_flen[cp_entry->len] > strlen(cp_entry->name) ? cps_flen[cp_entry->len] : (int)strlen(cp_entry->name)); strncat(format, "s", SRVBUFLEN - 1); } else snprintf(format, SRVBUFLEN, "%s", "%s"); } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_STRING || cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { if (formatted) { snprintf(format, SRVBUFLEN, "%%-%d", cp_entry->len > strlen(cp_entry->name) ? cp_entry->len : (int)strlen(cp_entry->name)); strncat(format, "s", SRVBUFLEN - 1); } else snprintf(format, SRVBUFLEN, "%s", "%s"); } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_IP) { int len = 0; len = INET6_ADDRSTRLEN; if (formatted) { snprintf(format, SRVBUFLEN, "%%-%d", len > strlen(cp_entry->name) ? len : (int)strlen(cp_entry->name)); strncat(format, "s", SRVBUFLEN - 1); } else snprintf(format, SRVBUFLEN, "%s", "%s"); } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) { int len = ETHER_ADDRSTRLEN; if (formatted) { snprintf(format, SRVBUFLEN, "%%-%d", len > strlen(cp_entry->name) ? len : (int)strlen(cp_entry->name)); strncat(format, "s", SRVBUFLEN - 1); } else snprintf(format, SRVBUFLEN, "%s", "%s"); } snprintf(out, outlen, format, cp_entry->name); } } void pmc_custom_primitive_value_print(char *out, int outlen, u_char *in, struct imt_custom_primitive_entry *cp_entry, int formatted) { char format[SRVBUFLEN]; if (in && out && cp_entry) { memset(out, 0, outlen); if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_UINT || cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) { if (formatted) snprintf(format, SRVBUFLEN, "%%-%d%s", cps_flen[cp_entry->len] > strlen(cp_entry->name) ? cps_flen[cp_entry->len] : (int)strlen(cp_entry->name), cps_type[cp_entry->semantics]); else snprintf(format, SRVBUFLEN, "%%%s", cps_type[cp_entry->semantics]); if (cp_entry->len == 1) { u_int8_t t8; memcpy(&t8, (in+cp_entry->off), 1); snprintf(out, outlen, format, t8); } else if (cp_entry->len == 2) { u_int16_t t16, st16; memcpy(&t16, (in+cp_entry->off), 2); st16 = ntohs(t16); snprintf(out, outlen, format, st16); } else if (cp_entry->len == 4) { u_int32_t t32, st32; memcpy(&t32, (in+cp_entry->off), 4); st32 = ntohl(t32); snprintf(out, outlen, format, st32); } else if (cp_entry->len == 8) { u_int64_t t64, st64; memcpy(&t64, (in+cp_entry->off), 8); st64 = pm_ntohll(t64); snprintf(out, outlen, format, st64); } } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_STRING || cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { if (formatted) snprintf(format, SRVBUFLEN, "%%-%d%s", cp_entry->len > strlen(cp_entry->name) ? cp_entry->len : (int)strlen(cp_entry->name), cps_type[cp_entry->semantics]); else snprintf(format, SRVBUFLEN, "%%%s", cps_type[cp_entry->semantics]); snprintf(out, outlen, format, (in+cp_entry->off)); } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_IP) { struct host_addr ip_addr; char ip_str[INET6_ADDRSTRLEN]; int len = 0; memset(&ip_addr, 0, sizeof(ip_addr)); memset(ip_str, 0, sizeof(ip_str)); len = INET6_ADDRSTRLEN; if (cp_entry->len == 4) { ip_addr.family = AF_INET; memcpy(&ip_addr.address.ipv4, in+cp_entry->off, 4); } else if (cp_entry->len == 16) { ip_addr.family = AF_INET6; memcpy(&ip_addr.address.ipv6, in+cp_entry->off, 16); } addr_to_str(ip_str, &ip_addr); if (formatted) snprintf(format, SRVBUFLEN, "%%-%d%s", len > strlen(cp_entry->name) ? len : (int)strlen(cp_entry->name), cps_type[cp_entry->semantics]); else snprintf(format, SRVBUFLEN, "%%%s", cps_type[cp_entry->semantics]); snprintf(out, outlen, format, ip_str); } else if (cp_entry->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) { char eth_str[ETHER_ADDRSTRLEN]; int len = ETHER_ADDRSTRLEN; memset(eth_str, 0, sizeof(eth_str)); etheraddr_string(in+cp_entry->off, eth_str); if (formatted) snprintf(format, SRVBUFLEN, "%%-%d%s", len > strlen(cp_entry->name) ? len : (int)strlen(cp_entry->name), cps_type[cp_entry->semantics]); else snprintf(format, SRVBUFLEN, "%%%s", cps_type[cp_entry->semantics]); snprintf(out, outlen, format, eth_str); } } } void pmc_vlen_prims_get(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc, char **res) { pm_label_t *label_ptr; char *ptr = (char *) hdr; int x, rlen; if (res) *res = NULL; if (!hdr || !wtc || !res) return; ptr += PvhdrSz; label_ptr = (pm_label_t *) ptr; for (x = 0, rlen = 0; x < hdr->num && rlen < hdr->tot_len; x++) { if (label_ptr->type == wtc) { if (label_ptr->len) { ptr += PmLabelTSz; *res = ptr; } return; } else { ptr += (PmLabelTSz + label_ptr->len); rlen += (PmLabelTSz + label_ptr->len); label_ptr = (pm_label_t *) ptr; } } } void pmc_printf_csv_label(struct pkt_vlen_hdr_primitives *pvlen, pm_cfgreg_t wtc, char *sep, char *empty_string) { char *label_ptr = NULL; pmc_vlen_prims_get(pvlen, wtc, &label_ptr); if (!label_ptr) label_ptr = empty_string; printf("%s%s", sep, label_ptr); } void pmc_lower_string(char *string) { int i = 0; while (string[i] != '\0') { string[i] = tolower(string[i]); i++; } } char *pmc_ndpi_get_proto_name(u_int16_t proto_id) { static char unknown[] = "unknown"; if (!proto_id || proto_id > ct_idx || !class_table[proto_id].id) { return unknown; } else { return class_table[proto_id - 1].protocol; } } const char *pmc_rpki_roa_print(u_int8_t roa) { if (roa <= ROA_STATUS_MAX) return rpki_roa[roa]; else return rpki_roa[ROA_STATUS_UNKNOWN]; } u_int8_t pmc_rpki_str2roa(char *roa_str) { if (!strcmp(roa_str, "u")) return ROA_STATUS_UNKNOWN; else if (!strcmp(roa_str, "i")) return ROA_STATUS_INVALID; else if (!strcmp(roa_str, "v")) return ROA_STATUS_VALID; return ROA_STATUS_UNKNOWN; } const char *pmc_sampling_direction_print(u_int8_t sd_id) { if (sd_id <= SAMPLING_DIRECTION_MAX) return sampling_direction[sd_id]; else return sampling_direction[SAMPLING_DIRECTION_UNKNOWN]; } u_int8_t pmc_sampling_direction_str2id(char *sd_str) { if (!strcmp(sd_str, "u")) return SAMPLING_DIRECTION_UNKNOWN; else if (!strcmp(sd_str, "i")) return SAMPLING_DIRECTION_INGRESS; else if (!strcmp(sd_str, "e")) return SAMPLING_DIRECTION_EGRESS; return SAMPLING_DIRECTION_UNKNOWN; } pmacct-1.7.8/src/plugin_cmn_avro.h0000644000175000017500000001041514354105275016135 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLUGIN_CMN_AVRO_H #define PLUGIN_CMN_AVRO_H /* includes */ #ifdef WITH_SERDES #include #endif /* defines */ #ifdef WITH_AVRO /* libavro-c bails out with generic error messages on typical cases where schema and actual data encoding are not matching. This small wrapper aims to identify what line in the code does specifically cause the issue */ #define pm_avro_check(call) \ do { \ if ((call) != 0) { \ Log(LOG_ERR, "ERROR: %s\n", avro_strerror()); \ assert(1 == 0); \ } \ } while (0) #define AVRO_ACCT_DATA_SID 0 #define AVRO_ACCT_INIT_SID 1 #define AVRO_ACCT_CLOSE_SID 2 /* prototypes */ extern void compose_label_avro_schema_opt(avro_schema_t); extern void compose_label_avro_schema_nonopt(avro_schema_t); extern void compose_tcpflags_avro_schema(avro_schema_t); extern void compose_tunnel_tcpflags_avro_schema(avro_schema_t); extern void compose_fwd_status_avro_schema(avro_schema_t); extern void compose_mpls_label_stack_schema(avro_schema_t); extern int compose_label_avro_data_opt(char *, avro_value_t); extern int compose_label_avro_data_nonopt(char *, avro_value_t); extern int compose_tcpflags_avro_data(size_t, avro_value_t); extern int compose_tunnel_tcpflags_avro_data(size_t, avro_value_t); extern int compose_mpls_label_stack_data(u_int32_t *, int, avro_value_t); extern int compose_fwd_status_avro_data(size_t, avro_value_t); extern void pm_avro_exit_gracefully(int); extern avro_schema_t p_avro_schema_build_acct_data(u_int64_t wtc, u_int64_t wtc_2); extern avro_schema_t p_avro_schema_build_acct_init(); extern avro_schema_t p_avro_schema_build_acct_close(); extern void p_avro_schema_add_writer_id(avro_schema_t); extern void add_writer_name_and_pid_avro(avro_value_t, char *, pid_t); extern void add_writer_name_and_pid_avro_v2(avro_value_t, struct dynname_tokens *); extern avro_value_t compose_avro_acct_data(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, u_char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int8_t tcp_flags, u_int8_t tunnel_tcp_flags, struct timeval *basetime, struct pkt_stitching *stitch, avro_value_iface_t *iface); extern avro_value_t compose_avro_acct_init(char *, pid_t, avro_value_iface_t *); extern avro_value_t compose_avro_acct_close(char *, pid_t, int, int, int, avro_value_iface_t *); extern void write_avro_schema_to_file(char *, avro_schema_t); extern void write_avro_schema_to_file_with_suffix(char *, char *, char *, avro_schema_t); extern char *write_avro_schema_to_memory(avro_schema_t); extern char *compose_avro_purge_schema(avro_schema_t, char *); extern char *compose_avro_schema_name(char *, char *); extern void write_avro_json_record_to_file(FILE *, avro_value_t); extern char *write_avro_json_record_to_buf(avro_value_t); #ifdef WITH_SERDES extern void p_avro_serdes_logger(serdes_t *, int, const char *, const char *, void *); extern serdes_schema_t *compose_avro_schema_registry_name(char *, int, avro_schema_t, char *, char *, char *); extern serdes_schema_t *compose_avro_schema_registry_name_2(char *, int, avro_schema_t, char *, char *, char *); #endif /* global variables */ extern avro_schema_t p_avro_acct_schema, p_avro_acct_init_schema, p_avro_acct_close_schema; #endif #endif //PLUGIN_CMN_AVRO_H pmacct-1.7.8/src/mysql_plugin.h0000644000175000017500000000400514354105275015474 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #if defined HAVE_MYSQL_H #include #else #include #endif #include "plugin_common.h" /* prototypes */ void mysql_plugin(int, struct configuration *, void *); int MY_cache_dbop(struct DBdesc *, struct db_cache *, struct insert_data *); void MY_cache_purge(struct db_cache *[], int, struct insert_data *); int MY_evaluate_history(int); int MY_compose_static_queries(); void MY_Lock(struct DBdesc *); void MY_Unlock(struct BE_descs *); void MY_DB_Connect(struct DBdesc *, char *); void MY_DB_Close(struct BE_descs *); void MY_create_dyn_table(struct DBdesc *, char *); void MY_get_errmsg(struct DBdesc *); void MY_create_backend(struct DBdesc *); void MY_set_callbacks(struct sqlfunc_cb_registry *); void MY_init_default_values(struct insert_data *); void MY_mysql_get_version(); /* variables */ extern char mysql_user[]; extern char mysql_pwd[]; extern unsigned int mysql_prt; extern char mysql_db[]; extern char mysql_table[]; extern char mysql_table_v2[]; extern char mysql_table_v3[]; extern char mysql_table_v4[]; extern char mysql_table_v5[]; extern char mysql_table_v6[]; extern char mysql_table_v7[]; extern char mysql_table_v8[]; extern char mysql_table_bgp[]; pmacct-1.7.8/src/base64.c0000644000175000017500000000670714354105275014043 0ustar paolopaolo/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include #include #include "base64.h" static const unsigned char base64_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * base64_encode - Base64 encode * @src: Data to be encoded * @len: Length of the data to be encoded * @out_len: Pointer to output length variable, or %NULL if not used * Returns: Allocated buffer of out_len bytes of encoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. Returned buffer is * nul terminated to make it easier to use as a C string. The nul terminator is * not included in out_len. */ unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char *out, *pos; const unsigned char *end, *in; size_t olen; int line_len; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ olen += olen / 72; /* line feeds */ olen++; /* nul termination */ out = malloc(olen); if (out == NULL) return NULL; end = src + len; in = src; pos = out; line_len = 0; while (end - in >= 3) { *pos++ = base64_table[in[0] >> 2]; *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; *pos++ = base64_table[in[2] & 0x3f]; in += 3; line_len += 4; if (line_len >= 72) { *pos++ = '\n'; line_len = 0; } } if (end - in) { *pos++ = base64_table[in[0] >> 2]; if (end - in == 1) { *pos++ = base64_table[(in[0] & 0x03) << 4]; *pos++ = '='; } else { *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[(in[1] & 0x0f) << 2]; } *pos++ = '='; line_len += 4; } if (line_len) *pos++ = '\n'; *pos = '\0'; if (out_len) *out_len = pos - out; return out; } /** * base64_decode - Base64 decode * @src: Data to be decoded * @len: Length of the data to be decoded * @out_len: Pointer to output length variable * Returns: Allocated buffer of out_len bytes of decoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. */ unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char dtable[256], *out, *pos, in[4], block[4], tmp; size_t i, count; memset(dtable, 0x80, 256); for (i = 0; i < sizeof(base64_table); i++) dtable[base64_table[i]] = i; dtable['='] = 0; count = 0; for (i = 0; i < len; i++) { if (dtable[src[i]] != 0x80) count++; } if (count % 4) return NULL; pos = out = malloc(count); if (out == NULL) return NULL; count = 0; for (i = 0; i < len; i++) { tmp = dtable[src[i]]; if (tmp == 0x80) continue; in[count] = src[i]; block[count] = tmp; count++; if (count == 4) { *pos++ = (block[0] << 2) | (block[1] >> 4); *pos++ = (block[1] << 4) | (block[2] >> 2); *pos++ = (block[2] << 6) | block[3]; count = 0; } } if (pos > out) { if (in[2] == '=') pos -= 2; else if (in[3] == '=') pos--; } *out_len = pos - out; return out; } void base64_freebuf(unsigned char *src) { if (src) free(src); } pmacct-1.7.8/src/sql_common.h0000644000175000017500000005653314354105275015135 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SQL_COMMON_H #define SQL_COMMON_H /* includes */ #include #include "net_aggr.h" /* defines */ #define DEFAULT_DB_REFRESH_TIME 60 #define DEFAULT_SQL_TABLE_VERSION 1 #define DEFAULT_SQL_WRITERS_NO 10 #define CACHE_ENTRIES 32771 #define QUERY_BUFFER_SIZE 32768 #define MAGIC 14021979 #define DEF_HDR_FIELD_LEN 128 #define MAX_LOGFILE_SIZE 2048000000 #define MAX_LOGFILE_ROTATIONS 1000 /* cache elements defines */ #define REASONABLE_NUMBER 100 #define STALE_M 3 #define RETIRE_M STALE_M*STALE_M /* backend types */ #define BE_TYPE_PRIMARY 0 #define BE_TYPE_BACKUP 1 #define BE_TYPE_LOGFILE 2 /* lock types */ #define PM_LOCK_EXCLUSIVE 0 #define PM_LOCK_ROW_EXCLUSIVE 1 #define PM_LOCK_NONE 2 /* cache element states */ #define SQL_CACHE_FREE 0 #define SQL_CACHE_COMMITTED 1 #define SQL_CACHE_INUSE 2 #define SQL_CACHE_INVALID 3 #define SQL_CACHE_ERROR 255 #define SQL_TABLE_VERSION_PLAIN 0 #define SQL_TABLE_VERSION_BGP 1000 /* macros */ #define SPACELEFT(x) (sizeof(x)-strlen(x)) #define SPACELEFT_LEN(x,y) (sizeof(x)-y) #define SPACELEFT_PTR(x,y) (y-strlen(x)) #define SQL_INSERT_INSERT 0x00000001 #define SQL_INSERT_UPDATE 0x00000002 #define SQL_INSERT_PRO_RATING 0x00000004 #define SQL_INSERT_SAFE_ACTION 0x00000008 struct multi_values { int buffer_offset; /* multi-values buffer offset where to write next query */ int head_buffer_elem; /* first multi-values buffer element */ int buffer_elem_num; /* number of elements in the multi-values buffer */ int last_queue_elem; /* last queue element signallation */ }; /* structures */ struct insert_data { struct configuration *cfg; unsigned int hash; unsigned int modulo; time_t now; struct timeval nowtv; time_t basetime; time_t triggertime; time_t timeslot; /* counters timeslot */ time_t t_timeslot; /* trigger timeslot */ struct timeval flushtime; /* last time the table has been flushed */ int pending_accumulators; int num_primitives; int dyn_table; int dyn_table_time_only; char dyn_table_name[SRVBUFLEN]; int recover; int locks; time_t new_basetime; time_t committed_basetime; int current_queue_elem; struct multi_values mv; int cp_idx; /* custom primitives index */ /* stats */ time_t elap_time; /* elapsed time */ unsigned int ten; /* total elements number */ unsigned int een; /* effective elements number */ unsigned int qn; /* total query number */ unsigned int iqn; /* INSERTs query number */ unsigned int uqn; /* UPDATEs query number */ }; struct db_cache { struct pkt_primitives primitives; pm_counter_t bytes_counter; pm_counter_t packet_counter; pm_counter_t flows_counter; u_int8_t flow_type; u_int8_t tcp_flags; u_int8_t tunnel_tcp_flags; time_t basetime; struct pkt_bgp_primitives *pbgp; struct pkt_nat_primitives *pnat; struct pkt_mpls_primitives *pmpls; struct pkt_tunnel_primitives *ptun; u_char *pcust; struct pkt_vlen_hdr_primitives *pvlen; u_int8_t valid; u_int8_t prep_valid; unsigned int signature; u_int8_t chained; struct pkt_stitching *stitch; struct db_cache *prev; struct db_cache *next; time_t start_tag; /* time: first packet received */ time_t lru_tag; /* time: last packet received */ struct db_cache *lru_prev; struct db_cache *lru_next; }; typedef void (*dbop_handler) (const struct db_cache *, struct insert_data *, int, char **, char **); struct frags { dbop_handler handler; u_int64_t type; char string[SRVBUFLEN]; }; /* Backend descriptors */ struct DBdesc { void *desc; char *conn_string; /* PostgreSQL */ char *filename; /* SQLite */ char *errmsg; short int type; short int connected; short int fail; }; struct BE_descs { struct DBdesc *p; struct DBdesc *b; }; /* Callbacks for a common SQL layer */ typedef void (*db_connect)(struct DBdesc *, char *); typedef void (*db_close)(struct BE_descs *); typedef void (*db_lock)(struct DBdesc *); typedef void (*db_unlock)(struct BE_descs *); typedef void (*db_create_table)(struct DBdesc *, char *); typedef int (*db_op)(struct DBdesc *, struct db_cache *, struct insert_data *); typedef void (*sqlcache_purge)(struct db_cache *[], int, struct insert_data *); typedef void (*sqlbackend_create)(struct DBdesc *); struct sqlfunc_cb_registry { db_connect connect; db_close close; db_lock lock; db_unlock unlock; db_op op; db_create_table create_table; sqlbackend_create create_backend; sqlcache_purge purge; /* flush and query wrapper are common for all SQL plugins */ }; #include "preprocess.h" /* functions */ extern void count_src_mac_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_mac_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_vlan_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_out_vlan_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_cos_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_etype_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_host_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_net_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_as_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_host_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_net_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_as_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_std_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_ext_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_lrg_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_as_path_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_local_pref_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_med_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_roa_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_std_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_ext_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_lrg_comm_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_as_path_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_local_pref_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_med_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_roa_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_mpls_vpn_rd_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_mpls_pw_id_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_src_as_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_dst_as_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_src_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_dst_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_ip_tos_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_in_iface_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_out_iface_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_nmask_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_nmask_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_sampling_rate_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_sampling_direction_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void MY_count_ip_proto_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_count_ip_proto_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_copy_timestamp_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tag_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tag2_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_label_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_class_id_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tcpflags_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_src_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_dst_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_src_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_dst_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_nat_event_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_fw_event_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_fwd_status_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_mpls_label_top_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_mpls_label_bottom_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_mpls_label_stack_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_src_mac_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_dst_mac_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_src_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_dst_ip_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void MY_count_tunnel_ip_proto_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_count_tunnel_ip_proto_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_ip_tos_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_src_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_dst_port_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_tcpflags_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_vxlan_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_start_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_start_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_start_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_end_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_end_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_end_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_arrival_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_arrival_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_arrival_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_export_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_export_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_export_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_min_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_min_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_min_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_max_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void PG_copy_count_timestamp_max_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_export_proto_seqno_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_export_proto_version_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_export_proto_sysid_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_timestamp_max_residual_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_custom_primitives_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_mac_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_host_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_as_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_comms_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_as_path_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_mpls_vpn_rd_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_host_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_host_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_net_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_net_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_src_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_peer_dst_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_src_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_post_nat_dst_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_src_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_dst_ip_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void fake_host_aton_handler(const struct db_cache *, struct insert_data *, int, char **, char **); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) extern void count_src_host_country_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_host_country_handler(const struct db_cache *, struct insert_data *, int, char **, char **); #endif #if defined (WITH_GEOIPV2) extern void count_src_host_pocode_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_host_pocode_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_src_host_coords_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_dst_host_coords_handler(const struct db_cache *, struct insert_data *, int, char **, char **); #endif #if defined (WITH_NDPI) extern void count_ndpi_class_handler(const struct db_cache *, struct insert_data *, int, char **, char **); #endif extern void count_counters_setclause_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_flows_setclause_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tcpflags_setclause_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_tunnel_tcpflags_setclause_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_noop_setclause_handler(const struct db_cache *, struct insert_data *, int, char **, char **); extern void count_noop_setclause_event_handler(const struct db_cache *, struct insert_data *, int, char **, char **); /* Toward a common SQL layer */ extern void sql_set_signals(); extern void sql_set_insert_func(); extern void sql_init_maps(struct extra_primitives *, struct primitives_ptrs *, struct networks_table *, struct networks_cache *, struct ports_table *, struct protos_table *, struct protos_table *); extern void sql_init_global_buffers(); extern void sql_init_default_values(struct extra_primitives *); extern void sql_init_historical_acct(time_t, struct insert_data *); extern void sql_init_triggers(time_t, struct insert_data *); extern void sql_init_refresh_deadline(time_t *); extern void sql_link_backend_descriptors(struct BE_descs *, struct DBdesc *, struct DBdesc *); extern void sql_cache_modulo(struct primitives_ptrs *, struct insert_data *); extern int sql_cache_flush(struct db_cache *[], int, struct insert_data *, int); extern void sql_cache_flush_pending(struct db_cache *[], int, struct insert_data *); extern void sql_cache_handle_flush_event(struct insert_data *, time_t *, struct ports_table *, struct protos_table *, struct protos_table *); extern void sql_cache_insert(struct primitives_ptrs *, struct insert_data *); extern struct db_cache *sql_cache_search(struct primitives_ptrs *, time_t); extern int sql_trigger_exec(char *); extern void sql_db_ok(struct DBdesc *); extern void sql_db_fail(struct DBdesc *); extern void sql_db_errmsg(struct DBdesc *); extern void sql_db_warnmsg(struct DBdesc *); extern int sql_query(struct BE_descs *, struct db_cache *, struct insert_data *); extern void sql_exit_gracefully(int); extern int sql_evaluate_primitives(int); extern void sql_create_table(struct DBdesc *, time_t *, struct primitives_ptrs *); extern void sql_invalidate_shadow_entries(struct db_cache *[], int *); extern int sql_select_locking_style(char *); extern int sql_compose_static_set(int); extern int sql_compose_static_set_event(); extern void primptrs_set_all_from_db_cache(struct primitives_ptrs *, struct db_cache *); extern void sql_set_stitch(struct db_cache *, struct pkt_data *, struct insert_data *); extern void sql_update_stitch(struct db_cache *, struct pkt_data *, struct insert_data *); extern void sql_update_time_reference(struct insert_data *); extern void sql_sum_host_insert(struct primitives_ptrs *, struct insert_data *); extern void sql_sum_port_insert(struct primitives_ptrs *, struct insert_data *); extern void sql_sum_as_insert(struct primitives_ptrs *, struct insert_data *); #if defined (HAVE_L2) extern void sql_sum_mac_insert(struct primitives_ptrs *, struct insert_data *); #endif extern void sql_sum_std_comm_insert(struct primitives_ptrs *, struct insert_data *); extern void sql_sum_ext_comm_insert(struct primitives_ptrs *, struct insert_data *); #if 10 /* Global Variables: a simple way of gain precious speed when playing with strings */ extern char sql_data[LARGEBUFLEN]; extern char lock_clause[LONGSRVBUFLEN]; extern char unlock_clause[LONGSRVBUFLEN]; extern char update_clause[LONGSRVBUFLEN]; extern char set_clause[LONGSRVBUFLEN]; extern char copy_clause[LONGSRVBUFLEN]; extern char insert_clause[LONGSRVBUFLEN]; extern char insert_counters_clause[LONGSRVBUFLEN]; extern char insert_nocounters_clause[LONGSRVBUFLEN]; extern char insert_full_clause[LONGSRVBUFLEN]; extern char values_clause[LONGLONGSRVBUFLEN]; extern char *multi_values_buffer; extern char where_clause[LONGLONGSRVBUFLEN]; extern unsigned char *pipebuf; extern struct db_cache *sql_cache; extern struct db_cache **sql_queries_queue, **sql_pending_queries_queue; extern struct db_cache *collision_queue; extern int cq_ptr, sql_qq_ptr, qq_size, sql_pp_size, sql_pb_size, sql_pn_size, sql_pm_size, sql_pt_size; extern int sql_pc_size, sql_dbc_size, cq_size, sql_pqq_ptr; extern struct db_cache lru_head, *lru_tail; extern struct frags where[N_PRIMITIVES+2]; extern struct frags values[N_PRIMITIVES+2]; extern struct frags copy_values[N_PRIMITIVES+2]; extern struct frags set[N_PRIMITIVES+2]; extern struct frags set_event[N_PRIMITIVES+2]; extern int glob_num_primitives; /* last resort for signal handling */ extern int glob_basetime; /* last resort for signal handling */ extern time_t glob_new_basetime; /* last resort for signal handling */ extern time_t glob_committed_basetime; /* last resort for signal handling */ extern int glob_dyn_table, glob_dyn_table_time_only; /* last resort for signal handling */ extern int glob_timeslot; /* last resort for sql handlers */ extern struct sqlfunc_cb_registry sqlfunc_cbr; extern void (*sql_insert_func)(struct primitives_ptrs *, struct insert_data *); extern struct DBdesc p; extern struct DBdesc b; extern struct BE_descs bed; extern struct largebuf_s envbuf; extern time_t now; /* PostgreSQL */ #endif #endif //SQL_COMMON_H pmacct-1.7.8/src/imt_plugin.c0000644000175000017500000005040214354105275015115 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "imt_plugin.h" #include "bgp/bgp.h" #include "net_aggr.h" //Global variables void (*imt_insert_func)(struct primitives_ptrs *); unsigned char *mpd; unsigned char *a; struct memory_pool_desc *current_pool; struct acc **lru_elem_ptr; int no_more_space; struct timeval cycle_stamp; struct timeval table_reset_stamp; /* Functions */ void imt_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { int maxqsize = (MAX_QUERIES*sizeof(struct pkt_primitives))+sizeof(struct query_header)+2; struct sockaddr cAddr; struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; unsigned char srvbuf[maxqsize]; unsigned char *srvbufptr; struct query_header *qh; unsigned char *pipebuf, *dataptr; char path[] = "/tmp/collect.pipe"; short int go_to_clear = FALSE; u_int32_t request, sz; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct extra_primitives extras; unsigned char *rgptr; int pollagain = 0; u_int32_t seq = 0; int rg_err_count = 0; int ret, lock = FALSE, num, sd, sd2; struct pkt_bgp_primitives *pbgp, empty_pbgp; struct pkt_legacy_bgp_primitives *plbgp, empty_plbgp; struct pkt_nat_primitives *pnat, empty_pnat; struct pkt_mpls_primitives *pmpls, empty_pmpls; struct pkt_tunnel_primitives *ptun, empty_ptun; unsigned char *pcust, empty_pcust[] = ""; struct pkt_vlen_hdr_primitives *pvlen, empty_pvlen; struct networks_file_data nfd; struct primitives_ptrs prim_ptrs; socklen_t cLen; /* poll() stuff */ struct pollfd poll_fd[2]; /* pipe + server */ int poll_timeout; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "IMT Plugin", config.name); if (config.proc_priority) { ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (extras.off_pkt_vlen_hdr_primitives || config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) { Log(LOG_ERR, "ERROR ( %s/%s ): variable-length primitives, ie. label, are not supported in IMT plugin. Exiting ..\n", config.name, config.type); exit_gracefully(1); } reload_map = FALSE; status->wakeup = TRUE; /* a bunch of default definitions and post-checks */ pipebuf = (unsigned char *) malloc(config.buffer_size); if (!pipebuf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pipebuf). Exiting ..\n", config.name, config.type); exit_gracefully(1); } if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); memset(pipebuf, 0, config.buffer_size); no_more_space = FALSE; if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) imt_insert_func = sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) imt_insert_func = sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) imt_insert_func = sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) imt_insert_func = sum_mac_insert; #endif else imt_insert_func = insert_accounting_structure; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); if (!config.num_memory_pools) config.num_memory_pools = NUM_MEMORY_POOLS; if (!config.memory_pool_size) config.memory_pool_size = MEMORY_POOL_SIZE; else { if (config.memory_pool_size < sizeof(struct acc)) { Log(LOG_WARNING, "WARN ( %s/%s ): enforcing memory pool's minimum size, %d bytes.\n", config.name, config.type, (int)sizeof(struct acc)); config.memory_pool_size = MEMORY_POOL_SIZE; } } if (!config.imt_plugin_path) config.imt_plugin_path = path; if (!config.buckets) config.buckets = MAX_HOSTS; init_memory_pool_table(config); if (mpd == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate memory pools table\n", config.name, config.type); exit_gracefully(1); } current_pool = request_memory_pool(config.buckets*sizeof(struct acc)); if (current_pool == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate first memory pool, try with larger value.\n", config.name, config.type); exit_gracefully(1); } a = current_pool->base_ptr; lru_elem_ptr = malloc(config.buckets*sizeof(struct acc *)); if (lru_elem_ptr == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate LRU element pointers.\n", config.name, config.type); exit_gracefully(1); } else memset(lru_elem_ptr, 0, config.buckets*sizeof(struct acc *)); current_pool = request_memory_pool(config.memory_pool_size); if (current_pool == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate more memory pools, try with larger value.\n", config.name, config.type); exit_gracefully(1); } signal(SIGHUP, reload); /* handles reopening of syslog channel */ signal(SIGINT, exit_now); /* exit lane */ signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); memset(&empty_pbgp, 0, sizeof(empty_pbgp)); memset(&empty_plbgp, 0, sizeof(empty_plbgp)); memset(&empty_pnat, 0, sizeof(empty_pnat)); memset(&empty_pmpls, 0, sizeof(empty_pmpls)); memset(&empty_ptun, 0, sizeof(empty_ptun)); memset(&empty_pvlen, 0, sizeof(empty_pvlen)); memset(&table_reset_stamp, 0, sizeof(table_reset_stamp)); /* building a server for interrogations by clients */ sd = build_query_server(config.imt_plugin_path); cLen = sizeof(cAddr); qh = (struct query_header *) srvbuf; #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: poll_timeout = DEFAULT_IMT_PLUGIN_POLL_TIMEOUT * 1000; memset(&poll_fd, 0, sizeof(poll_fd)); poll_fd[0].fd = pipe_fd; poll_fd[0].events = POLLIN; poll_fd[1].fd = sd; poll_fd[1].events = POLLIN; num = poll(poll_fd, 2, poll_timeout); gettimeofday(&cycle_stamp, NULL); if (num <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (num < 0) goto poll_again; } /* doing server tasks */ if (poll_fd[1].revents & POLLIN) { struct pollfd pfd; sd2 = accept(sd, &cAddr, &cLen); setblocking(sd2); srvbufptr = srvbuf; sz = maxqsize; pfd.fd = sd2; pfd.events = POLLIN; recv_again: ret = poll(&pfd, 1, 1000); if (ret == 0) { Log(LOG_WARNING, "WARN ( %s/%s ): Timed out while processing fragmented query.\n", config.name, config.type); close(sd2); goto poll_again; } else { num = recv(sd2, srvbufptr, sz, 0); if (srvbufptr[num-1] != '\x4') { srvbufptr += num; sz -= num; goto recv_again; /* fragmented query */ } } num = num+(maxqsize-sz); if (qh->num > MAX_QUERIES) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): request discarded. Too much queries.\n", config.name, config.type); close(sd2); continue; } request = qh->type; if (request & WANT_RESET) request ^= WANT_RESET; if (request & WANT_LOCK_OP) { lock = TRUE; request ^= WANT_LOCK_OP; } /* - if explicitely required, we do not fork: query obtains exclusive control - lock - over the memory table; - operations that may cause inconsistencies (full erasure, counter reset for individual entries, etc.) are entitled of an exclusive lock. - if query is matter of just a single short-lived walk through the table, we avoid fork(): the plugin will serve the request; - in all other cases, we fork; the newly created child will serve queries asyncronously. */ if (request & WANT_ERASE) { request ^= WANT_ERASE; if (request) { if (num > 0) process_query_data(sd2, srvbuf, num, &extras, datasize, FALSE); else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d incoming bytes. Errno: %d\n", config.name, config.type, num, errno); } Log(LOG_DEBUG, "DEBUG ( %s/%s ): Closing connection with client ...\n", config.name, config.type); go_to_clear = TRUE; } else if (((request == WANT_COUNTER) || (request == WANT_MATCH)) && (qh->num == 1) && (qh->what_to_count == config.what_to_count)) { if (num > 0) process_query_data(sd2, srvbuf, num, &extras, datasize, FALSE); else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d incoming bytes. ERRNO: %d\n", config.name, config.type, num, errno); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Closing connection with client ...\n", config.name, config.type); } else if (request == WANT_CLASS_TABLE) { if (num > 0) process_query_data(sd2, srvbuf, num, &extras, datasize, FALSE); else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d incoming bytes. ERRNO: %d\n", config.name, config.type, num, errno); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Closing connection with client ...\n", config.name, config.type); } else { if (lock) { if (num > 0) process_query_data(sd2, srvbuf, num, &extras, datasize, FALSE); else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d incoming bytes. Errno: %d\n", config.name, config.type, num, errno); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Closing connection with client ...\n", config.name, config.type); } else { switch (fork()) { case -1: /* Something went wrong */ Log(LOG_WARNING, "WARN ( %s/%s ): Unable to serve client query: %s\n", config.name, config.type, strerror(errno)); break; case 0: /* Child */ close(sd); pm_setproctitle("%s [%s]", "IMT Plugin -- serving client", config.name); config.is_forked = TRUE; if (num > 0) process_query_data(sd2, srvbuf, num, &extras, datasize, TRUE); else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %d incoming bytes. Errno: %d\n", config.name, config.type, num, errno); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Closing connection with client ...\n", config.name, config.type); close(sd2); exit_gracefully(0); default: /* Parent */ break; } } } close(sd2); } /* clearing stats if requested */ if (go_to_clear) { /* When using extended BGP features we need to free() up memory allocations before erasing */ /* XXX: given the current use of empty_* vars we have always to free_extra_allocs() in order to prevent memory leaks */ free_extra_allocs(); clear_memory_pool_table(); current_pool = request_memory_pool(config.buckets*sizeof(struct acc)); if (current_pool == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): Cannot allocate my first memory pool, try with larger value.\n", config.name, config.type); exit_gracefully(1); } a = current_pool->base_ptr; current_pool = request_memory_pool(config.memory_pool_size); if (current_pool == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): Cannot allocate more memory pools, try with larger value.\n", config.name, config.type); exit_gracefully(1); } go_to_clear = FALSE; no_more_space = FALSE; memcpy(&table_reset_stamp, &cycle_stamp, sizeof(struct timeval)); } if (reload_map) { load_networks(config.networks_file, &nt, &nc); load_ports(config.ports_file, &pt); load_protos(config.protos_file, &prt); load_tos(config.tos_file, &tost); reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } if (poll_fd[0].revents & POLLIN) { #ifdef WITH_ZMQ read_data: #endif if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; } pollagain = FALSE; if ((num = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ if (num < 0) { pollagain = TRUE; goto poll_again; } memcpy(pipebuf, rgptr, config.buffer_size); if (((struct ch_buf_hdr *)pipebuf)->seq != seq) { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif if (num > 0) { data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { if (extras.off_pkt_bgp_primitives) pbgp = (struct pkt_bgp_primitives *) ((u_char *)data + extras.off_pkt_bgp_primitives); else pbgp = &empty_pbgp; if (extras.off_pkt_lbgp_primitives) plbgp = (struct pkt_legacy_bgp_primitives *) ((u_char *)data + extras.off_pkt_lbgp_primitives); else plbgp = &empty_plbgp; if (extras.off_pkt_nat_primitives) pnat = (struct pkt_nat_primitives *) ((u_char *)data + extras.off_pkt_nat_primitives); else pnat = &empty_pnat; if (extras.off_pkt_mpls_primitives) pmpls = (struct pkt_mpls_primitives *) ((u_char *)data + extras.off_pkt_mpls_primitives); else pmpls = &empty_pmpls; if (extras.off_pkt_tun_primitives) ptun = (struct pkt_tunnel_primitives *) ((u_char *)data + extras.off_pkt_tun_primitives); else ptun = &empty_ptun; if (extras.off_custom_primitives) pcust = ((u_char *)data + extras.off_custom_primitives); else pcust = empty_pcust; if (extras.off_pkt_vlen_hdr_primitives) pvlen = (struct pkt_vlen_hdr_primitives *) ((u_char *)data + extras.off_pkt_vlen_hdr_primitives); else pvlen = &empty_pvlen; for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; prim_ptrs.pbgp = pbgp; prim_ptrs.plbgp = plbgp; prim_ptrs.pnat = pnat; prim_ptrs.pmpls = pmpls; prim_ptrs.ptun = ptun; prim_ptrs.pcust = pcust; prim_ptrs.pvlen = pvlen; (*imt_insert_func)(&prim_ptrs); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; dataptr += datasize; data = (struct pkt_data *) dataptr; } } } #ifdef WITH_ZMQ if (config.pipe_zmq) goto read_data; #endif } } } void exit_now(int signum) { if (config.imt_plugin_path) unlink(config.imt_plugin_path); if (config.pidfile) remove_pid_file(config.pidfile); exit_gracefully(0); } void sum_host_insert(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; struct host_addr tmp; memcpy(&tmp, &data->primitives.dst_ip, HostAddrSz); memset(&data->primitives.dst_ip, 0, HostAddrSz); insert_accounting_structure(prim_ptrs); memcpy(&data->primitives.src_ip, &tmp, HostAddrSz); insert_accounting_structure(prim_ptrs); } void sum_port_insert(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; u_int16_t port; port = data->primitives.dst_port; data->primitives.dst_port = 0; insert_accounting_structure(prim_ptrs); data->primitives.src_port = port; insert_accounting_structure(prim_ptrs); } void sum_as_insert(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; as_t asn; asn = data->primitives.dst_as; data->primitives.dst_as = 0; insert_accounting_structure(prim_ptrs); data->primitives.src_as = asn; insert_accounting_structure(prim_ptrs); } #if defined (HAVE_L2) void sum_mac_insert(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; u_char macaddr[ETH_ADDR_LEN]; memcpy(macaddr, &data->primitives.eth_dhost, ETH_ADDR_LEN); memset(data->primitives.eth_dhost, 0, ETH_ADDR_LEN); insert_accounting_structure(prim_ptrs); memcpy(&data->primitives.eth_shost, macaddr, ETH_ADDR_LEN); insert_accounting_structure(prim_ptrs); } #endif void free_extra_allocs() { struct acc *acc_elem = NULL; unsigned char *elem; int following_chain = FALSE; unsigned int idx; elem = (unsigned char *) a; for (idx = 0; idx < config.buckets; idx++) { if (!following_chain) acc_elem = (struct acc *) elem; if (acc_elem->pbgp) { free(acc_elem->pbgp); acc_elem->pbgp = NULL; } if (acc_elem->clbgp) free_cache_legacy_bgp_primitives(&acc_elem->clbgp); if (acc_elem->pnat) { free(acc_elem->pnat); acc_elem->pnat = NULL; } if (acc_elem->pmpls) { free(acc_elem->pmpls); acc_elem->pmpls = NULL; } if (acc_elem->ptun) { free(acc_elem->ptun); acc_elem->ptun = NULL; } if (acc_elem->pcust) { free(acc_elem->pcust); acc_elem->pcust = NULL; } if (acc_elem->pvlen) { free(acc_elem->pvlen); acc_elem->pvlen= NULL; } if (acc_elem->next) { acc_elem = acc_elem->next; following_chain++; idx--; } else { elem += sizeof(struct acc); following_chain = FALSE; } } } pmacct-1.7.8/src/sql_common.c0000644000175000017500000050252214354105275015122 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "sql_common.h" #include "sql_common_m.h" #include "crc32.h" /* Global variables */ char sql_data[LARGEBUFLEN]; char lock_clause[LONGSRVBUFLEN]; char unlock_clause[LONGSRVBUFLEN]; char update_clause[LONGSRVBUFLEN]; char set_clause[LONGSRVBUFLEN]; char copy_clause[LONGSRVBUFLEN]; char insert_clause[LONGSRVBUFLEN]; char insert_counters_clause[LONGSRVBUFLEN]; char insert_nocounters_clause[LONGSRVBUFLEN]; char insert_full_clause[LONGSRVBUFLEN]; char values_clause[LONGLONGSRVBUFLEN]; char *multi_values_buffer; char where_clause[LONGLONGSRVBUFLEN]; unsigned char *pipebuf; struct db_cache *sql_cache; struct db_cache **sql_queries_queue, **sql_pending_queries_queue; struct db_cache *collision_queue; int cq_ptr, sql_qq_ptr, qq_size, sql_pp_size, sql_pb_size, sql_pn_size, sql_pm_size, sql_pt_size; int sql_pc_size, sql_dbc_size, cq_size, sql_pqq_ptr; struct db_cache lru_head, *lru_tail; struct frags where[N_PRIMITIVES+2]; struct frags values[N_PRIMITIVES+2]; struct frags copy_values[N_PRIMITIVES+2]; struct frags set[N_PRIMITIVES+2]; struct frags set_event[N_PRIMITIVES+2]; int glob_num_primitives; /* last resort for signal handling */ int glob_basetime; /* last resort for signal handling */ time_t glob_new_basetime; /* last resort for signal handling */ time_t glob_committed_basetime; /* last resort for signal handling */ int glob_dyn_table, glob_dyn_table_time_only; /* last resort for signal handling */ int glob_timeslot; /* last resort for sql handlers */ struct sqlfunc_cb_registry sqlfunc_cbr; void (*sql_insert_func)(struct primitives_ptrs *, struct insert_data *); struct DBdesc p; struct DBdesc b; struct BE_descs bed; struct largebuf_s envbuf; time_t now; /* PostgreSQL */ /* Functions */ void sql_set_signals() { signal(SIGINT, sql_exit_gracefully); signal(SIGHUP, reload); /* handles reopening of syslog channel */ signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, ignore_falling_child); } void sql_set_insert_func() { if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) sql_insert_func = sql_sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) sql_insert_func = sql_sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) sql_insert_func = sql_sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) sql_insert_func = sql_sum_mac_insert; #endif else sql_insert_func = sql_cache_insert; } void sql_init_maps(struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs, struct networks_table *nt, struct networks_cache *nc, struct ports_table *pt, struct protos_table *prt, struct protos_table *tost) { memset(prim_ptrs, 0, sizeof(struct primitives_ptrs)); set_primptrs_funcs(extras); memset(nt, 0, sizeof(struct networks_table)); memset(nc, 0, sizeof(struct networks_cache)); memset(pt, 0, sizeof(struct ports_table)); memset(prt, 0, sizeof(struct protos_table)); memset(tost, 0, sizeof(struct protos_table)); load_networks(config.networks_file, nt, nc); set_net_funcs(nt); if (config.ports_file) load_ports(config.ports_file, pt); if (config.protos_file) load_protos(config.protos_file, prt); if (config.tos_file) load_tos(config.tos_file, tost); } void sql_init_global_buffers() { memset(sql_data, 0, sizeof(sql_data)); memset(lock_clause, 0, sizeof(lock_clause)); memset(unlock_clause, 0, sizeof(unlock_clause)); memset(update_clause, 0, sizeof(update_clause)); memset(set_clause, 0, sizeof(set_clause)); memset(copy_clause, 0, sizeof(copy_clause)); memset(insert_clause, 0, sizeof(insert_clause)); memset(insert_counters_clause, 0, sizeof(insert_counters_clause)); memset(insert_nocounters_clause, 0, sizeof(insert_nocounters_clause)); memset(where, 0, sizeof(where)); memset(values, 0, sizeof(values)); memset(set, 0, sizeof(set)); memset(set_event, 0, sizeof(set_event)); memset(&lru_head, 0, sizeof(lru_head)); lru_tail = &lru_head; Log(LOG_INFO, "INFO ( %s/%s ): cache entries=%d base cache memory=%lu bytes\n", config.name, config.type, config.sql_cache_entries, (unsigned long)(((config.sql_cache_entries * sizeof(struct db_cache)) + (2 * (qq_size * sizeof(struct db_cache *)))))); pipebuf = (unsigned char *) malloc(config.buffer_size); sql_cache = (struct db_cache *) malloc(config.sql_cache_entries*sizeof(struct db_cache)); sql_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *)); sql_pending_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *)); if (!pipebuf || !sql_cache || !sql_queries_queue || !sql_pending_queries_queue) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (sql_init_global_buffers). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memset(pipebuf, 0, config.buffer_size); memset(sql_cache, 0, config.sql_cache_entries*sizeof(struct db_cache)); memset(sql_queries_queue, 0, qq_size*sizeof(struct db_cache *)); memset(sql_pending_queries_queue, 0, qq_size*sizeof(struct db_cache *)); } /* being the first routine to be called by each SQL plugin, this is also the place for some initial common configuration consistency check */ void sql_init_default_values(struct extra_primitives *extras) { memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } if (!config.sql_refresh_time) config.sql_refresh_time = DEFAULT_DB_REFRESH_TIME; if (!config.sql_table_version) config.sql_table_version = DEFAULT_SQL_TABLE_VERSION; if (!config.sql_cache_entries) config.sql_cache_entries = CACHE_ENTRIES; if (!config.dump_max_writers) config.dump_max_writers = DEFAULT_SQL_WRITERS_NO; dump_writers.list = malloc(config.dump_max_writers * sizeof(pid_t)); dump_writers_init(); /* SQL table type parsing; basically mapping everything down to a SQL table version */ /* ie. BGP == 1000 */ if (config.sql_table_type) { if (!strcmp(config.sql_table_type, "bgp")) config.sql_table_version += SQL_TABLE_VERSION_BGP; else { Log(LOG_ERR, "ERROR ( %s/%s ): Unknown sql_table_type value: '%s'.\n", config.name, config.type, config.sql_table_type); exit_gracefully(1); } } else { if (extras->off_pkt_bgp_primitives) { config.sql_table_version += SQL_TABLE_VERSION_BGP; Log(LOG_INFO, "INFO ( %s/%s ): sql_table_type set to 'bgp' (aggregate includes one or more BGP primitives).\n", config.name, config.type); } } if (config.nfacctd_stitching) { if (config.nfacctd_pro_rating) { Log(LOG_ERR, "ERROR ( %s/%s ): Pro-rating (ie. nfacctd_pro_rating) and stitching (ie. nfacctd_stitching) are mutual exclusive. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (!config.sql_dont_try_update) { Log(LOG_WARNING, "WARN ( %s/%s ): stitching (ie. nfacctd_stitching) behaviour is undefined when sql_dont_try_update is set to false.\n", config.name, config.type); } } sql_qq_ptr = 0; sql_pqq_ptr = 0; qq_size = config.sql_cache_entries+(config.sql_refresh_time*REASONABLE_NUMBER); sql_pp_size = sizeof(struct pkt_primitives); sql_pb_size = sizeof(struct pkt_bgp_primitives); sql_pn_size = sizeof(struct pkt_nat_primitives); sql_pm_size = sizeof(struct pkt_mpls_primitives); sql_pt_size = sizeof(struct pkt_tunnel_primitives); sql_pc_size = config.cpptrs.len; sql_dbc_size = sizeof(struct db_cache); /* handling purge preprocessor */ set_preprocess_funcs(config.sql_preprocess, &prep, PREP_DICT_SQL); if (config.tcpflags_encode_as_array || config.mpls_label_stack_encode_as_array || config.pretag_label_encode_as_map) { Log(LOG_WARNING, "WARN ( %s/%s ): Complex data types (ie. pre_tag_label_encode_as_map) not supported by SQL plugins. Ignored.\n", config.name, config.type); } } void sql_init_historical_acct(time_t now, struct insert_data *idata) { time_t t; if (config.sql_history) { idata->basetime = now; if (config.sql_history == COUNT_SECONDLY) idata->timeslot = config.sql_history_howmany; else if (config.sql_history == COUNT_MINUTELY) idata->timeslot = config.sql_history_howmany*60; else if (config.sql_history == COUNT_HOURLY) idata->timeslot = config.sql_history_howmany*3600; else if (config.sql_history == COUNT_DAILY) idata->timeslot = config.sql_history_howmany*86400; else if (config.sql_history == COUNT_WEEKLY) idata->timeslot = config.sql_history_howmany*86400*7; else if (config.sql_history == COUNT_MONTHLY) { idata->basetime = roundoff_time(idata->basetime, "d"); /* resetting day of month */ idata->timeslot = calc_monthly_timeslot(idata->basetime, config.sql_history_howmany, ADD); } /* round off stuff */ t = roundoff_time(idata->basetime, config.sql_history_roundoff); while ((t+idata->timeslot) < idata->basetime) { t += idata->timeslot; if (config.sql_history == COUNT_MONTHLY) idata->timeslot = calc_monthly_timeslot(t, config.sql_history_howmany, ADD); } if (config.sql_history_offset) { if (config.sql_history_offset >= idata->timeslot) { Log(LOG_ERR, "ERROR ( %s/%s ): History offset (ie. sql_history_offset) must be < history (ie. sql_history).\n", config.name, config.type); exit_gracefully(1); } t = t - (idata->timeslot + config.sql_history_offset); } idata->basetime = t; glob_basetime = idata->basetime; idata->new_basetime = idata->basetime; glob_new_basetime = idata->basetime; glob_timeslot = idata->timeslot; idata->committed_basetime = 0; glob_committed_basetime = 0; } } /* NOTE: sql triggers time init: deadline; if a trigger exec is specified but no time is supplied, use 'sql_refresh_time' as interval; this will result in a trigger being executed each time data is purged into the DB */ void sql_init_triggers(time_t now, struct insert_data *idata) { time_t t, deadline; if (config.sql_trigger_exec) { deadline = now; if (config.sql_trigger_time == COUNT_MINUTELY) idata->t_timeslot = config.sql_trigger_time_howmany*60; else if (config.sql_trigger_time == COUNT_HOURLY) idata->t_timeslot = config.sql_trigger_time_howmany*3600; else if (config.sql_trigger_time == COUNT_DAILY) idata->t_timeslot = config.sql_trigger_time_howmany*86400; else if (config.sql_trigger_time == COUNT_WEEKLY) idata->t_timeslot = config.sql_trigger_time_howmany*86400*7; else if (config.sql_trigger_time == COUNT_MONTHLY) { deadline = roundoff_time(deadline, "d"); /* resetting day of month */ idata->t_timeslot = calc_monthly_timeslot(deadline, config.sql_trigger_time_howmany, ADD); } else idata->t_timeslot = config.sql_refresh_time; /* round off stuff */ t = roundoff_time(deadline, config.sql_history_roundoff); while ((t+idata->t_timeslot) < deadline) { t += idata->t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata->t_timeslot = calc_monthly_timeslot(t, config.sql_trigger_time_howmany, ADD); } idata->triggertime = (t + config.sql_startup_delay); /* adding a trailer timeslot: it's a deadline not a basetime */ idata->triggertime += idata->t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata->t_timeslot = calc_monthly_timeslot(t, config.sql_trigger_time_howmany, ADD); } } void sql_init_refresh_deadline(time_t *rd) { time_t t; t = roundoff_time(*rd, config.sql_history_roundoff); while ((t+config.sql_refresh_time) < *rd) t += config.sql_refresh_time; *rd = t; *rd += (config.sql_refresh_time+config.sql_startup_delay); /* it's a deadline not a basetime */ } void sql_link_backend_descriptors(struct BE_descs *registry, struct DBdesc *p, struct DBdesc *b) { memset(registry, 0, sizeof(struct BE_descs)); memset(p, 0, sizeof(struct DBdesc)); memset(b, 0, sizeof(struct DBdesc)); registry->p = p; registry->b = b; registry->p->type = BE_TYPE_PRIMARY; registry->b->type = BE_TYPE_BACKUP; if (*sqlfunc_cbr.create_backend) { (*sqlfunc_cbr.create_backend)(registry->p); (*sqlfunc_cbr.create_backend)(registry->b); } } void sql_cache_modulo(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *pdata = prim_ptrs->data; struct pkt_primitives *srcdst = &pdata->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; idata->hash = cache_crc32((unsigned char *)srcdst, sql_pp_size); if (pbgp) idata->hash ^= cache_crc32((unsigned char *)pbgp, sql_pb_size); if (pnat) idata->hash ^= cache_crc32((unsigned char *)pnat, sql_pn_size); if (pmpls) idata->hash ^= cache_crc32((unsigned char *)pmpls, sql_pm_size); if (ptun) idata->hash ^= cache_crc32((unsigned char *)ptun, sql_pt_size); if (pcust) idata->hash ^= cache_crc32((unsigned char *)pcust, sql_pc_size); if (pvlen) idata->hash ^= cache_crc32((unsigned char *)pvlen, (PvhdrSz + pvlen->tot_len)); idata->modulo = idata->hash % config.sql_cache_entries; } int sql_cache_flush(struct db_cache *queue[], int index, struct insert_data *idata, int exiting) { int j, delay = 0, new_basetime = FALSE; /* We are seeking how many time-bins data has to be delayed by; residual time is taken into account by scanner deadlines (sql_refresh_time) */ if (config.sql_startup_delay) { if (idata->timeslot) delay = config.sql_startup_delay/idata->timeslot; delay = delay*idata->timeslot; } /* check-pointing: we record last committed time-bin; part of this is checking whether basetime was moved forward yet (as this is not for sure). */ if (idata->new_basetime && idata->new_basetime < idata->basetime && idata->new_basetime > idata->committed_basetime) { new_basetime = TRUE; idata->committed_basetime = idata->new_basetime; } else idata->committed_basetime = idata->basetime; if (!exiting) { for (j = 0, sql_pqq_ptr = 0; j < index; j++) { if (new_basetime && queue[j]->basetime+delay >= idata->basetime) { sql_pending_queries_queue[sql_pqq_ptr] = queue[j]; sql_pqq_ptr++; } else if (!new_basetime && queue[j]->basetime+delay > idata->basetime) { sql_pending_queries_queue[sql_pqq_ptr] = queue[j]; sql_pqq_ptr++; } else queue[j]->valid = SQL_CACHE_COMMITTED; } } /* If exiting instead .. */ else { for (j = 0; j < index; j++) queue[j]->valid = SQL_CACHE_COMMITTED; } return index; } void sql_cache_flush_pending(struct db_cache *queue[], int index, struct insert_data *idata) { struct db_cache *Cursor, *auxCursor, *PendingElem, SavedCursor; int j; /* Not everything was purged, let's sort out the SQL cache buckets involved into that */ if (index) { for (j = 0; j < index; j++) { /* Select next element on the pending queue */ PendingElem = queue[j]; /* Go to the first element in the bucket */ for (Cursor = PendingElem, auxCursor = NULL; Cursor; auxCursor = Cursor, Cursor = Cursor->prev); /* Check whether we are already first in the bucket */ if (auxCursor != PendingElem) { Cursor = auxCursor; for (; Cursor && Cursor != PendingElem && Cursor->valid == SQL_CACHE_INUSE; Cursor = Cursor->next); /* Check whether a) the whole bucket chain is currently in use or b) we came across the current pending element: meaning no free positions are available in the chain, ahead of it */ if (Cursor && Cursor != PendingElem) { /* Check whether we have to replace the first element in the bucket */ if (!Cursor->prev) { memcpy(&SavedCursor, Cursor, sizeof(struct db_cache)); memcpy(Cursor, PendingElem, sizeof(struct db_cache)); Cursor->prev = NULL; Cursor->next = SavedCursor.next; Cursor->chained = FALSE; Cursor->lru_prev = NULL; Cursor->lru_next = NULL; /* unlinking pointers from PendingElem to prevent free-up (linked by Cursor) */ PendingElem->pbgp = NULL; PendingElem->pnat = NULL; PendingElem->pmpls = NULL; PendingElem->ptun = NULL; PendingElem->pcust = NULL; PendingElem->pvlen = NULL; PendingElem->stitch = NULL; RetireElem(PendingElem); queue[j] = Cursor; /* freeing stale allocations */ if (SavedCursor.pbgp) free(SavedCursor.pbgp); if (SavedCursor.pnat) free(SavedCursor.pnat); if (SavedCursor.pmpls) free(SavedCursor.pmpls); if (SavedCursor.ptun) free(SavedCursor.ptun); if (SavedCursor.pcust) free(SavedCursor.pcust); if (SavedCursor.pvlen) free(SavedCursor.pvlen); if (SavedCursor.stitch) free(SavedCursor.stitch); } /* We found at least one Cursor->valid == SQL_CACHE_INUSE */ else SwapChainedElems(PendingElem, Cursor); } } } } } void sql_cache_handle_flush_event(struct insert_data *idata, time_t *refresh_deadline, struct ports_table *pt, struct protos_table *prt, struct protos_table *tost) { int ret; dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) { switch (ret = fork()) { case 0: /* Child */ /* we have to ignore signals to avoid loops: because we are already forked */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); pm_setproctitle("%s %s [%s]", config.type, "Plugin -- DB Writer", config.name); config.is_forked = TRUE; if (sql_qq_ptr) { if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p); if (!strcmp(config.type, "mysql")) (*sqlfunc_cbr.connect)(&p, config.sql_host); else (*sqlfunc_cbr.connect)(&p, NULL); } /* sql_qq_ptr check inside purge function along with a Log() call */ (*sqlfunc_cbr.purge)(sql_queries_queue, sql_qq_ptr, idata); if (sql_qq_ptr) (*sqlfunc_cbr.close)(&bed); if (config.sql_trigger_exec) { if (idata->now > idata->triggertime) sql_trigger_exec(config.sql_trigger_exec); } exit_gracefully(0); default: /* Parent */ if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork DB writer: %s\n", config.name, config.type, strerror(errno)); else dump_writers_add(ret); break; } } else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); if (sql_pqq_ptr) sql_cache_flush_pending(sql_pending_queries_queue, sql_pqq_ptr, idata); gettimeofday(&idata->flushtime, NULL); while (idata->now > *refresh_deadline) *refresh_deadline += config.sql_refresh_time; while (idata->now > idata->triggertime && idata->t_timeslot > 0) { idata->triggertime += idata->t_timeslot; if (config.sql_trigger_time == COUNT_MONTHLY) idata->t_timeslot = calc_monthly_timeslot(idata->triggertime, config.sql_trigger_time_howmany, ADD); } idata->new_basetime = FALSE; glob_new_basetime = FALSE; sql_qq_ptr = sql_pqq_ptr; memcpy(sql_queries_queue, sql_pending_queries_queue, sql_qq_ptr*sizeof(struct db_cache *)); if (reload_map) { load_networks(config.networks_file, &nt, &nc); load_ports(config.ports_file, pt); load_protos(config.protos_file, prt); load_tos(config.tos_file, tost); reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } } struct db_cache *sql_cache_search(struct primitives_ptrs *prim_ptrs, time_t basetime) { struct pkt_data *pdata = prim_ptrs->data; struct pkt_primitives *data = &pdata->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct db_cache *Cursor; struct insert_data idata; int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE; int res_cust = TRUE, res_vlen = TRUE; sql_cache_modulo(prim_ptrs, &idata); Cursor = &sql_cache[idata.modulo]; start: if (idata.hash != Cursor->signature) { if (Cursor->valid == SQL_CACHE_INUSE) { follow_chain: if (Cursor->next) { Cursor = Cursor->next; goto start; } } } else { if (Cursor->valid == SQL_CACHE_INUSE) { /* checks: pkt_primitives and pkt_bgp_primitives */ res_data = memcmp(&Cursor->primitives, data, sizeof(struct pkt_primitives)); if (pbgp && Cursor->pbgp) { res_bgp = memcmp(Cursor->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); } else res_bgp = FALSE; if (pnat && Cursor->pnat) { res_nat = memcmp(Cursor->pnat, pnat, sizeof(struct pkt_nat_primitives)); } else res_nat = FALSE; if (pmpls && Cursor->pmpls) { res_mpls = memcmp(Cursor->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); } else res_mpls = FALSE; if (ptun && Cursor->ptun) { res_tun = memcmp(Cursor->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); } else res_tun = FALSE; if (pcust && Cursor->pcust) { res_cust = memcmp(Cursor->pcust, pcust, config.cpptrs.len); } else res_cust = FALSE; if (pvlen && Cursor->pvlen) { res_vlen = vlen_prims_cmp(Cursor->pvlen, pvlen); } else res_vlen = FALSE; if (!res_data && !res_bgp && !res_nat && !res_mpls && !res_tun && !res_cust && !res_vlen) { /* additional check: time */ if ((Cursor->basetime < basetime) && config.sql_history) goto follow_chain; else return Cursor; } else goto follow_chain; } } return NULL; } void sql_cache_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; time_t basetime = idata->basetime, timeslot = idata->timeslot; struct pkt_primitives *srcdst = &data->primitives; struct db_cache *Cursor, *newElem, *SafePtr = NULL, *staleElem = NULL; int ret, insert_status; /* pro_rating vars */ int time_delta = 0, time_total = 0; pm_counter_t tot_bytes = 0, tot_packets = 0, tot_flows = 0; /* housekeeping to start */ if (lru_head.lru_next && ((idata->now-lru_head.lru_next->lru_tag) > RETIRE_M*config.sql_refresh_time)) { /* if element status is SQL_CACHE_INUSE it can't be retired because sits on the queue */ if (lru_head.lru_next->valid != SQL_CACHE_INUSE) RetireElem(lru_head.lru_next); } tot_bytes = data->pkt_len; tot_packets = data->pkt_num; tot_flows = data->flo_num; if (data->time_start.tv_sec && config.sql_history) { if (config.sql_history != COUNT_MONTHLY) { int residual; if (basetime > data->time_start.tv_sec) { residual = timeslot - ((basetime - data->time_start.tv_sec) % timeslot); } else { residual = ((data->time_start.tv_sec - basetime) % timeslot); } basetime = data->time_start.tv_sec - residual; } else { while (basetime > data->time_start.tv_sec) { timeslot = calc_monthly_timeslot(basetime, config.sql_history_howmany, SUB); basetime -= timeslot; } while ((basetime + timeslot) < data->time_start.tv_sec) { basetime += timeslot; timeslot = calc_monthly_timeslot(basetime, config.sql_history_howmany, ADD); } } } new_timeslot: /* pro_rating, if needed */ if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) { if (data->time_end.tv_sec > data->time_start.tv_sec) { time_total = data->time_end.tv_sec - data->time_start.tv_sec; time_delta = MIN(data->time_end.tv_sec, basetime + timeslot) - MAX(data->time_start.tv_sec, basetime); if (time_delta > 0 && time_total > 0 && time_delta < time_total) { float ratio = (float) time_total / (float) time_delta; if (tot_bytes) data->pkt_len = MAX((float)tot_bytes / ratio, 1); if (tot_packets) data->pkt_num = MAX((float)tot_packets / ratio, 1); if (tot_flows) data->flo_num = MAX((float)tot_flows / ratio, 1); } } } sql_cache_modulo(prim_ptrs, idata); Cursor = &sql_cache[idata->modulo]; start: insert_status = SQL_INSERT_INSERT; if (idata->hash != Cursor->signature) { if (Cursor->valid == SQL_CACHE_INUSE) { follow_chain: if (Cursor->next) { Cursor = Cursor->next; goto start; } else { if (lru_head.lru_next && lru_head.lru_next->valid != SQL_CACHE_INUSE && ((idata->now-lru_head.lru_next->lru_tag) > STALE_M*config.sql_refresh_time)) { newElem = lru_head.lru_next; /* if (newElem != Cursor) */ /* check removed: Cursor must be SQL_CACHE_INUSE; newElem must be not SQL_CACHE_INUSE */ ReBuildChain(Cursor, newElem); Cursor = newElem; /* we have successfully reused a stale element */ } else { newElem = (struct db_cache *) malloc(sizeof(struct db_cache)); if (newElem) { memset(newElem, 0, sizeof(struct db_cache)); BuildChain(Cursor, newElem); Cursor = newElem; /* creating a new element */ } else insert_status = SQL_INSERT_SAFE_ACTION; /* we should have finished memory */ } } } /* we found a no more valid entry; let's insert here our data */ } else { if (Cursor->valid == SQL_CACHE_INUSE) { int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE; int res_cust = TRUE, res_vlen = TRUE; /* checks: pkt_primitives and pkt_bgp_primitives */ res_data = memcmp(&Cursor->primitives, srcdst, sizeof(struct pkt_primitives)); if (pbgp && Cursor->pbgp) { res_bgp = memcmp(Cursor->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); } else res_bgp = FALSE; if (pnat && Cursor->pnat) { res_nat = memcmp(Cursor->pnat, pnat, sizeof(struct pkt_nat_primitives)); } else res_nat = FALSE; if (pmpls && Cursor->pmpls) { res_mpls = memcmp(Cursor->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); } else res_mpls = FALSE; if (ptun && Cursor->ptun) { res_tun = memcmp(Cursor->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); } else res_tun = FALSE; if (pcust && Cursor->pcust) { res_cust = memcmp(Cursor->pcust, pcust, config.cpptrs.len); } else res_cust = FALSE; if (pvlen && Cursor->pvlen) { res_vlen = vlen_prims_cmp(Cursor->pvlen, pvlen); } else res_vlen = FALSE; if (!res_data && !res_bgp && !res_nat && !res_mpls && !res_tun && !res_cust && !res_vlen) { /* additional check: time */ if ((Cursor->basetime != basetime) && config.sql_history) goto follow_chain; /* additional check: bytes counter overflow */ if (Cursor->bytes_counter > CACHE_THRESHOLD) goto follow_chain; /* All is good: let's update the matching entry */ insert_status = SQL_INSERT_UPDATE; } else goto follow_chain; } } if (insert_status == SQL_INSERT_INSERT) { if (sql_qq_ptr < qq_size) { sql_queries_queue[sql_qq_ptr] = Cursor; sql_qq_ptr++; } else SafePtr = Cursor; /* we add the new entry in the cache */ memcpy(&Cursor->primitives, srcdst, sizeof(struct pkt_primitives)); if (pbgp) { if (!Cursor->pbgp) { Cursor->pbgp = (struct pkt_bgp_primitives *) malloc(sql_pb_size); if (!Cursor->pbgp) goto safe_action; } memcpy(Cursor->pbgp, pbgp, sql_pb_size); } else { if (Cursor->pbgp) free(Cursor->pbgp); Cursor->pbgp = NULL; } if (pnat) { if (!Cursor->pnat) { Cursor->pnat = (struct pkt_nat_primitives *) malloc(sql_pn_size); if (!Cursor->pnat) goto safe_action; } memcpy(Cursor->pnat, pnat, sql_pn_size); } else { if (Cursor->pnat) free(Cursor->pnat); Cursor->pnat = NULL; } if (pmpls) { if (!Cursor->pmpls) { Cursor->pmpls = (struct pkt_mpls_primitives *) malloc(sql_pm_size); if (!Cursor->pmpls) goto safe_action; } memcpy(Cursor->pmpls, pmpls, sql_pm_size); } else { if (Cursor->pmpls) free(Cursor->pmpls); Cursor->pmpls = NULL; } if (ptun) { if (!Cursor->ptun) { Cursor->ptun = (struct pkt_tunnel_primitives *) malloc(sql_pt_size); if (!Cursor->ptun) goto safe_action; } memcpy(Cursor->ptun, ptun, sql_pt_size); } else { if (Cursor->ptun) free(Cursor->ptun); Cursor->ptun = NULL; } if (pcust) { if (!Cursor->pcust) { Cursor->pcust = malloc(sql_pc_size); if (!Cursor->pcust) goto safe_action; } memcpy(Cursor->pcust, pcust, sql_pc_size); } else { if (Cursor->pcust) free(Cursor->pcust); Cursor->pcust = NULL; } /* if we have a pvlen from before let's free it up due to the vlen nature of the memory area */ if (Cursor->pvlen) { vlen_prims_free(Cursor->pvlen); Cursor->pvlen = NULL; } if (pvlen) { Cursor->pvlen = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen); if (!Cursor->pvlen) goto safe_action; } Cursor->packet_counter = data->pkt_num; Cursor->flows_counter = data->flo_num; Cursor->bytes_counter = data->pkt_len; Cursor->flow_type = data->flow_type; Cursor->tcp_flags = data->tcp_flags; Cursor->tunnel_tcp_flags = data->tunnel_tcp_flags; if (config.nfacctd_stitching) { if (!Cursor->stitch) { Cursor->stitch = (struct pkt_stitching *) malloc(sizeof(struct pkt_stitching)); } if (Cursor->stitch) { sql_set_stitch(Cursor, data, idata); } else Log(LOG_WARNING, "WARN ( %s/%s ): Finished memory for flow stitching.\n", config.name, config.type); } else assert(!Cursor->stitch); Cursor->valid = SQL_CACHE_INUSE; Cursor->basetime = basetime; Cursor->start_tag = idata->now; Cursor->lru_tag = idata->now; Cursor->signature = idata->hash; /* We are not so fancy to reuse elements which have not been malloc()'d before */ if (Cursor->chained) AddToLRUTail(Cursor); if (SafePtr) goto safe_action; if (staleElem) SwapChainedElems(Cursor, staleElem); insert_status = SQL_INSERT_PRO_RATING; } if (insert_status == SQL_INSERT_UPDATE) { Cursor->packet_counter += data->pkt_num; Cursor->flows_counter += data->flo_num; Cursor->bytes_counter += data->pkt_len; Cursor->flow_type = data->flow_type; Cursor->tcp_flags |= data->tcp_flags; Cursor->tunnel_tcp_flags |= data->tunnel_tcp_flags; if (config.nfacctd_stitching) { if (Cursor->stitch) { sql_update_stitch(Cursor, data, idata); } } insert_status = SQL_INSERT_PRO_RATING; } if (insert_status == SQL_INSERT_PRO_RATING) { if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) { if ((basetime + timeslot) < data->time_end.tv_sec) { basetime += timeslot; goto new_timeslot; } } } if (insert_status == SQL_INSERT_SAFE_ACTION) { safe_action: Log(LOG_INFO, "INFO ( %s/%s ): Finished cache entries (ie. sql_cache_entries). Purging.\n", config.name, config.type); if (sql_qq_ptr) sql_cache_flush(sql_queries_queue, sql_qq_ptr, idata, FALSE); dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) { switch (ret = fork()) { case 0: /* Child */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); pm_setproctitle("%s [%s]", "SQL Plugin -- DB Writer (urgent)", config.name); config.is_forked = TRUE; if (sql_qq_ptr) { if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p); (*sqlfunc_cbr.connect)(&p, config.sql_host); (*sqlfunc_cbr.purge)(sql_queries_queue, sql_qq_ptr, idata); (*sqlfunc_cbr.close)(&bed); } exit_gracefully(0); default: /* Parent */ if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork DB writer (urgent): %s\n", config.name, config.type, strerror(errno)); else dump_writers_add(ret); break; } } else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); sql_qq_ptr = sql_pqq_ptr; memcpy(sql_queries_queue, sql_pending_queries_queue, sizeof(*sql_queries_queue)); if (SafePtr) { sql_queries_queue[sql_qq_ptr] = Cursor; sql_qq_ptr++; } else { Cursor = &sql_cache[idata->modulo]; goto start; } } } void sql_sum_host_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; struct host_addr tmp; memcpy(&tmp, &data->primitives.dst_ip, HostAddrSz); memset(&data->primitives.dst_ip, 0, HostAddrSz); sql_cache_insert(prim_ptrs, idata); memcpy(&data->primitives.src_ip, &tmp, HostAddrSz); sql_cache_insert(prim_ptrs, idata); } void sql_sum_port_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; u_int16_t port; port = data->primitives.dst_port; data->primitives.dst_port = 0; sql_cache_insert(prim_ptrs, idata); data->primitives.src_port = port; sql_cache_insert(prim_ptrs, idata); } void sql_sum_as_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; as_t asn; asn = data->primitives.dst_as; data->primitives.dst_as = 0; sql_cache_insert(prim_ptrs, idata); data->primitives.src_as = asn; sql_cache_insert(prim_ptrs, idata); } #if defined (HAVE_L2) void sql_sum_mac_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata) { struct pkt_data *data = prim_ptrs->data; u_char macaddr[ETH_ADDR_LEN]; memcpy(macaddr, &data->primitives.eth_dhost, ETH_ADDR_LEN); memset(data->primitives.eth_dhost, 0, ETH_ADDR_LEN); sql_cache_insert(prim_ptrs, idata); memcpy(&data->primitives.eth_shost, macaddr, ETH_ADDR_LEN); sql_cache_insert(prim_ptrs, idata); } #endif int sql_trigger_exec(char *filename) { char *args[2] = { filename, NULL }; int pid; #ifdef HAVE_VFORK switch (pid = vfork()) { #else switch (pid = fork()) { #endif case -1: return -1; case 0: execv(filename, args); _exit(0); } return 0; } void sql_db_ok(struct DBdesc *db) { db->fail = FALSE; db->connected = TRUE; } void sql_db_fail(struct DBdesc *db) { db->fail = TRUE; db->connected = FALSE; } void sql_db_errmsg(struct DBdesc *db) { if (db->type == BE_TYPE_PRIMARY) Log(LOG_ERR, "ERROR ( %s/%s ): PRIMARY '%s' backend trouble.\n", config.name, config.type, config.type); else if (db->type == BE_TYPE_BACKUP) Log(LOG_ERR, "ERROR ( %s/%s ): BACKUP '%s' backend trouble.\n", config.name, config.type, config.type); if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): The SQL server says: %s\n", config.name, config.type, db->errmsg); } void sql_db_warnmsg(struct DBdesc *db) { if (db->errmsg) Log(LOG_WARNING, "WARN ( %s/%s ): The SQL server says: %s\n", config.name, config.type, db->errmsg); } void sql_exit_gracefully(int signum) { struct insert_data idata; signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); Log(LOG_DEBUG, "( %s/%s ) *** Purging queries queue ***\n", config.name, config.type); if (config.syslog) closelog(); memset(&idata, 0, sizeof(idata)); idata.num_primitives = glob_num_primitives; idata.now = time(NULL); idata.basetime = glob_basetime; idata.dyn_table = glob_dyn_table; idata.dyn_table_time_only = glob_dyn_table_time_only; idata.new_basetime = glob_new_basetime; idata.timeslot = glob_timeslot; idata.committed_basetime = glob_committed_basetime; if (config.sql_backup_host) idata.recover = TRUE; if (config.sql_locking_style) idata.locks = sql_select_locking_style(config.sql_locking_style); sql_cache_flush(sql_queries_queue, sql_qq_ptr, &idata, TRUE); dump_writers_count(); if (dump_writers_get_flags() != CHLD_ALERT) { if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p); (*sqlfunc_cbr.connect)(&p, config.sql_host); (*sqlfunc_cbr.purge)(sql_queries_queue, sql_qq_ptr, &idata); (*sqlfunc_cbr.close)(&bed); } else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active()); if (config.pidfile) remove_pid_file(config.pidfile); exit_gracefully(0); } int sql_evaluate_primitives(int primitive) { pm_cfgreg_t what_to_count = 0, what_to_count_2 = 0, fakes = 0; short int assume_custom_table = FALSE; char *insert_clause_start_ptr = insert_clause + strlen(insert_clause); char default_delim[] = ",", delim_buf[SRVBUFLEN]; /* SQL tables < v6 multiplex IP addresses and AS numbers on the same field, thus are unable to use both them for a same direction (ie. src, dst). Tables v6 break such assumption */ if (((config.what_to_count & (COUNT_SRC_HOST|COUNT_SRC_NET|COUNT_SUM_HOST|COUNT_SUM_NET) && config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) || (config.what_to_count & COUNT_DST_AS && config.what_to_count & (COUNT_DST_HOST|COUNT_DST_NET))) && config.sql_table_version < 6) { Log(LOG_ERR, "ERROR ( %s/%s ): SQL tables < v6 are unable to mix IP addresses and AS numbers (ie. src_ip, src_as).\n", config.name, config.type); exit_gracefully(1); } if (config.sql_optimize_clauses) { what_to_count = config.what_to_count; what_to_count_2 = config.what_to_count_2; assume_custom_table = TRUE; } else { /* It is being requested to avoid SQL query optmization; then we will build an all-true bitmap */ if (config.what_to_count & COUNT_SRC_MAC) what_to_count |= COUNT_SRC_MAC; else if (config.what_to_count & COUNT_SUM_MAC) what_to_count |= COUNT_SUM_MAC; else fakes |= FAKE_SRC_MAC; if (config.what_to_count & COUNT_DST_MAC) what_to_count |= COUNT_DST_MAC; else fakes |= FAKE_DST_MAC; if (config.what_to_count & COUNT_SUM_PORT) what_to_count |= COUNT_SUM_PORT; what_to_count |= COUNT_SRC_PORT|COUNT_DST_PORT|COUNT_TCPFLAGS|COUNT_IP_PROTO|COUNT_CLASS|COUNT_VLAN|COUNT_IP_TOS; if (config.what_to_count & COUNT_SRC_HOST) what_to_count |= COUNT_SRC_HOST; else if (config.what_to_count & COUNT_SUM_HOST) what_to_count |= COUNT_SUM_HOST; else if (config.what_to_count & COUNT_SUM_NET) what_to_count |= COUNT_SUM_NET; else fakes |= FAKE_SRC_HOST; if (config.what_to_count & COUNT_SRC_NET) what_to_count |= COUNT_SRC_NET; if (config.what_to_count & COUNT_DST_HOST) what_to_count |= COUNT_DST_HOST; else fakes |= FAKE_DST_HOST; if (config.what_to_count & COUNT_DST_NET) what_to_count |= COUNT_DST_NET; if (config.what_to_count & COUNT_AS_PATH) what_to_count |= COUNT_AS_PATH; else fakes |= FAKE_AS_PATH; if (config.what_to_count & COUNT_SRC_AS_PATH) what_to_count |= COUNT_SRC_AS_PATH; if (config.what_to_count & COUNT_STD_COMM) what_to_count |= COUNT_STD_COMM; else if (config.what_to_count & COUNT_EXT_COMM) what_to_count |= COUNT_EXT_COMM; else fakes |= FAKE_COMMS; if (config.what_to_count & COUNT_SRC_STD_COMM) what_to_count |= COUNT_SRC_STD_COMM; else if (config.what_to_count & COUNT_SRC_EXT_COMM) what_to_count |= COUNT_SRC_EXT_COMM; if (config.what_to_count & COUNT_PEER_SRC_AS) what_to_count |= COUNT_PEER_SRC_AS; else fakes |= FAKE_PEER_SRC_AS; if (config.what_to_count & COUNT_PEER_DST_AS) what_to_count |= COUNT_PEER_DST_AS; else fakes |= FAKE_PEER_DST_AS; if (config.what_to_count & COUNT_PEER_SRC_IP) what_to_count |= COUNT_PEER_SRC_IP; else fakes |= FAKE_PEER_SRC_IP; if (config.what_to_count & COUNT_PEER_DST_IP) what_to_count |= COUNT_PEER_DST_IP; else fakes |= FAKE_PEER_DST_IP; what_to_count |= COUNT_LOCAL_PREF|COUNT_MED; if (config.what_to_count & COUNT_SRC_LOCAL_PREF) what_to_count |= COUNT_SRC_LOCAL_PREF; if (config.what_to_count & COUNT_SRC_MED) what_to_count |= COUNT_SRC_MED; if (config.what_to_count_2 & COUNT_SRC_ROA) what_to_count_2 |= COUNT_SRC_ROA; if (config.what_to_count_2 & COUNT_DST_ROA) what_to_count_2 |= COUNT_DST_ROA; if (config.sql_table_version < 6) { if (config.what_to_count & COUNT_SRC_AS) what_to_count |= COUNT_SRC_AS; else if (config.what_to_count & COUNT_SUM_AS) what_to_count |= COUNT_SUM_AS; else fakes |= FAKE_SRC_AS; } else { what_to_count |= COUNT_SRC_AS; if (config.what_to_count & COUNT_SUM_AS) what_to_count |= COUNT_SUM_AS; } if (config.sql_table_version < 6) { if (config.what_to_count & COUNT_DST_AS) what_to_count |= COUNT_DST_AS; else fakes |= FAKE_DST_AS; } else what_to_count |= COUNT_DST_AS; if (config.sql_table_version < 6) { if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) { if (fakes & FAKE_SRC_HOST) fakes ^= FAKE_SRC_HOST; } else { if (fakes & FAKE_SRC_AS) fakes ^= FAKE_SRC_AS; } if (what_to_count & COUNT_DST_AS) { if (fakes & FAKE_DST_HOST) fakes ^= FAKE_DST_HOST; } else { if (fakes & FAKE_DST_AS) fakes ^= FAKE_DST_AS; } } what_to_count |= COUNT_TAG; /* aggregation primitives listed below are not part of any default SQL schema; hence no matter if SQL statements optimization is enabled or not, they have to be passed on blindly */ if (config.what_to_count & COUNT_TAG2) what_to_count |= COUNT_TAG2; if (config.what_to_count & COUNT_COS) what_to_count |= COUNT_COS; if (config.what_to_count & COUNT_ETHERTYPE) what_to_count |= COUNT_ETHERTYPE; if (config.what_to_count & COUNT_MPLS_VPN_RD) what_to_count |= COUNT_MPLS_VPN_RD; if (config.what_to_count & COUNT_IN_IFACE) what_to_count |= COUNT_IN_IFACE; if (config.what_to_count & COUNT_OUT_IFACE) what_to_count |= COUNT_OUT_IFACE; if (config.what_to_count & COUNT_SRC_NMASK) what_to_count |= COUNT_SRC_NMASK; if (config.what_to_count & COUNT_DST_NMASK) what_to_count |= COUNT_DST_NMASK; #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) what_to_count_2 |= COUNT_SRC_HOST_COUNTRY; if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) what_to_count_2 |= COUNT_DST_HOST_COUNTRY; #endif #if defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) what_to_count_2 |= COUNT_SRC_HOST_POCODE; if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) what_to_count_2 |= COUNT_DST_HOST_POCODE; if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) what_to_count_2 |= COUNT_SRC_HOST_COORDS; if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) what_to_count_2 |= COUNT_DST_HOST_COORDS; #endif if (config.what_to_count_2 & COUNT_SAMPLING_RATE) what_to_count_2 |= COUNT_SAMPLING_RATE; if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) what_to_count_2 |= COUNT_POST_NAT_SRC_HOST; if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) what_to_count_2 |= COUNT_POST_NAT_DST_HOST; if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) what_to_count_2 |= COUNT_POST_NAT_SRC_PORT; if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) what_to_count_2 |= COUNT_POST_NAT_DST_PORT; if (config.what_to_count_2 & COUNT_NAT_EVENT) what_to_count_2 |= COUNT_NAT_EVENT; if (config.what_to_count_2 & COUNT_FW_EVENT) what_to_count_2 |= COUNT_FW_EVENT; if (config.what_to_count_2 & COUNT_FWD_STATUS) what_to_count_2 |= COUNT_FWD_STATUS; if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) what_to_count_2 |= COUNT_MPLS_LABEL_TOP; if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) what_to_count_2 |= COUNT_MPLS_LABEL_BOTTOM; if (config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) what_to_count_2 |= COUNT_MPLS_LABEL_STACK; if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) what_to_count_2 |= COUNT_TUNNEL_SRC_MAC; if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) what_to_count_2 |= COUNT_TUNNEL_DST_MAC; if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) what_to_count_2 |= COUNT_TUNNEL_SRC_HOST; if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) what_to_count_2 |= COUNT_TUNNEL_DST_HOST; if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) what_to_count_2 |= COUNT_TUNNEL_IP_PROTO; if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) what_to_count_2 |= COUNT_TUNNEL_IP_TOS; if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) what_to_count_2 |= COUNT_TUNNEL_SRC_PORT; if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) what_to_count_2 |= COUNT_TUNNEL_DST_PORT; if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) what_to_count_2 |= COUNT_TUNNEL_TCPFLAGS; if (config.what_to_count_2 & COUNT_TIMESTAMP_START) what_to_count_2 |= COUNT_TIMESTAMP_START; if (config.what_to_count_2 & COUNT_TIMESTAMP_END) what_to_count_2 |= COUNT_TIMESTAMP_END; if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) what_to_count_2 |= COUNT_TIMESTAMP_ARRIVAL; if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) what_to_count_2 |= COUNT_EXPORT_PROTO_SEQNO; if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) what_to_count_2 |= COUNT_EXPORT_PROTO_VERSION; if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) what_to_count_2 |= COUNT_EXPORT_PROTO_SYSID; if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) what_to_count_2 |= COUNT_EXPORT_PROTO_TIME; if (config.what_to_count_2 & COUNT_LABEL) what_to_count_2 |= COUNT_LABEL; #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) what_to_count_2 |= COUNT_NDPI_CLASS; #endif } /* sorting out delimiter */ if (!config.sql_delimiter || !config.sql_use_copy) snprintf(delim_buf, SRVBUFLEN, "%s ", default_delim); else snprintf(delim_buf, SRVBUFLEN, "%s ", config.sql_delimiter); /* 1st part: arranging pointers to an opaque structure and composing the static selection (WHERE) string */ #if defined (HAVE_L2) if (what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): MAC accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mac_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mac_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_MAC; values[primitive].handler = where[primitive].handler = count_src_mac_handler; primitive++; } } if (what_to_count & COUNT_DST_MAC) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): MAC accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mac_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mac_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_MAC; values[primitive].handler = where[primitive].handler = count_dst_mac_handler; primitive++; } } if ((what_to_count & COUNT_VLAN) && config.tmp_vlan_legacy) { int count_it = FALSE; if ((config.sql_table_version < 2 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_VLAN) { Log(LOG_ERR, "ERROR ( %s/%s ): VLAN accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_VLAN; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "vlan", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "vlan=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_VLAN; values[primitive].handler = where[primitive].handler = count_vlan_handler; primitive++; } } if ((what_to_count & COUNT_VLAN) && !config.tmp_vlan_legacy) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "vlan_in", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "vlan_in=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_VLAN; values[primitive].handler = where[primitive].handler = count_vlan_handler; primitive++; } if (what_to_count_2 & COUNT_OUT_VLAN) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "vlan_out", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "vlan_out=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_OUT_VLAN; values[primitive].handler = where[primitive].handler = count_out_vlan_handler; primitive++; } if (what_to_count & COUNT_COS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "cos", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "cos=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_COS; values[primitive].handler = where[primitive].handler = count_cos_handler; primitive++; } if (what_to_count & COUNT_ETHERTYPE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "etype", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%x\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "etype=\'%x\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_ETHERTYPE; values[primitive].handler = where[primitive].handler = count_etype_handler; primitive++; } #endif if (what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): IP host accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST; values[primitive].handler = where[primitive].handler = count_src_host_aton_handler; primitive++; } else { strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST; values[primitive].handler = where[primitive].handler = count_src_host_handler; primitive++; } } } if (what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "net_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "net_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_NET; values[primitive].handler = where[primitive].handler = count_src_net_aton_handler; primitive++; } else { strncat(insert_clause, "net_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "net_src=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_NET; values[primitive].handler = where[primitive].handler = count_src_net_handler; primitive++; } } if (what_to_count & COUNT_DST_HOST) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): IP host accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST; values[primitive].handler = where[primitive].handler = count_dst_host_aton_handler; primitive++; } else { strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST; values[primitive].handler = where[primitive].handler = count_dst_host_handler; primitive++; } } } if (what_to_count & COUNT_DST_NET) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "net_dst", SPACELEFT(insert_clause)); strncat(where[primitive].string, "net_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_NET; values[primitive].handler = where[primitive].handler = count_dst_net_aton_handler; primitive++; } else { strncat(insert_clause, "net_dst", SPACELEFT(insert_clause)); strncat(where[primitive].string, "net_dst=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_NET; values[primitive].handler = where[primitive].handler = count_dst_net_handler; primitive++; } } if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if (config.sql_table_version >= 6) { strncat(insert_clause, "as_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "as_src=%u", SPACELEFT(where[primitive].string)); } else { strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") || (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) { strncat(values[primitive].string, "\'%u\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=\'%u\'", SPACELEFT(where[primitive].string)); } else { strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=%u", SPACELEFT(where[primitive].string)); } } values[primitive].type = where[primitive].type = COUNT_INT_SRC_AS; values[primitive].handler = where[primitive].handler = count_src_as_handler; primitive++; } if (what_to_count & COUNT_IN_IFACE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "iface_in", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "iface_in=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_IN_IFACE; values[primitive].handler = where[primitive].handler = count_in_iface_handler; primitive++; } if (what_to_count & COUNT_OUT_IFACE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "iface_out", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "iface_out=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_OUT_IFACE; values[primitive].handler = where[primitive].handler = count_out_iface_handler; primitive++; } if (what_to_count & COUNT_SRC_NMASK) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mask_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mask_src=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_NMASK; values[primitive].handler = where[primitive].handler = count_src_nmask_handler; primitive++; } if (what_to_count & COUNT_DST_NMASK) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mask_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mask_dst=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_NMASK; values[primitive].handler = where[primitive].handler = count_dst_nmask_handler; primitive++; } if (what_to_count & COUNT_DST_AS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if (config.sql_table_version >= 6) { strncat(insert_clause, "as_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "as_dst=%u", SPACELEFT(where[primitive].string)); } else { strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") || (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) { strncat(values[primitive].string, "\'%u\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=\'%u\'", SPACELEFT(where[primitive].string)); } else { strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=%u", SPACELEFT(where[primitive].string)); } } values[primitive].type = where[primitive].type = COUNT_INT_DST_AS; values[primitive].handler = where[primitive].handler = count_dst_as_handler; primitive++; } if (what_to_count & COUNT_STD_COMM) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "comms", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "comms=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_STD_COMM; values[primitive].handler = where[primitive].handler = count_std_comm_handler; primitive++; } } if (what_to_count & COUNT_EXT_COMM) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "ecomms", SPACELEFT(insert_clause)); strncat(where[primitive].string, "ecomms=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_EXT_COMM; values[primitive].handler = where[primitive].handler = count_ext_comm_handler; primitive++; } } if (what_to_count_2 & COUNT_LRG_COMM) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "lcomms", SPACELEFT(insert_clause)); strncat(where[primitive].string, "lcomms=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_LRG_COMM; values[primitive].handler = where[primitive].handler = count_lrg_comm_handler; primitive++; } if (what_to_count & COUNT_SRC_STD_COMM) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "comms_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "comms_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_STD_COMM; values[primitive].handler = where[primitive].handler = count_src_std_comm_handler; primitive++; } if (what_to_count & COUNT_SRC_EXT_COMM) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "ecomms_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "ecomms_src=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_EXT_COMM; values[primitive].handler = where[primitive].handler = count_src_ext_comm_handler; primitive++; } if (what_to_count_2 & COUNT_SRC_LRG_COMM) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "lcomms_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "lcomms_src=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_LRG_COMM; values[primitive].handler = where[primitive].handler = count_src_lrg_comm_handler; primitive++; } if (what_to_count & COUNT_AS_PATH) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "as_path", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "as_path=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_AS_PATH; values[primitive].handler = where[primitive].handler = count_as_path_handler; primitive++; } } if (what_to_count & COUNT_SRC_AS_PATH) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "as_path_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "as_path_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_AS_PATH; values[primitive].handler = where[primitive].handler = count_src_as_path_handler; primitive++; } if (what_to_count & COUNT_LOCAL_PREF) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_LOCAL_PREF) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_LOCAL_PREF; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "local_pref", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "local_pref=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_LOCAL_PREF; values[primitive].handler = where[primitive].handler = count_local_pref_handler; primitive++; } } if (what_to_count & COUNT_SRC_LOCAL_PREF) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "local_pref_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "local_pref_src=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_LOCAL_PREF; values[primitive].handler = where[primitive].handler = count_src_local_pref_handler; primitive++; } if (what_to_count & COUNT_MED) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_MED) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_MED; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "med", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "med=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MED; values[primitive].handler = where[primitive].handler = count_med_handler; primitive++; } } if (what_to_count & COUNT_SRC_MED) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "med_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "med_src=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_MED; values[primitive].handler = where[primitive].handler = count_src_med_handler; primitive++; } if (what_to_count_2 & COUNT_SRC_ROA) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "roa_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "roa_src=%s", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_ROA; values[primitive].handler = where[primitive].handler = count_src_roa_handler; primitive++; } if (what_to_count_2 & COUNT_DST_ROA) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "roa_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "roa_dst=%s", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_ROA; values[primitive].handler = where[primitive].handler = count_dst_roa_handler; primitive++; } if (what_to_count & COUNT_MPLS_VPN_RD) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mpls_vpn_rd", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mpls_vpn_rd=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MPLS_VPN_RD; values[primitive].handler = where[primitive].handler = count_mpls_vpn_rd_handler; primitive++; } if (what_to_count_2 & COUNT_MPLS_PW_ID) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mpls_pw_id", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mpls_pw_id=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MPLS_PW_ID; values[primitive].handler = where[primitive].handler = count_mpls_pw_id_handler; primitive++; } if (what_to_count & COUNT_PEER_SRC_AS) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "peer_as_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_as_src=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_AS; values[primitive].handler = where[primitive].handler = count_peer_src_as_handler; primitive++; } } if (what_to_count & COUNT_PEER_DST_AS) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "peer_as_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_as_dst=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_AS; values[primitive].handler = where[primitive].handler = count_peer_dst_as_handler; primitive++; } } if (what_to_count & COUNT_PEER_SRC_IP) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_IP; values[primitive].handler = where[primitive].handler = count_peer_src_ip_aton_handler; primitive++; } else { strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_IP; values[primitive].handler = where[primitive].handler = count_peer_src_ip_handler; primitive++; } } } if (what_to_count & COUNT_PEER_DST_IP) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_IP; values[primitive].handler = where[primitive].handler = count_peer_dst_ip_aton_handler; primitive++; } else { strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_IP; values[primitive].handler = where[primitive].handler = count_peer_dst_ip_handler; primitive++; } } } if (what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) { Log(LOG_ERR, "ERROR ( %s/%s ): TCP/UDP port accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else { if (what_to_count & COUNT_SRC_PORT) what_to_count ^= COUNT_SRC_PORT; if (what_to_count & COUNT_SUM_PORT) what_to_count ^= COUNT_SUM_PORT; } } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3")) && (config.sql_table_version < 8 || (config.sql_table_version >= SQL_TABLE_VERSION_BGP && config.sql_table_version < SQL_TABLE_VERSION_BGP+8))) { strncat(insert_clause, "src_port", SPACELEFT(insert_clause)); strncat(where[primitive].string, "src_port=%u", SPACELEFT(where[primitive].string)); } else { strncat(insert_clause, "port_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "port_src=%u", SPACELEFT(where[primitive].string)); } strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_PORT; values[primitive].handler = where[primitive].handler = count_src_port_handler; primitive++; } } if (what_to_count & COUNT_DST_PORT) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_DST_PORT) { Log(LOG_ERR, "ERROR ( %s/%s ): TCP/UDP port accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_DST_PORT; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3")) && (config.sql_table_version < 8 || (config.sql_table_version >= SQL_TABLE_VERSION_BGP && config.sql_table_version < SQL_TABLE_VERSION_BGP+8))) { strncat(insert_clause, "dst_port", SPACELEFT(insert_clause)); strncat(where[primitive].string, "dst_port=%u", SPACELEFT(where[primitive].string)); } else { strncat(insert_clause, "port_dst", SPACELEFT(insert_clause)); strncat(where[primitive].string, "port_dst=%u", SPACELEFT(where[primitive].string)); } strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_PORT; values[primitive].handler = where[primitive].handler = count_dst_port_handler; primitive++; } } if (what_to_count & COUNT_TCPFLAGS) { int count_it = FALSE; if ((config.sql_table_version < 7 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_TCPFLAGS) { Log(LOG_ERR, "ERROR ( %s/%s ): TCP flags accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_TCPFLAGS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); } strncat(insert_clause, "tcp_flags", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TCPFLAGS; values[primitive].handler = where[primitive].handler = count_tcpflags_handler; primitive++; } } if (what_to_count & COUNT_IP_TOS) { int count_it = FALSE; if ((config.sql_table_version < 3 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_IP_TOS) { Log(LOG_ERR, "ERROR ( %s/%s ): IP ToS accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_IP_TOS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tos", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tos=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_IP_TOS; values[primitive].handler = where[primitive].handler = count_ip_tos_handler; primitive++; } } if (what_to_count & COUNT_IP_PROTO) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_IP_PROTO) { Log(LOG_ERR, "ERROR ( %s/%s ): IP proto accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_IP_PROTO; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "ip_proto", SPACELEFT(insert_clause)); if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && !config.num_protos) { strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_proto=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].handler = where[primitive].handler = MY_count_ip_proto_handler; } else { strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_proto=%u", SPACELEFT(where[primitive].string)); values[primitive].handler = where[primitive].handler = PG_count_ip_proto_handler; } values[primitive].type = where[primitive].type = COUNT_INT_IP_PROTO; primitive++; } } #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_COUNTRY) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "country_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "country_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_COUNTRY; values[primitive].handler = where[primitive].handler = count_src_host_country_handler; primitive++; } if (what_to_count_2 & COUNT_DST_HOST_COUNTRY) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "country_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "country_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_COUNTRY; values[primitive].handler = where[primitive].handler = count_dst_host_country_handler; primitive++; } #endif #if defined (WITH_GEOIPV2) if (what_to_count_2 & COUNT_SRC_HOST_POCODE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "pocode_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "pocode_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_POCODE; values[primitive].handler = where[primitive].handler = count_src_host_pocode_handler; primitive++; } if (what_to_count_2 & COUNT_DST_HOST_POCODE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "pocode_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "pocode_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_POCODE; values[primitive].handler = where[primitive].handler = count_dst_host_pocode_handler; primitive++; } if (what_to_count_2 & COUNT_SRC_HOST_COORDS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "lat_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "lat_ip_src=\'%f\'", SPACELEFT(where[primitive].string)); strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "lon_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "lon_ip_src=\'%f\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_COORDS; values[primitive].handler = where[primitive].handler = count_src_host_coords_handler; primitive++; } if (what_to_count_2 & COUNT_DST_HOST_COORDS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "lat_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "lat_ip_dst=\'%f\'", SPACELEFT(where[primitive].string)); strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "lon_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "lon_ip_dst=\'%f\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_COORDS; values[primitive].handler = where[primitive].handler = count_dst_host_coords_handler; primitive++; } #endif if (what_to_count_2 & COUNT_SAMPLING_RATE) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "sampling_rate", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "sampling_rate=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SAMPLING_RATE; values[primitive].handler = where[primitive].handler = count_sampling_rate_handler; primitive++; } if (what_to_count_2 & COUNT_SAMPLING_DIRECTION) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "sampling_direction", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "sampling_direction=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_SAMPLING_DIRECTION; values[primitive].handler = where[primitive].handler = count_sampling_direction_handler; primitive++; } if (what_to_count_2 & COUNT_POST_NAT_SRC_HOST) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "post_nat_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "post_nat_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_HOST; values[primitive].handler = where[primitive].handler = count_post_nat_src_ip_aton_handler; primitive++; } else { strncat(insert_clause, "post_nat_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "post_nat_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_HOST; values[primitive].handler = where[primitive].handler = count_post_nat_src_ip_handler; primitive++; } } if (what_to_count_2 & COUNT_POST_NAT_DST_HOST) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "post_nat_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "post_nat_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_HOST; values[primitive].handler = where[primitive].handler = count_post_nat_dst_ip_aton_handler; primitive++; } else { strncat(insert_clause, "post_nat_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "post_nat_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_HOST; values[primitive].handler = where[primitive].handler = count_post_nat_dst_ip_handler; primitive++; } } if (what_to_count_2 & COUNT_POST_NAT_SRC_PORT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "post_nat_port_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "post_nat_port_src=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_PORT; values[primitive].handler = where[primitive].handler = count_post_nat_src_port_handler; primitive++; } if (what_to_count_2 & COUNT_POST_NAT_DST_PORT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "post_nat_port_dst", SPACELEFT(insert_clause)); strncat(where[primitive].string, "post_nat_port_dst=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_PORT; values[primitive].handler = where[primitive].handler = count_post_nat_dst_port_handler; primitive++; } if (what_to_count_2 & COUNT_NAT_EVENT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "nat_event", SPACELEFT(insert_clause)); strncat(where[primitive].string, "nat_event=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_NAT_EVENT; values[primitive].handler = where[primitive].handler = count_nat_event_handler; primitive++; } if (what_to_count_2 & COUNT_FW_EVENT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "fw_event", SPACELEFT(insert_clause)); strncat(where[primitive].string, "fw_event=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_FW_EVENT; values[primitive].handler = where[primitive].handler = count_fw_event_handler; primitive++; } if (what_to_count_2 & COUNT_FWD_STATUS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "fwd_status", SPACELEFT(insert_clause)); strncat(where[primitive].string, "fwd_status=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_FWD_STATUS; values[primitive].handler = where[primitive].handler = count_fwd_status_handler; primitive++; } if (what_to_count_2 & COUNT_MPLS_LABEL_TOP) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mpls_label_top", SPACELEFT(insert_clause)); strncat(where[primitive].string, "mpls_label_top=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MPLS_LABEL_TOP; values[primitive].handler = where[primitive].handler = count_mpls_label_top_handler; primitive++; } if (what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mpls_label_bottom", SPACELEFT(insert_clause)); strncat(where[primitive].string, "mpls_label_bottom=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MPLS_LABEL_BOTTOM; values[primitive].handler = where[primitive].handler = count_mpls_label_bottom_handler; primitive++; } if (what_to_count_2 & COUNT_MPLS_LABEL_STACK) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mpls_label_stack", SPACELEFT(insert_clause)); strncat(where[primitive].string, "mpls_label_stack=%s", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_MPLS_LABEL_STACK; values[primitive].handler = where[primitive].handler = count_mpls_label_stack_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_SRC_MAC) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_mac_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_mac_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_MAC; values[primitive].handler = where[primitive].handler = count_tunnel_src_mac_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_DST_MAC) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_mac_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_mac_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_MAC; values[primitive].handler = where[primitive].handler = count_tunnel_dst_mac_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_SRC_HOST) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "tunnel_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_HOST; values[primitive].handler = where[primitive].handler = count_tunnel_src_ip_aton_handler; primitive++; } else { strncat(insert_clause, "tunnel_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_HOST; values[primitive].handler = where[primitive].handler = count_tunnel_src_ip_handler; primitive++; } } if (what_to_count_2 & COUNT_TUNNEL_DST_HOST) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "tunnel_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_HOST; values[primitive].handler = where[primitive].handler = count_tunnel_dst_ip_aton_handler; primitive++; } else { strncat(insert_clause, "tunnel_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_HOST; values[primitive].handler = where[primitive].handler = count_tunnel_dst_ip_handler; primitive++; } } if (what_to_count_2 & COUNT_TUNNEL_IP_PROTO) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_ip_proto", SPACELEFT(insert_clause)); if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && !config.num_protos) { strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_proto=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].handler = where[primitive].handler = MY_count_tunnel_ip_proto_handler; } else { strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_ip_proto=%u", SPACELEFT(where[primitive].string)); values[primitive].handler = where[primitive].handler = PG_count_tunnel_ip_proto_handler; } values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_IP_PROTO; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_IP_TOS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_tos", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tunnel_tos=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_IP_TOS; values[primitive].handler = where[primitive].handler = count_tunnel_ip_tos_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_SRC_PORT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_port_src", SPACELEFT(insert_clause)); strncat(where[primitive].string, "tunnel_port_src=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_PORT; values[primitive].handler = where[primitive].handler = count_tunnel_src_port_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_DST_PORT) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tunnel_port_dst", SPACELEFT(insert_clause)); strncat(where[primitive].string, "tunnel_port_dst=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_PORT; values[primitive].handler = where[primitive].handler = count_tunnel_dst_port_handler; primitive++; } if (what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); } strncat(insert_clause, "tunnel_tcp_flags", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_TCPFLAGS; values[primitive].handler = where[primitive].handler = count_tunnel_tcpflags_handler; primitive++; } if (what_to_count_2 & COUNT_VXLAN) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "vxlan", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "vxlan=%u", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_VXLAN; values[primitive].handler = where[primitive].handler = count_vxlan_handler; primitive++; } if (what_to_count_2 & COUNT_TIMESTAMP_START) { int use_copy=0; if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_start", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_start=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_start=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_start=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_start=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_start=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_start_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_start_handler; values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_START; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_start_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_start_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_START; values[primitive].handler = where[primitive].handler = count_timestamp_start_residual_handler; primitive++; } } if (what_to_count_2 & COUNT_TIMESTAMP_END) { int use_copy=0; if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_end", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_end=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_end=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_end=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_end=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_end=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_end_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_end_handler; values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_END; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_end_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_end_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_END; values[primitive].handler = where[primitive].handler = count_timestamp_end_residual_handler; primitive++; } } if (what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) { int use_copy=0; if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_arrival", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_arrival=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_arrival=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_arrival=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_arrival=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_arrival=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_arrival_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_arrival_handler; values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_ARRIVAL; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_arrival_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_arrival_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_ARRIVAL; values[primitive].handler = where[primitive].handler = count_timestamp_arrival_residual_handler; primitive++; } } if (what_to_count_2 & COUNT_EXPORT_PROTO_TIME) { int use_copy=0; if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_export", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_export=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_export=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_export=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_export=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_export=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_export_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_export_handler; values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_TIME; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_export_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_export_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_TIME; values[primitive].handler = where[primitive].handler = count_timestamp_export_residual_handler; primitive++; } } if (config.nfacctd_stitching) { int use_copy=0; /* timestamp_min */ if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_min", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_min=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_min=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_min=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_min=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_min=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_min_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_min_handler; values[primitive].type = where[primitive].type = FALSE; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_min_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_min_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = FALSE; values[primitive].handler = where[primitive].handler = count_timestamp_min_residual_handler; primitive++; } /* timestamp_max */ if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "timestamp_max", SPACELEFT(insert_clause)); if (config.timestamps_since_epoch) { strncat(where[primitive].string, "timestamp_max=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); } else { if (!strcmp(config.type, "mysql")) { strncat(where[primitive].string, "timestamp_max=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string)); } else if (!strcmp(config.type, "pgsql")) { if (config.sql_use_copy) { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); use_copy = TRUE; } else { strncat(where[primitive].string, "timestamp_max=to_timestamp(%u)", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string)); } } else if (!strcmp(config.type, "sqlite3")) { if (!config.timestamps_utc) { strncat(where[primitive].string, "timestamp_max=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "timestamp_max=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string)); } } } if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_max_handler; else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_max_handler; values[primitive].type = where[primitive].type = FALSE; primitive++; if (!config.timestamps_secs) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); strncat(insert_clause, "timestamp_max_residual", SPACELEFT(insert_clause)); strncat(where[primitive].string, "timestamp_max_residual=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = FALSE; values[primitive].handler = where[primitive].handler = count_timestamp_max_residual_handler; primitive++; } } if (what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "export_proto_seqno", SPACELEFT(insert_clause)); strncat(where[primitive].string, "export_proto_seqno=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_export_proto_seqno_handler; values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_SEQNO; primitive++; } if (what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "export_proto_version", SPACELEFT(insert_clause)); strncat(where[primitive].string, "export_proto_version=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_export_proto_version_handler; values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_VERSION; primitive++; } if (what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "export_proto_sysid", SPACELEFT(insert_clause)); strncat(where[primitive].string, "export_proto_sysid=%u", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string)); values[primitive].handler = where[primitive].handler = count_export_proto_sysid_handler; values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_SYSID; primitive++; } /* all custom primitives printed here */ { struct custom_primitive_ptrs *cp_entry; int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } cp_entry = &config.cpptrs.primitive[cp_idx]; strncat(insert_clause, cp_entry->name, SPACELEFT(insert_clause)); strncat(where[primitive].string, cp_entry->name, SPACELEFT(where[primitive].string)); if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT) { strncat(where[primitive].string, "=%s", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); } else { strncat(where[primitive].string, "=\'%s\'", SPACELEFT(where[primitive].string)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); } values[primitive].type = where[primitive].type = COUNT_INT_CUSTOM_PRIMITIVES; values[primitive].handler = where[primitive].handler = count_custom_primitives_handler; primitive++; } } if (what_to_count & COUNT_TAG) { int count_it = FALSE; if ((config.sql_table_version < 2) && !assume_custom_table) { if (config.what_to_count & COUNT_TAG) { Log(LOG_ERR, "ERROR ( %s/%s ): Tag/ID accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_TAG; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if (config.sql_table_version < 9 || (config.sql_table_version >= SQL_TABLE_VERSION_BGP && config.sql_table_version < SQL_TABLE_VERSION_BGP+9)) { strncat(insert_clause, "agent_id", SPACELEFT(insert_clause)); strncat(where[primitive].string, "agent_id=%llu", SPACELEFT(where[primitive].string)); } else { strncat(insert_clause, "tag", SPACELEFT(insert_clause)); strncat(where[primitive].string, "tag=%llu", SPACELEFT(where[primitive].string)); } strncat(values[primitive].string, "%llu", SPACELEFT(values[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TAG; values[primitive].handler = where[primitive].handler = count_tag_handler; primitive++; } } if (what_to_count & COUNT_TAG2) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "tag2", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%llu", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "tag2=%llu", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_TAG2; values[primitive].handler = where[primitive].handler = count_tag2_handler; primitive++; } if (what_to_count_2 & COUNT_LABEL) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "label", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "label=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_LABEL; values[primitive].handler = where[primitive].handler = count_label_handler; primitive++; } if (what_to_count & COUNT_CLASS) { int count_it = FALSE; if ((config.sql_table_version < 5 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { if (config.what_to_count & COUNT_CLASS) { Log(LOG_ERR, "ERROR ( %s/%s ): L7 classification accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type); exit_gracefully(1); } else what_to_count ^= COUNT_CLASS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "class_id", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "class_id=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_CLASS; values[primitive].handler = where[primitive].handler = count_class_id_handler; primitive++; } } #if defined (WITH_NDPI) if (what_to_count_2 & COUNT_NDPI_CLASS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "class", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "class=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = COUNT_INT_CLASS; values[primitive].handler = where[primitive].handler = count_ndpi_class_handler; primitive++; } #endif #if defined (HAVE_L2) if (fakes & FAKE_SRC_MAC) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_SRC_MAC; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mac_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mac_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_SRC_MAC; values[primitive].handler = where[primitive].handler = fake_mac_handler; primitive++; } } if (fakes & FAKE_DST_MAC) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_DST_MAC; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "mac_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "mac_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_DST_MAC; values[primitive].handler = where[primitive].handler = fake_mac_handler; primitive++; } } #endif if (fakes & FAKE_SRC_HOST) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_SRC_HOST; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_SRC_HOST; values[primitive].handler = where[primitive].handler = fake_host_aton_handler; primitive++; } else { strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_SRC_HOST; values[primitive].handler = where[primitive].handler = fake_host_handler; primitive++; } } } if (fakes & FAKE_DST_HOST) { int count_it = FALSE; if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_DST_HOST; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_DST_HOST; values[primitive].handler = where[primitive].handler = fake_host_aton_handler; primitive++; } else { strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_DST_HOST; values[primitive].handler = where[primitive].handler = fake_host_handler; primitive++; } } } if (fakes & FAKE_SRC_AS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "ip_src", SPACELEFT(insert_clause)); if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") || (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) { strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string)); } else { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_src=%s", SPACELEFT(where[primitive].string)); } values[primitive].type = where[primitive].type = FAKE_SRC_AS; values[primitive].handler = where[primitive].handler = fake_as_handler; primitive++; } if (fakes & FAKE_DST_AS) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause)); if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") || (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) { strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); } else { strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "ip_dst=%s", SPACELEFT(where[primitive].string)); } values[primitive].type = where[primitive].type = FAKE_DST_AS; values[primitive].handler = where[primitive].handler = fake_as_handler; primitive++; } if (fakes & FAKE_COMMS) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_COMMS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "comms", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "comms=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_COMMS; values[primitive].handler = where[primitive].handler = fake_comms_handler; primitive++; } } if (fakes & FAKE_AS_PATH) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_AS_PATH; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "as_path", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "as_path=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_AS_PATH; values[primitive].handler = where[primitive].handler = fake_as_path_handler; primitive++; } } if (fakes & FAKE_PEER_SRC_AS) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_PEER_SRC_AS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "peer_as_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_as_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_SRC_AS; values[primitive].handler = where[primitive].handler = fake_as_handler; primitive++; } } if (fakes & FAKE_PEER_DST_AS) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_PEER_DST_AS; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } strncat(insert_clause, "peer_as_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_as_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_DST_AS; values[primitive].handler = where[primitive].handler = fake_as_handler; primitive++; } } if (fakes & FAKE_PEER_SRC_IP) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_PEER_SRC_IP; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_SRC_IP; values[primitive].handler = where[primitive].handler = fake_host_aton_handler; primitive++; } else { strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_src=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_SRC_IP; values[primitive].handler = where[primitive].handler = fake_host_handler; primitive++; } } } if (fakes & FAKE_PEER_DST_IP) { int count_it = FALSE; if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) { fakes ^= FAKE_PEER_DST_IP; } else count_it = TRUE; if (count_it) { if (primitive) { strncat(insert_clause, ", ", SPACELEFT(insert_clause)); strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string)); strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string)); } if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) { strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_DST_IP; values[primitive].handler = where[primitive].handler = fake_host_aton_handler; primitive++; } else { strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause)); strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string)); strncat(where[primitive].string, "peer_ip_dst=\'%s\'", SPACELEFT(where[primitive].string)); values[primitive].type = where[primitive].type = FAKE_PEER_DST_IP; values[primitive].handler = where[primitive].handler = fake_host_handler; primitive++; } } } strncat(copy_clause, insert_clause_start_ptr, SPACELEFT(copy_clause)); return primitive; } int sql_query(struct BE_descs *bed, struct db_cache *elem, struct insert_data *idata) { if (!bed->p->fail && elem->valid == SQL_CACHE_COMMITTED) { if ((*sqlfunc_cbr.op)(bed->p, elem, idata)); /* failed */ else { idata->qn++; return FALSE; } } if ( elem->valid == SQL_CACHE_ERROR || (bed->p->fail && !(elem->valid == SQL_CACHE_INUSE)) ) { if (config.sql_backup_host) { if (!bed->b->fail) { if (!bed->b->connected) { (*sqlfunc_cbr.connect)(bed->b, config.sql_backup_host); if (config.sql_table_schema) { time_t stamp = idata->new_basetime ? idata->new_basetime : idata->basetime; sql_create_table(bed->b, &stamp, NULL); // XXX: should not be null } (*sqlfunc_cbr.lock)(bed->b); } if (!bed->b->fail) { if ((*sqlfunc_cbr.op)(bed->b, elem, idata)) sql_db_fail(bed->b); } } } } return TRUE; } void sql_create_table(struct DBdesc *db, time_t *basetime, struct primitives_ptrs *prim_ptrs) { char buf[LARGEBUFLEN], tmpbuf[LARGEBUFLEN]; int ret; ret = read_SQLquery_from_file(config.sql_table_schema, buf, LARGEBUFLEN); if (ret) { handle_dynname_internal_strings_same(buf, LARGEBUFLEN, tmpbuf, prim_ptrs, DYN_STR_SQL_TABLE); pm_strftime_same(buf, LARGEBUFLEN, tmpbuf, basetime, config.timestamps_utc); (*sqlfunc_cbr.create_table)(db, buf); } } void sql_invalidate_shadow_entries(struct db_cache *queue[], int *num) { int x; for (x = 0; x < *num; x++) { if (!queue[x]->bytes_counter && !queue[x]->packet_counter && !queue[x]->flows_counter) queue[x]->valid = SQL_CACHE_FREE; } } int sql_select_locking_style(char *lock) { int i = 0, len = strlen(lock); while (i < len) { lock[i] = tolower(lock[i]); i++; } if (!strcmp(lock, "table")) return PM_LOCK_EXCLUSIVE; else if (!strcmp(lock, "row")) return PM_LOCK_ROW_EXCLUSIVE; else if (!strcmp(lock, "none")) return PM_LOCK_NONE; Log(LOG_WARNING, "WARN ( %s/%s ): sql_locking_style value '%s' is unknown. Ignored.\n", config.name, config.type, lock); return PM_LOCK_EXCLUSIVE; } int sql_compose_static_set_event() { int set_primitives=0; if (config.what_to_count & COUNT_TCPFLAGS) { strncat(set_event[set_primitives].string, "SET tcp_flags=tcp_flags|%u", SPACELEFT(set_event[set_primitives].string)); set_event[set_primitives].type = COUNT_INT_TCPFLAGS; set_event[set_primitives].handler = count_tcpflags_setclause_handler; set_primitives++; } if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) { strncat(set_event[set_primitives].string, "SET tunnel_tcp_flags=tunnel_tcp_flags|%u", SPACELEFT(set_event[set_primitives].string)); set_event[set_primitives].type = COUNT_INT_TUNNEL_TCPFLAGS; set_event[set_primitives].handler = count_tunnel_tcpflags_setclause_handler; set_primitives++; } return set_primitives; } int sql_compose_static_set(int have_flows) { int set_primitives=0; strncpy(set[set_primitives].string, "SET packets=packets+%llu, bytes=bytes+%llu", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = COUNT_INT_COUNTERS; set[set_primitives].handler = count_counters_setclause_handler; set_primitives++; if (have_flows) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "flows=flows+%llu", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = COUNT_INT_FLOWS; set[set_primitives].handler = count_flows_setclause_handler; set_primitives++; } if (config.what_to_count & COUNT_TCPFLAGS) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "tcp_flags=tcp_flags|%u", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = COUNT_INT_TCPFLAGS; set[set_primitives].handler = count_tcpflags_setclause_handler; set_primitives++; } if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) { strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string)); strncat(set[set_primitives].string, "tunnel_tcp_flags=tunnel_tcp_flags|%u", SPACELEFT(set[set_primitives].string)); set[set_primitives].type = COUNT_INT_TUNNEL_TCPFLAGS; set[set_primitives].handler = count_tunnel_tcpflags_setclause_handler; set_primitives++; } return set_primitives; } void primptrs_set_all_from_db_cache(struct primitives_ptrs *prim_ptrs, struct db_cache *entry) { struct pkt_data *data = prim_ptrs->data; if (prim_ptrs && data && entry) { memset(data, 0, PdataSz); data->primitives = entry->primitives; prim_ptrs->pbgp = entry->pbgp; prim_ptrs->pnat = entry->pnat; prim_ptrs->pmpls = entry->pmpls; prim_ptrs->ptun = entry->ptun; prim_ptrs->pcust = entry->pcust; prim_ptrs->pvlen = entry->pvlen; } } void sql_set_stitch(struct db_cache *cache_ptr, struct pkt_data *data, struct insert_data *idata) { if (data->time_start.tv_sec) { memcpy(&cache_ptr->stitch->timestamp_min, &data->time_start, sizeof(struct timeval)); } else { memcpy(&cache_ptr->stitch->timestamp_min, &idata->nowtv, sizeof(struct timeval)); } if (data->time_end.tv_sec) { memcpy(&cache_ptr->stitch->timestamp_max, &data->time_end, sizeof(struct timeval)); } else { memcpy(&cache_ptr->stitch->timestamp_max, &idata->nowtv, sizeof(struct timeval)); } } void sql_update_stitch(struct db_cache *cache_ptr, struct pkt_data *data, struct insert_data *idata) { if (data->time_end.tv_sec) { if (data->time_end.tv_sec > cache_ptr->stitch->timestamp_max.tv_sec && data->time_end.tv_usec > cache_ptr->stitch->timestamp_max.tv_usec) { memcpy(&cache_ptr->stitch->timestamp_max, &data->time_end, sizeof(struct timeval)); } } else { memcpy(&cache_ptr->stitch->timestamp_max, &idata->nowtv, sizeof(struct timeval)); } } void sql_update_time_reference(struct insert_data *idata) { idata->now = time(NULL); if (config.nfacctd_stitching) { gettimeofday(&idata->nowtv, NULL); if (config.timestamps_secs) { idata->nowtv.tv_usec = 0; } } if (config.sql_history) { while (idata->now > (idata->basetime + idata->timeslot)) { time_t saved_basetime = idata->basetime; idata->basetime += idata->timeslot; if (config.sql_history == COUNT_MONTHLY) idata->timeslot = calc_monthly_timeslot(idata->basetime, config.sql_history_howmany, ADD); glob_basetime = idata->basetime; idata->new_basetime = saved_basetime; glob_new_basetime = saved_basetime; } } } pmacct-1.7.8/src/print_plugin.c0000644000175000017500000021764014354105275015471 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_common.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "plugin_cmn_json.h" #include "plugin_cmn_avro.h" #include "plugin_cmn_custom.h" #include "print_plugin.h" #include "ip_flow.h" #include "classifier.h" #include "crc32.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif #include "net_aggr.h" #include "preprocess-internal.h" /* Global variables */ int print_output_stdout_header; /* Functions */ void print_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; unsigned char *pipebuf; struct pollfd pfd; struct insert_data idata; int refresh_timeout, ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; char spacing_sep[2]; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; unsigned char *dataptr; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "Print Plugin", config.name); P_set_signals(); P_init_default_values(); P_config_checks(); pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); if (!config.print_output) config.print_output = PRINT_OUTPUT_FORMATTED; refresh_timeout = config.sql_refresh_time*1000; if (config.print_output != PRINT_OUTPUT_JSON && config.print_output != PRINT_OUTPUT_AVRO_BIN && config.print_output != PRINT_OUTPUT_AVRO_JSON) { if (config.tcpflags_encode_as_array || config.mpls_label_stack_encode_as_array || config.pretag_label_encode_as_map) { Log(LOG_WARNING, "WARN ( %s/%s ): Complex data types (ie. pre_tag_label_encode_as_map) not supported by the selected print_output. Ignored.\n", config.name, config.type); } } if (config.print_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON compose_json(config.what_to_count, config.what_to_count_2); #endif } else if ((config.print_output & PRINT_OUTPUT_AVRO_BIN) || (config.print_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO p_avro_acct_schema = p_avro_schema_build_acct_data(config.what_to_count, config.what_to_count_2); if (config.avro_schema_file) write_avro_schema_to_file(config.avro_schema_file, p_avro_acct_schema); #endif } else if (config.print_output & PRINT_OUTPUT_CUSTOM) { if (config.print_output_custom_lib != NULL) { custom_output_setup(config.print_output_custom_lib, config.print_output_custom_cfg_file, &custom_print_plugin); } } /* setting function pointers */ if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) insert_func = P_sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) insert_func = P_sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) insert_func = P_sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) insert_func = P_sum_mac_insert; #endif else insert_func = P_cache_insert; purge_func = P_cache_purge; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); memset(&idata, 0, sizeof(idata)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); set_primptrs_funcs(&extras); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); idata.now = time(NULL); /* print_refresh time init: deadline */ refresh_deadline = idata.now; P_init_refresh_deadline(&refresh_deadline, config.sql_refresh_time, config.sql_startup_delay, config.sql_history_roundoff); if (config.sql_history) { basetime_init = P_init_historical_acct; basetime_eval = P_eval_historical_acct; basetime_cmp = P_cmp_historical_acct; (*basetime_init)(idata.now); } /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; if (!config.print_output_separator) config.print_output_separator = DEFAULT_SEP; else { if (!strcmp(config.print_output_separator, "\\s")) { spacing_sep[0] = ' '; spacing_sep[1] = '\0'; config.print_output_separator = spacing_sep; } if (!strcmp(config.print_output_separator, "\\t")) { spacing_sep[0] = '\t'; spacing_sep[1] = '\0'; config.print_output_separator = spacing_sep; } } if ((extras.off_pkt_vlen_hdr_primitives || config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) && config.print_output & PRINT_OUTPUT_FORMATTED) { Log(LOG_ERR, "ERROR ( %s/%s ): variable-length primitives, ie. label as_path std_comm etc., are not supported in print plugin with formatted output.\n", config.name, config.type); Log(LOG_ERR, "ERROR ( %s/%s ): Please switch to one of the other supported output formats (ie. csv, json, avro). Exiting ..\n", config.name, config.type); exit_gracefully(1); } print_output_stdout_header = TRUE; if (!config.sql_table && config.daemon) { Log(LOG_ERR, "ERROR ( %s/%s ): no print_output_file defined and 'daemonize: true'. Output would be lost. Exiting ..\n", config.name, config.type); exit_gracefully(1); } if (!config.sql_table && !config.print_output_lock_file) { Log(LOG_WARNING, "WARN ( %s/%s ): no print_output_file and no print_output_lock_file defined.\n", config.name, config.type); } if (config.sql_table) { if (strchr(config.sql_table, '%') || strchr(config.sql_table, '$')) { dyn_table = TRUE; if (!have_dynname_nontime(config.sql_table)) dyn_table_time_only = TRUE; else dyn_table_time_only = FALSE; } else { dyn_table = FALSE; dyn_table_time_only = FALSE; if (config.print_latest_file && (strchr(config.print_latest_file, '%') || strchr(config.print_latest_file, '$'))) { Log(LOG_WARNING, "WARN ( %s/%s ): Disabling print_latest_file due to non-dynamic print_output_file.\n", config.name, config.type); config.print_latest_file = NULL; } } } #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: P_update_time_reference(&idata); if (idata.now > refresh_deadline) { int saved_qq_ptr; saved_qq_ptr = qq_ptr; P_cache_handle_flush_event(&pt, &prt, &tost); if (saved_qq_ptr) print_output_stdout_header = FALSE; } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } void P_cache_purge(struct chained_cache *queue[], int index, int safe_action) { struct pkt_primitives *data = NULL; struct pkt_bgp_primitives *pbgp = NULL; struct pkt_nat_primitives *pnat = NULL; struct pkt_mpls_primitives *pmpls = NULL; struct pkt_tunnel_primitives *ptun = NULL; u_char *pcust = NULL; struct pkt_vlen_hdr_primitives *pvlen = NULL; struct pkt_bgp_primitives empty_pbgp; struct pkt_nat_primitives empty_pnat; struct pkt_mpls_primitives empty_pmpls; struct pkt_tunnel_primitives empty_ptun; u_char *empty_pcust = NULL; char src_mac[18], dst_mac[18], src_host[INET6_ADDRSTRLEN], dst_host[INET6_ADDRSTRLEN], ip_address[INET6_ADDRSTRLEN]; char rd_str[SRVBUFLEN], *sep = config.print_output_separator, *fd_buf; char *as_path, *bgp_comm, empty_string[] = "", empty_ip6[] = "::"; char empty_macaddress[] = "00:00:00:00:00:00", empty_rd[] = "0:0"; #if defined (WITH_NDPI) char ndpi_class[SUPERSHORTBUFLEN]; #endif FILE *f = NULL, *lockf = NULL; int j, stop, is_event = FALSE, qn = 0, go_to_pending, saved_index = index, file_to_be_created; time_t start, duration; char tmpbuf[SRVBUFLEN], current_table[SRVBUFLEN], elem_table[SRVBUFLEN]; struct primitives_ptrs prim_ptrs, elem_prim_ptrs; struct pkt_data dummy_data, elem_dummy_data; pid_t writer_pid = getpid(); #ifdef WITH_AVRO avro_file_writer_t p_avro_writer; #endif if (!index && !config.print_write_empty_file) { Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: 0/0, ET: X) ***\n", config.name, config.type, writer_pid); return; } empty_pcust = malloc(config.cpptrs.len); if (!empty_pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() empty_pcust. Exiting.\n", config.name, config.type); exit_gracefully(1); } memset(&empty_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&empty_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&empty_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&empty_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(empty_pcust, 0, config.cpptrs.len); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); memset(&elem_prim_ptrs, 0, sizeof(elem_prim_ptrs)); memset(&elem_dummy_data, 0, sizeof(elem_dummy_data)); fd_buf = malloc(OUTPUT_FILE_BUFSZ); for (j = 0, stop = 0; (!stop) && P_preprocess_funcs[j]; j++) stop = P_preprocess_funcs[j](queue, &index, j); memcpy(pending_queries_queue, queue, index*sizeof(struct db_cache *)); pqq_ptr = index; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); start: memcpy(queue, pending_queries_queue, pqq_ptr*sizeof(struct db_cache *)); memset(pending_queries_queue, 0, pqq_ptr*sizeof(struct db_cache *)); index = pqq_ptr; pqq_ptr = 0; file_to_be_created = FALSE; if (config.print_output & PRINT_OUTPUT_EVENT) is_event = TRUE; if (config.sql_table) { time_t stamp = 0; if (dyn_table) { /* NOTE: on saved_index=0; queue[0] is NULL */ if (saved_index > 0) { stamp = queue[0]->basetime.tv_sec; prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[0]); } else { stamp = start; } handle_dynname_internal_strings(current_table, SRVBUFLEN, config.sql_table, &prim_ptrs, DYN_STR_PRINT_FILE); pm_strftime_same(current_table, SRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); } else strlcpy(current_table, config.sql_table, SRVBUFLEN); if (config.print_output & PRINT_OUTPUT_AVRO_BIN) { #ifdef WITH_AVRO int file_is_empty, ret; f = open_output_file(current_table, "ab", TRUE); fseek(f, 0, SEEK_END); file_is_empty = ftell(f) == 0; close_output_file(f); if (config.print_output_file_append && !file_is_empty) { ret = avro_file_writer_open(current_table, &p_avro_writer); } else { ret = avro_file_writer_create(current_table, p_avro_acct_schema, &p_avro_writer); } if (ret) { Log(LOG_ERR, "ERROR ( %s/%s ): P_cache_purge(): failed opening %s: %s\n", config.name, config.type, current_table, avro_strerror()); exit_gracefully(1); } #endif } else if (config.print_output & PRINT_OUTPUT_CUSTOM) { if (0 != custom_print_plugin.output_init(current_table, config.print_output_file_append)) { Log(LOG_ERR, "ERROR ( %s/%s ): Custom output: failed opening %s: %s\n", config.name, config.type, current_table, custom_print_plugin.get_error_text()); exit_gracefully(1); } } else { if (config.print_output_file_append) { file_to_be_created = access(current_table, F_OK); f = open_output_file(current_table, "a", TRUE); } else { f = open_output_file(current_table, "w", TRUE); } } if (f) { if (!(config.print_output & PRINT_OUTPUT_AVRO_BIN) && fd_buf) { if (setvbuf(f, fd_buf, _IOFBF, OUTPUT_FILE_BUFSZ)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] setvbuf() failed: %s\n", config.name, config.type, current_table, strerror(errno)); } else { memset(fd_buf, 0, OUTPUT_FILE_BUFSZ); } } if (config.print_markers) { if ((config.print_output & PRINT_OUTPUT_CSV) || (config.print_output & PRINT_OUTPUT_FORMATTED)) fprintf(f, "--START (%u)--\n", writer_pid); else if (config.print_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON void *json_obj; json_obj = compose_purge_init_json(config.name, writer_pid); if (json_obj) write_and_free_json(f, json_obj); #endif } } if (!config.print_output_file_append || (config.print_output_file_append && file_to_be_created)) { if (config.print_output & PRINT_OUTPUT_FORMATTED) P_write_stats_header_formatted(f, is_event); else if (config.print_output & PRINT_OUTPUT_CSV) P_write_stats_header_csv(f, is_event); } } } else { /* writing to stdout: pointing f and obtaining lock */ f = stdout; if (config.print_output_lock_file) { lockf = open_output_file(config.print_output_lock_file, "w", TRUE); if (!lockf) Log(LOG_WARNING, "WARN ( %s/%s ): Failed locking print_output_lock_file: %s\n", config.name, config.type, config.print_output_lock_file); } if (config.print_markers) { if ((config.print_output & PRINT_OUTPUT_CSV) || (config.print_output & PRINT_OUTPUT_FORMATTED)) fprintf(stdout, "--START (%u)--\n", writer_pid); else if (config.print_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON void *json_obj; json_obj = compose_purge_init_json(config.name, writer_pid); if (json_obj) write_and_free_json(stdout, json_obj); #endif } } /* writing to stdout: writing header only once */ if (print_output_stdout_header) { if (config.print_output & PRINT_OUTPUT_FORMATTED) P_write_stats_header_formatted(stdout, is_event); else if (config.print_output & PRINT_OUTPUT_CSV) P_write_stats_header_csv(stdout, is_event); } } for (j = 0; j < index; j++) { int count = 0; go_to_pending = FALSE; if (queue[j]->valid != PRINT_CACHE_COMMITTED) continue; if (dyn_table && (!dyn_table_time_only || !config.nfacctd_time_new || (config.sql_refresh_time != timeslot))) { time_t stamp = 0; stamp = queue[j]->basetime.tv_sec; elem_prim_ptrs.data = &elem_dummy_data; primptrs_set_all_from_chained_cache(&elem_prim_ptrs, queue[j]); handle_dynname_internal_strings(elem_table, SRVBUFLEN, config.sql_table, &elem_prim_ptrs, DYN_STR_PRINT_FILE); pm_strftime_same(elem_table, SRVBUFLEN, tmpbuf, &stamp, config.timestamps_utc); if (strncmp(current_table, elem_table, SRVBUFLEN)) { pending_queries_queue[pqq_ptr] = queue[j]; pqq_ptr++; go_to_pending = TRUE; } } if (!go_to_pending) { if (f) qn++; else { qn++; } data = &queue[j]->primitives; if (queue[j]->pbgp) pbgp = queue[j]->pbgp; else pbgp = &empty_pbgp; if (queue[j]->pnat) pnat = queue[j]->pnat; else pnat = &empty_pnat; if (queue[j]->pmpls) pmpls = queue[j]->pmpls; else pmpls = &empty_pmpls; if (queue[j]->ptun) ptun = queue[j]->ptun; else ptun = &empty_ptun; if (queue[j]->pcust) pcust = queue[j]->pcust; else pcust = empty_pcust; if (queue[j]->pvlen) pvlen = queue[j]->pvlen; else pvlen = NULL; if (queue[j]->valid == PRINT_CACHE_FREE) continue; if (f && config.print_output & PRINT_OUTPUT_FORMATTED) { if (config.what_to_count & COUNT_TAG) fprintf(f, "%-10" PRIu64 " ", data->tag); if (config.what_to_count & COUNT_TAG2) fprintf(f, "%-10" PRIu64 " ", data->tag2); if (config.what_to_count & COUNT_CLASS) fprintf(f, "%-16s ", ((data->class && class[(data->class)-1].id) ? class[(data->class)-1].protocol : "unknown" )); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) { snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.app_protocol)); fprintf(f, "%-16s ", ndpi_class); } #endif #if defined HAVE_L2 if (config.what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { etheraddr_string(data->eth_shost, src_mac); if (strlen(src_mac)) fprintf(f, "%-17s ", src_mac); else fprintf(f, "%-17s ", empty_macaddress); } if (config.what_to_count & COUNT_DST_MAC) { etheraddr_string(data->eth_dhost, dst_mac); if (strlen(dst_mac)) fprintf(f, "%-17s ", dst_mac); else fprintf(f, "%-17s ", empty_macaddress); } if (config.what_to_count & COUNT_VLAN) fprintf(f, "%-5u ", data->vlan_id); if (config.what_to_count_2 & COUNT_OUT_VLAN) fprintf(f, "%-8u ", data->out_vlan_id); if (config.what_to_count & COUNT_COS) fprintf(f, "%-2u ", data->cos); if (config.what_to_count & COUNT_ETHERTYPE) fprintf(f, "%-5x ", data->etype); #endif if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) fprintf(f, "%-10u ", data->src_as); if (config.what_to_count & COUNT_DST_AS) fprintf(f, "%-10u ", data->dst_as); if (config.what_to_count & COUNT_LOCAL_PREF) fprintf(f, "%-7u ", pbgp->local_pref); if (config.what_to_count & COUNT_SRC_LOCAL_PREF) fprintf(f, "%-7u ", pbgp->src_local_pref); if (config.what_to_count & COUNT_MED) fprintf(f, "%-6u ", pbgp->med); if (config.what_to_count & COUNT_SRC_MED) fprintf(f, "%-6u ", pbgp->src_med); if (config.what_to_count_2 & COUNT_SRC_ROA) fprintf(f, "%-6s ", rpki_roa_print(pbgp->src_roa)); if (config.what_to_count_2 & COUNT_DST_ROA) fprintf(f, "%-6s ", rpki_roa_print(pbgp->dst_roa)); if (config.what_to_count & COUNT_PEER_SRC_AS) fprintf(f, "%-10u ", pbgp->peer_src_as); if (config.what_to_count & COUNT_PEER_DST_AS) fprintf(f, "%-10u ", pbgp->peer_dst_as); if (config.what_to_count & COUNT_PEER_SRC_IP) { addr_to_str(ip_address, &pbgp->peer_src_ip); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & COUNT_PEER_DST_IP) { addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(queue[j]->flow_type)); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & COUNT_IN_IFACE) fprintf(f, "%-10u ", data->ifindex_in); if (config.what_to_count & COUNT_OUT_IFACE) fprintf(f, "%-10u ", data->ifindex_out); if (config.what_to_count & COUNT_MPLS_VPN_RD) { bgp_rd2str(rd_str, &pbgp->mpls_vpn_rd); if (strlen(rd_str)) fprintf(f, "%-18s ", rd_str); else fprintf(f, "%-18s ", empty_rd); } if (config.what_to_count_2 & COUNT_MPLS_PW_ID) fprintf(f, "%-10u ", pbgp->mpls_pw_id); if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { addr_to_str(src_host, &data->src_ip); if (strlen(src_host)) fprintf(f, "%-45s ", src_host); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { addr_to_str(src_host, &data->src_net); if (strlen(src_host)) fprintf(f, "%-45s ", src_host); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & COUNT_DST_HOST) { addr_to_str(dst_host, &data->dst_ip); if (strlen(dst_host)) fprintf(f, "%-45s ", dst_host); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & COUNT_DST_NET) { addr_to_str(dst_host, &data->dst_net); if (strlen(dst_host)) fprintf(f, "%-45s ", dst_host); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count & COUNT_SRC_NMASK) fprintf(f, "%-3u ", data->src_nmask); if (config.what_to_count & COUNT_DST_NMASK) fprintf(f, "%-3u ", data->dst_nmask); if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) fprintf(f, "%-5u ", data->src_port); if (config.what_to_count & COUNT_DST_PORT) fprintf(f, "%-5u ", data->dst_port); if (config.what_to_count & COUNT_TCPFLAGS) fprintf(f, "%-3u ", queue[j]->tcp_flags); if (config.what_to_count & COUNT_IP_PROTO) { if (!config.num_protos && (data->proto < protocols_number)) fprintf(f, "%-10s ", _protocols[data->proto].name); else fprintf(f, "%-10d ", data->proto); } if (config.what_to_count & COUNT_IP_TOS) fprintf(f, "%-3u ", data->tos); #if defined WITH_GEOIP if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "%-5s ", GeoIP_code_by_id(data->src_ip_country.id)); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "%-5s ", GeoIP_code_by_id(data->dst_ip_country.id)); #endif #if defined WITH_GEOIPV2 if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "%-5s ", data->src_ip_country.str); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "%-5s ", data->dst_ip_country.str); if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) fprintf(f, "%-12s ", data->src_ip_pocode.str); if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) fprintf(f, "%-12s ", data->dst_ip_pocode.str); if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) { fprintf(f, "%-8f ", data->src_ip_lat); fprintf(f, "%-8f ", data->src_ip_lon); } if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) { fprintf(f, "%-8f ", data->dst_ip_lat); fprintf(f, "%-8f ", data->dst_ip_lon); } #endif if (config.what_to_count_2 & COUNT_SAMPLING_RATE) fprintf(f, "%-7u ", data->sampling_rate); if (config.what_to_count_2 & COUNT_SAMPLING_DIRECTION) fprintf(f, "%-1s ", sampling_direction_print(data->sampling_direction)); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) { addr_to_str(ip_address, &pnat->post_nat_src_ip); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) { addr_to_str(ip_address, &pnat->post_nat_dst_ip); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) fprintf(f, "%-5u ", pnat->post_nat_src_port); if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) fprintf(f, "%-5u ", pnat->post_nat_dst_port); if (config.what_to_count_2 & COUNT_NAT_EVENT) fprintf(f, "%-3u ", pnat->nat_event); if (config.what_to_count_2 & COUNT_FW_EVENT) fprintf(f, "%-3u ", pnat->fw_event); if (config.what_to_count_2 & COUNT_FWD_STATUS) fprintf(f, "%-3u ", pnat->fwd_status); if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) { fprintf(f, "%-7u ", pmpls->mpls_label_top); } if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) { fprintf(f, "%-7u ", pmpls->mpls_label_bottom); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) { etheraddr_string(ptun->tunnel_eth_shost, src_mac); if (strlen(src_mac)) fprintf(f, "%-17s ", src_mac); else fprintf(f, "%-17s ", empty_macaddress); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) { etheraddr_string(ptun->tunnel_eth_dhost, dst_mac); if (strlen(dst_mac)) fprintf(f, "%-17s ", dst_mac); else fprintf(f, "%-17s ", empty_macaddress); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) { addr_to_str(ip_address, &ptun->tunnel_src_ip); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) { addr_to_str(ip_address, &ptun->tunnel_dst_ip); if (strlen(ip_address)) fprintf(f, "%-45s ", ip_address); else fprintf(f, "%-45s ", empty_ip6); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) { if (!config.num_protos && (ptun->tunnel_proto < protocols_number)) fprintf(f, "%-10s ", _protocols[ptun->tunnel_proto].name); else fprintf(f, "%-10d ", ptun->tunnel_proto); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) fprintf(f, "%-3u ", ptun->tunnel_tos); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) fprintf(f, "%-5u ", ptun->tunnel_src_port); if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) fprintf(f, "%-5u ", ptun->tunnel_dst_port); if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) fprintf(f, "%-3u ", queue[j]->tunnel_tcp_flags); if (config.what_to_count_2 & COUNT_VXLAN) fprintf(f, "%-8u ", ptun->tunnel_id); if (config.what_to_count_2 & COUNT_TIMESTAMP_START) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_start, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); } if (config.what_to_count_2 & COUNT_TIMESTAMP_END) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_end, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); } if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_export, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); } if (config.nfacctd_stitching && queue[j]->stitch) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &queue[j]->stitch->timestamp_min, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &queue[j]->stitch->timestamp_max, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%-30s ", tstamp_str); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) fprintf(f, "%-18u ", data->export_proto_seqno); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) fprintf(f, "%-20u ", data->export_proto_version); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) fprintf(f, "%-18u ", data->export_proto_sysid); /* all custom primitives printed here */ { int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], TRUE); fprintf(f, "%s ", cp_str); } else { /* vlen primitives not supported in formatted outputs: we should never get here */ char *label_ptr = NULL; vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; fprintf(f, "%s ", label_ptr); } } } if (!is_event) { fprintf(f, "%-20" PRIu64 " ", queue[j]->packet_counter); if (config.what_to_count & COUNT_FLOWS) fprintf(f, "%-20" PRIu64 " ", queue[j]->flow_counter); fprintf(f, "%" PRIu64 "\n", queue[j]->bytes_counter); } else fprintf(f, "\n"); } else if (f && config.print_output & PRINT_OUTPUT_CSV) { if (config.what_to_count & COUNT_TAG) fprintf(f, "%s%" PRIu64 "", write_sep(sep, &count), data->tag); if (config.what_to_count & COUNT_TAG2) fprintf(f, "%s%" PRIu64 "", write_sep(sep, &count), data->tag2); if (config.what_to_count_2 & COUNT_LABEL) P_fprintf_csv_string(f, pvlen, COUNT_INT_LABEL, write_sep(sep, &count), empty_string); if (config.what_to_count & COUNT_CLASS) fprintf(f, "%s%s", write_sep(sep, &count), ((data->class && class[(data->class)-1].id) ? class[(data->class)-1].protocol : "unknown" )); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) { snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, data->ndpi_class.app_protocol)); fprintf(f, "%s%s", write_sep(sep, &count), ndpi_class); } #endif #if defined (HAVE_L2) if (config.what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { etheraddr_string(data->eth_shost, src_mac); fprintf(f, "%s%s", write_sep(sep, &count), src_mac); } if (config.what_to_count & COUNT_DST_MAC) { etheraddr_string(data->eth_dhost, dst_mac); fprintf(f, "%s%s", write_sep(sep, &count), dst_mac); } if (config.what_to_count & COUNT_VLAN) fprintf(f, "%s%u", write_sep(sep, &count), data->vlan_id); if (config.what_to_count_2 & COUNT_OUT_VLAN) fprintf(f, "%s%u", write_sep(sep, &count), data->out_vlan_id); if (config.what_to_count & COUNT_COS) fprintf(f, "%s%u", write_sep(sep, &count), data->cos); if (config.what_to_count & COUNT_ETHERTYPE) fprintf(f, "%s%x", write_sep(sep, &count), data->etype); #endif if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) fprintf(f, "%s%u", write_sep(sep, &count), data->src_as); if (config.what_to_count & COUNT_DST_AS) fprintf(f, "%s%u", write_sep(sep, &count), data->dst_as); if (config.what_to_count & COUNT_STD_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_STD_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_EXT_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_EXT_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count_2 & COUNT_LRG_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_LRG_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_SRC_STD_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_SRC_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_SRC_STD_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_SRC_EXT_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_SRC_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_SRC_EXT_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count_2 & COUNT_SRC_LRG_COMM) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_SRC_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_SRC_LRG_COMM, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_AS_PATH) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_AS_PATH, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_SRC_AS_PATH) { char *str_ptr = NULL; vlen_prims_get(pvlen, COUNT_INT_SRC_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } P_fprintf_csv_string(f, pvlen, COUNT_INT_SRC_AS_PATH, write_sep(sep, &count), empty_string); } if (config.what_to_count & COUNT_LOCAL_PREF) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->local_pref); if (config.what_to_count & COUNT_SRC_LOCAL_PREF) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->src_local_pref); if (config.what_to_count & COUNT_MED) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->med); if (config.what_to_count & COUNT_SRC_MED) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->src_med); if (config.what_to_count_2 & COUNT_SRC_ROA) fprintf(f, "%s%s", write_sep(sep, &count), rpki_roa_print(pbgp->src_roa)); if (config.what_to_count_2 & COUNT_DST_ROA) fprintf(f, "%s%s", write_sep(sep, &count), rpki_roa_print(pbgp->dst_roa)); if (config.what_to_count & COUNT_PEER_SRC_AS) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->peer_src_as); if (config.what_to_count & COUNT_PEER_DST_AS) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->peer_dst_as); if (config.what_to_count & COUNT_PEER_SRC_IP) { addr_to_str(ip_address, &pbgp->peer_src_ip); fprintf(f, "%s%s", write_sep(sep, &count), ip_address); } if (config.what_to_count & COUNT_PEER_DST_IP) { addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(queue[j]->flow_type)); fprintf(f, "%s%s", write_sep(sep, &count), ip_address); } if (config.what_to_count & COUNT_IN_IFACE) fprintf(f, "%s%u", write_sep(sep, &count), data->ifindex_in); if (config.what_to_count & COUNT_OUT_IFACE) fprintf(f, "%s%u", write_sep(sep, &count), data->ifindex_out); if (config.what_to_count & COUNT_MPLS_VPN_RD) { bgp_rd2str(rd_str, &pbgp->mpls_vpn_rd); fprintf(f, "%s%s", write_sep(sep, &count), rd_str); } if (config.what_to_count_2 & COUNT_MPLS_PW_ID) fprintf(f, "%s%u", write_sep(sep, &count), pbgp->mpls_pw_id); if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { addr_to_str(src_host, &data->src_ip); fprintf(f, "%s%s", write_sep(sep, &count), src_host); } if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) { addr_to_str(src_host, &data->src_net); fprintf(f, "%s%s", write_sep(sep, &count), src_host); } if (config.what_to_count & COUNT_DST_HOST) { addr_to_str(dst_host, &data->dst_ip); fprintf(f, "%s%s", write_sep(sep, &count), dst_host); } if (config.what_to_count & COUNT_DST_NET) { addr_to_str(dst_host, &data->dst_net); fprintf(f, "%s%s", write_sep(sep, &count), dst_host); } if (config.what_to_count & COUNT_SRC_NMASK) fprintf(f, "%s%u", write_sep(sep, &count), data->src_nmask); if (config.what_to_count & COUNT_DST_NMASK) fprintf(f, "%s%u", write_sep(sep, &count), data->dst_nmask); if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) fprintf(f, "%s%u", write_sep(sep, &count), data->src_port); if (config.what_to_count & COUNT_DST_PORT) fprintf(f, "%s%u", write_sep(sep, &count), data->dst_port); if (config.what_to_count & COUNT_TCPFLAGS) fprintf(f, "%s%u", write_sep(sep, &count), queue[j]->tcp_flags); if (config.what_to_count & COUNT_IP_PROTO) { if (!config.num_protos && (data->proto < protocols_number)) fprintf(f, "%s%s", write_sep(sep, &count), _protocols[data->proto].name); else fprintf(f, "%s%d", write_sep(sep, &count), data->proto); } if (config.what_to_count & COUNT_IP_TOS) fprintf(f, "%s%u", write_sep(sep, &count), data->tos); #if defined WITH_GEOIP if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "%s%s", write_sep(sep, &count), GeoIP_code_by_id(data->src_ip_country.id)); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "%s%s", write_sep(sep, &count), GeoIP_code_by_id(data->dst_ip_country.id)); #endif #if defined WITH_GEOIPV2 if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "%s%s", write_sep(sep, &count), data->src_ip_country.str); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "%s%s", write_sep(sep, &count), data->dst_ip_country.str); if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) fprintf(f, "%s%s", write_sep(sep, &count), data->src_ip_pocode.str); if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) fprintf(f, "%s%s", write_sep(sep, &count), data->dst_ip_pocode.str); if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) { fprintf(f, "%s%f", write_sep(sep, &count), data->src_ip_lat); fprintf(f, "%s%f", write_sep(sep, &count), data->src_ip_lon); } if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) { fprintf(f, "%s%f", write_sep(sep, &count), data->dst_ip_lat); fprintf(f, "%s%f", write_sep(sep, &count), data->dst_ip_lon); } #endif if (config.what_to_count_2 & COUNT_SAMPLING_RATE) fprintf(f, "%s%u", write_sep(sep, &count), data->sampling_rate); if (config.what_to_count_2 & COUNT_SAMPLING_DIRECTION) fprintf(f, "%s%s", write_sep(sep, &count), sampling_direction_print(data->sampling_direction)); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) { addr_to_str(src_host, &pnat->post_nat_src_ip); fprintf(f, "%s%s", write_sep(sep, &count), src_host); } if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) { addr_to_str(dst_host, &pnat->post_nat_dst_ip); fprintf(f, "%s%s", write_sep(sep, &count), dst_host); } if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) fprintf(f, "%s%u", write_sep(sep, &count), pnat->post_nat_src_port); if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) fprintf(f, "%s%u", write_sep(sep, &count), pnat->post_nat_dst_port); if (config.what_to_count_2 & COUNT_NAT_EVENT) fprintf(f, "%s%u", write_sep(sep, &count), pnat->nat_event); if (config.what_to_count_2 & COUNT_FW_EVENT) fprintf(f, "%s%u", write_sep(sep, &count), pnat->fw_event); if (config.what_to_count_2 & COUNT_FWD_STATUS) fprintf(f, "%s%u", write_sep(sep, &count), pnat->fwd_status); if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) fprintf(f, "%s%u", write_sep(sep, &count), pmpls->mpls_label_top); if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) fprintf(f, "%s%u", write_sep(sep, &count), pmpls->mpls_label_bottom); if (config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) { char label_stack[MAX_MPLS_LABEL_STACK]; char *label_stack_ptr = NULL; int label_stack_len = 0; memset(label_stack, 0, MAX_MPLS_LABEL_STACK); label_stack_len = vlen_prims_get(pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); if (label_stack_ptr) { mpls_label_stack_to_str(label_stack, sizeof(label_stack), (u_int32_t *)label_stack_ptr, label_stack_len); } fprintf(f, "%s%s", write_sep(sep, &count), label_stack); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) { etheraddr_string(ptun->tunnel_eth_shost, src_mac); fprintf(f, "%s%s", write_sep(sep, &count), src_mac); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) { etheraddr_string(ptun->tunnel_eth_dhost, dst_mac); fprintf(f, "%s%s", write_sep(sep, &count), dst_mac); } if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) { addr_to_str(src_host, &ptun->tunnel_src_ip); fprintf(f, "%s%s", write_sep(sep, &count), src_host); } if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) { addr_to_str(dst_host, &ptun->tunnel_dst_ip); fprintf(f, "%s%s", write_sep(sep, &count), dst_host); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) { if (!config.num_protos && (ptun->tunnel_proto < protocols_number)) fprintf(f, "%s%s", write_sep(sep, &count), _protocols[ptun->tunnel_proto].name); else fprintf(f, "%s%d", write_sep(sep, &count), ptun->tunnel_proto); } if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) fprintf(f, "%s%u", write_sep(sep, &count), ptun->tunnel_tos); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) fprintf(f, "%s%u", write_sep(sep, &count), ptun->tunnel_src_port); if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) fprintf(f, "%s%u", write_sep(sep, &count), ptun->tunnel_dst_port); if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) fprintf(f, "%s%u", write_sep(sep, &count), queue[j]->tunnel_tcp_flags); if (config.what_to_count_2 & COUNT_VXLAN) fprintf(f, "%s%u", write_sep(sep, &count), ptun->tunnel_id); if (config.what_to_count_2 & COUNT_TIMESTAMP_START) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_start, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); } if (config.what_to_count_2 & COUNT_TIMESTAMP_END) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_end, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); } if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &pnat->timestamp_export, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); } if (config.nfacctd_stitching && queue[j]->stitch) { char tstamp_str[VERYSHORTBUFLEN]; compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &queue[j]->stitch->timestamp_min, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); compose_timestamp(tstamp_str, VERYSHORTBUFLEN, &queue[j]->stitch->timestamp_max, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); fprintf(f, "%s%s", write_sep(sep, &count), tstamp_str); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) fprintf(f, "%s%u", write_sep(sep, &count), data->export_proto_seqno); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) fprintf(f, "%s%u", write_sep(sep, &count), data->export_proto_version); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) fprintf(f, "%s%u", write_sep(sep, &count), data->export_proto_sysid); /* all custom primitives printed here */ { int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], FALSE); fprintf(f, "%s%s", write_sep(sep, &count), cp_str); } else { char *label_ptr = NULL; vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; fprintf(f, "%s%s", write_sep(sep, &count), label_ptr); } } } if (!is_event) { fprintf(f, "%s%" PRIu64 "", write_sep(sep, &count), queue[j]->packet_counter); if (config.what_to_count & COUNT_FLOWS) fprintf(f, "%s%" PRIu64 "", write_sep(sep, &count), queue[j]->flow_counter); fprintf(f, "%s%" PRIu64 "\n", write_sep(sep, &count), queue[j]->bytes_counter); } else fprintf(f, "\n"); } else if (f && config.print_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *json_obj = json_object(); int idx; for (idx = 0; idx < N_PRIMITIVES && cjhandler[idx]; idx++) cjhandler[idx](json_obj, queue[j]); if (json_obj) write_and_free_json(f, json_obj); #endif } else if (f && ((config.print_output & PRINT_OUTPUT_AVRO_BIN) || (config.print_output & PRINT_OUTPUT_AVRO_JSON))) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_schema); avro_value_t p_avro_value = compose_avro_acct_data(config.what_to_count, config.what_to_count_2, queue[j]->flow_type, &queue[j]->primitives, pbgp, pnat, pmpls, ptun, pcust, pvlen, queue[j]->bytes_counter, queue[j]->packet_counter, queue[j]->flow_counter, queue[j]->tcp_flags, queue[j]->tunnel_tcp_flags, NULL, queue[j]->stitch, p_avro_iface); if (config.sql_table) { if (config.print_output & PRINT_OUTPUT_AVRO_BIN) { if (avro_file_writer_append_value(p_avro_writer, &p_avro_value)) { Log(LOG_ERR, "ERROR ( %s/%s ): P_cache_purge(): avro_file_writer_append_value() failed: %s\n", config.name, config.type, avro_strerror()); exit_gracefully(1); } } else if (config.print_output & PRINT_OUTPUT_AVRO_JSON) { write_avro_json_record_to_file(f, p_avro_value); } } else { write_avro_json_record_to_file(f, p_avro_value); } avro_value_iface_decref(p_avro_iface); avro_value_decref(&p_avro_value); #else if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_avro_acct_data(): AVRO object not created due to missing --enable-avro\n", config.name, config.type); #endif } if (config.print_output & PRINT_OUTPUT_CUSTOM) { custom_print_plugin.print(config.what_to_count, config.what_to_count_2, queue[j]->flow_type, &queue[j]->primitives, pbgp, pnat, pmpls, ptun, pcust, pvlen, queue[j]->bytes_counter, queue[j]->packet_counter, queue[j]->flow_counter, queue[j]->tcp_flags, queue[j]->tunnel_tcp_flags, NULL, queue[j]->stitch); } } } duration = time(NULL)-start; if (f && config.print_markers) { if ((config.print_output & PRINT_OUTPUT_CSV) || (config.print_output & PRINT_OUTPUT_FORMATTED)) fprintf(f, "--END (%u)--\n", writer_pid); else if (config.print_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON void *json_obj; json_obj = compose_purge_close_json(config.name, writer_pid, qn, saved_index, duration); if (json_obj) write_and_free_json(f, json_obj); #endif } } if (config.sql_table) { #ifdef WITH_AVRO if (config.print_output & PRINT_OUTPUT_AVRO_BIN) { avro_file_writer_flush(p_avro_writer); } #endif if (config.print_output & PRINT_OUTPUT_CUSTOM) { if (0 != custom_print_plugin.output_flush()) { Log(LOG_ERR, "ERROR ( %s/%s ): Custom output: failed flushing file %s: %s\n", config.name, config.type, current_table, custom_print_plugin.get_error_text()); exit_gracefully(1); } } if (config.print_latest_file) { if (!safe_action) { handle_dynname_internal_strings(tmpbuf, SRVBUFLEN, config.print_latest_file, &prim_ptrs, DYN_STR_PRINT_FILE); link_latest_output_file(tmpbuf, current_table); } } if (config.print_output & PRINT_OUTPUT_CUSTOM) { if (0 != custom_print_plugin.output_close()) { Log(LOG_ERR, "ERROR ( %s/%s ): Custom output: failed closing file %s: %s\n", config.name, config.type, current_table, custom_print_plugin.get_error_text()); exit_gracefully(1); } } #ifdef WITH_AVRO if (config.print_output & PRINT_OUTPUT_AVRO_BIN) { avro_file_writer_close(p_avro_writer); } #endif else { if (f) close_output_file(f); } } else { /* writing to stdout: releasing lock */ fflush(f); close_output_file(lockf); } /* If we have pending queries then start again */ if (pqq_ptr) goto start; Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, qn, saved_index, (long)duration); if (config.sql_trigger_exec && !safe_action) P_trigger_exec(config.sql_trigger_exec); if (empty_pcust) free(empty_pcust); } void P_write_stats_header_formatted(FILE *f, int is_event) { if (config.what_to_count & COUNT_TAG) fprintf(f, "TAG "); if (config.what_to_count & COUNT_TAG2) fprintf(f, "TAG2 "); if (config.what_to_count & COUNT_CLASS) fprintf(f, "CLASS "); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) fprintf(f, "CLASS "); #endif #if defined (HAVE_L2) if (config.what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) fprintf(f, "SRC_MAC "); if (config.what_to_count & COUNT_DST_MAC) fprintf(f, "DST_MAC "); if (config.what_to_count & COUNT_VLAN) { if (config.tmp_vlan_legacy) { fprintf(f, "VLAN "); } else { fprintf(f, "IN_VLAN "); } } if (config.what_to_count_2 & COUNT_OUT_VLAN) fprintf(f, "OUT_VLAN "); if (config.what_to_count & COUNT_COS) fprintf(f, "COS "); if (config.what_to_count & COUNT_ETHERTYPE) fprintf(f, "ETYPE "); #endif if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) fprintf(f, "SRC_AS "); if (config.what_to_count & COUNT_DST_AS) fprintf(f, "DST_AS "); if (config.what_to_count & COUNT_LOCAL_PREF) fprintf(f, "PREF "); if (config.what_to_count & COUNT_SRC_LOCAL_PREF) fprintf(f, "SRC_PREF "); if (config.what_to_count & COUNT_MED) fprintf(f, "MED "); if (config.what_to_count & COUNT_SRC_MED) fprintf(f, "SRC_MED "); if (config.what_to_count_2 & COUNT_SRC_ROA) fprintf(f, "SRC_ROA "); if (config.what_to_count_2 & COUNT_DST_ROA) fprintf(f, "DST_ROA "); if (config.what_to_count & COUNT_PEER_SRC_AS) fprintf(f, "PEER_SRC_AS "); if (config.what_to_count & COUNT_PEER_DST_AS) fprintf(f, "PEER_DST_AS "); if (config.what_to_count & COUNT_PEER_SRC_IP) fprintf(f, "PEER_SRC_IP "); if (config.what_to_count & COUNT_PEER_DST_IP) fprintf(f, "PEER_DST_IP "); if (config.what_to_count & COUNT_IN_IFACE) fprintf(f, "IN_IFACE "); if (config.what_to_count & COUNT_OUT_IFACE) fprintf(f, "OUT_IFACE "); if (config.what_to_count & COUNT_MPLS_VPN_RD) fprintf(f, "MPLS_VPN_RD "); if (config.what_to_count_2 & COUNT_MPLS_PW_ID) fprintf(f, "MPLS_PW_ID "); if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) fprintf(f, "SRC_IP "); if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) fprintf(f, "SRC_NET "); if (config.what_to_count & COUNT_DST_HOST) fprintf(f, "DST_IP "); if (config.what_to_count & COUNT_DST_NET) fprintf(f, "DST_NET "); if (config.what_to_count & COUNT_SRC_NMASK) fprintf(f, "SRC_MASK "); if (config.what_to_count & COUNT_DST_NMASK) fprintf(f, "DST_MASK "); if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) fprintf(f, "SRC_PORT "); if (config.what_to_count & COUNT_DST_PORT) fprintf(f, "DST_PORT "); if (config.what_to_count & COUNT_TCPFLAGS) fprintf(f, "TCP_FLAGS "); if (config.what_to_count & COUNT_IP_PROTO) fprintf(f, "PROTOCOL "); if (config.what_to_count & COUNT_IP_TOS) fprintf(f, "TOS "); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "SH_COUNTRY "); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "DH_COUNTRY "); #endif #if defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) fprintf(f, "SH_POCODE "); if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) fprintf(f, "DH_POCODE "); if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) { fprintf(f, "SH_LAT "); fprintf(f, "SH_LON "); } if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) { fprintf(f, "DH_LAT "); fprintf(f, "DH_LON "); } #endif if (config.what_to_count_2 & COUNT_SAMPLING_RATE) fprintf(f, "SAMPLING_RATE "); if (config.what_to_count_2 & COUNT_SAMPLING_DIRECTION) fprintf(f, "SAMPLING_DIRECTION "); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) fprintf(f, "POST_NAT_SRC_IP "); if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) fprintf(f, "POST_NAT_DST_IP "); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) fprintf(f, "POST_NAT_SRC_PORT "); if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) fprintf(f, "POST_NAT_DST_PORT "); if (config.what_to_count_2 & COUNT_NAT_EVENT) fprintf(f, "NAT_EVENT "); if (config.what_to_count_2 & COUNT_FW_EVENT) fprintf(f, "FW_EVENT "); if (config.what_to_count_2 & COUNT_FWD_STATUS) fprintf(f, "FWD_STATUS "); if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) fprintf(f, "MPLS_LABEL_TOP "); if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) fprintf(f, "MPLS_LABEL_BOTTOM "); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) fprintf(f, "TUNNEL_SRC_MAC "); if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) fprintf(f, "TUNNEL_DST_MAC "); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) fprintf(f, "TUNNEL_SRC_IP "); if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) fprintf(f, "TUNNEL_DST_IP "); if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) fprintf(f, "TUNNEL_PROTOCOL "); if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) fprintf(f, "TUNNEL_TOS "); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) fprintf(f, "TUNNEL_SRC_PORT "); if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) fprintf(f, "TUNNEL_DST_PORT "); if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) fprintf(f, "TUNNEL_TCP_FLAGS "); if (config.what_to_count_2 & COUNT_VXLAN) fprintf(f, "VXLAN "); if (config.what_to_count_2 & COUNT_TIMESTAMP_START) fprintf(f, "TIMESTAMP_START "); if (config.what_to_count_2 & COUNT_TIMESTAMP_END) fprintf(f, "TIMESTAMP_END "); if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) fprintf(f, "TIMESTAMP_ARRIVAL "); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) fprintf(f, "TIMESTAMP_EXPORT "); if (config.nfacctd_stitching) { fprintf(f, "TIMESTAMP_MIN "); fprintf(f, "TIMESTAMP_MAX "); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) fprintf(f, "EXPORT_PROTO_SEQNO "); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) fprintf(f, "EXPORT_PROTO_VERSION "); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) fprintf(f, "EXPORT_PROTO_SYSID "); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { custom_primitive_header_print(cp_str, SRVBUFLEN, &config.cpptrs.primitive[cp_idx], TRUE); fprintf(f, "%s ", cp_str); } } if (!is_event) { fprintf(f, "PACKETS "); if (config.what_to_count & COUNT_FLOWS) fprintf(f, "FLOWS "); fprintf(f, "BYTES\n"); } else fprintf(f, "\n"); } void P_write_stats_header_csv(FILE *f, int is_event) { char *sep = config.print_output_separator; int count = 0; if (config.what_to_count & COUNT_TAG) fprintf(f, "%sTAG", write_sep(sep, &count)); if (config.what_to_count & COUNT_TAG2) fprintf(f, "%sTAG2", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_LABEL) fprintf(f, "%sLABEL", write_sep(sep, &count)); if (config.what_to_count & COUNT_CLASS) fprintf(f, "%sCLASS", write_sep(sep, &count)); #if defined (WITH_NDPI) if (config.what_to_count_2 & COUNT_NDPI_CLASS) fprintf(f, "%sCLASS", write_sep(sep, &count)); #endif #if defined HAVE_L2 if (config.what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) fprintf(f, "%sSRC_MAC", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_MAC) fprintf(f, "%sDST_MAC", write_sep(sep, &count)); if (config.what_to_count & COUNT_VLAN) { if (config.tmp_vlan_legacy) { fprintf(f, "%sVLAN", write_sep(sep, &count)); } else { fprintf(f, "%sIN_VLAN", write_sep(sep, &count)); } } if (config.what_to_count_2 & COUNT_OUT_VLAN) fprintf(f, "%sOUT_VLAN", write_sep(sep, &count)); if (config.what_to_count & COUNT_COS) fprintf(f, "%sCOS", write_sep(sep, &count)); if (config.what_to_count & COUNT_ETHERTYPE) fprintf(f, "%sETYPE", write_sep(sep, &count)); #endif if (config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) fprintf(f, "%sSRC_AS", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_AS) fprintf(f, "%sDST_AS", write_sep(sep, &count)); if (config.what_to_count & COUNT_STD_COMM) fprintf(f, "%sCOMMS", write_sep(sep, &count)); if (config.what_to_count & COUNT_EXT_COMM) fprintf(f, "%sECOMMS", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_LRG_COMM) fprintf(f, "%sLCOMMS", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_STD_COMM) fprintf(f, "%sSRC_COMMS", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_EXT_COMM) fprintf(f, "%sSRC_ECOMMS", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_SRC_LRG_COMM) fprintf(f, "%sSRC_LCOMMS", write_sep(sep, &count)); if (config.what_to_count & COUNT_AS_PATH) fprintf(f, "%sAS_PATH", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_AS_PATH) fprintf(f, "%sSRC_AS_PATH", write_sep(sep, &count)); if (config.what_to_count & COUNT_LOCAL_PREF) fprintf(f, "%sPREF", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_LOCAL_PREF) fprintf(f, "%sSRC_PREF", write_sep(sep, &count)); if (config.what_to_count & COUNT_MED) fprintf(f, "%sMED", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_MED) fprintf(f, "%sSRC_MED", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_SRC_ROA) fprintf(f, "%sSRC_ROA", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_DST_ROA) fprintf(f, "%sDST_ROA", write_sep(sep, &count)); if (config.what_to_count & COUNT_PEER_SRC_AS) fprintf(f, "%sPEER_SRC_AS", write_sep(sep, &count)); if (config.what_to_count & COUNT_PEER_DST_AS) fprintf(f, "%sPEER_DST_AS", write_sep(sep, &count)); if (config.what_to_count & COUNT_PEER_SRC_IP) fprintf(f, "%sPEER_SRC_IP", write_sep(sep, &count)); if (config.what_to_count & COUNT_PEER_DST_IP) fprintf(f, "%sPEER_DST_IP", write_sep(sep, &count)); if (config.what_to_count & COUNT_IN_IFACE) fprintf(f, "%sIN_IFACE", write_sep(sep, &count)); if (config.what_to_count & COUNT_OUT_IFACE) fprintf(f, "%sOUT_IFACE", write_sep(sep, &count)); if (config.what_to_count & COUNT_MPLS_VPN_RD) fprintf(f, "%sMPLS_VPN_RD", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_MPLS_PW_ID) fprintf(f, "%sMPLS_PW_ID", write_sep(sep, &count)); if (config.what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) fprintf(f, "%sSRC_IP", write_sep(sep, &count)); if (config.what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) fprintf(f, "%sSRC_NET", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_HOST) fprintf(f, "%sDST_IP", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_NET) fprintf(f, "%sDST_NET", write_sep(sep, &count)); if (config.what_to_count & COUNT_SRC_NMASK) fprintf(f, "%sSRC_MASK", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_NMASK) fprintf(f, "%sDST_MASK", write_sep(sep, &count)); if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) fprintf(f, "%sSRC_PORT", write_sep(sep, &count)); if (config.what_to_count & COUNT_DST_PORT) fprintf(f, "%sDST_PORT", write_sep(sep, &count)); if (config.what_to_count & COUNT_TCPFLAGS) fprintf(f, "%sTCP_FLAGS", write_sep(sep, &count)); if (config.what_to_count & COUNT_IP_PROTO) fprintf(f, "%sPROTOCOL", write_sep(sep, &count)); if (config.what_to_count & COUNT_IP_TOS) fprintf(f, "%sTOS", write_sep(sep, &count)); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) fprintf(f, "%sSH_COUNTRY", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) fprintf(f, "%sDH_COUNTRY", write_sep(sep, &count)); #endif #if defined (WITH_GEOIPV2) if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) fprintf(f, "%sSH_POCODE", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) fprintf(f, "%sDH_POCODE", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) { fprintf(f, "%sSH_LAT", write_sep(sep, &count)); fprintf(f, "%sSH_LON", write_sep(sep, &count)); } if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) { fprintf(f, "%sDH_LAT", write_sep(sep, &count)); fprintf(f, "%sDH_LON", write_sep(sep, &count)); } #endif if (config.what_to_count_2 & COUNT_SAMPLING_RATE) fprintf(f, "%sSAMPLING_RATE", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_SAMPLING_DIRECTION) fprintf(f, "%sSAMPLING_DIRECTION", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) fprintf(f, "%sPOST_NAT_SRC_IP", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) fprintf(f, "%sPOST_NAT_DST_IP", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) fprintf(f, "%sPOST_NAT_SRC_PORT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) fprintf(f, "%sPOST_NAT_DST_PORT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_NAT_EVENT) fprintf(f, "%sNAT_EVENT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_FW_EVENT) fprintf(f, "%sFW_EVENT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_FWD_STATUS) fprintf(f, "%sFWD_STATUS", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) fprintf(f, "%sMPLS_LABEL_TOP", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) fprintf(f, "%sMPLS_LABEL_BOTTOM", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_MPLS_LABEL_STACK) fprintf(f, "%sMPLS_LABEL_STACK", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) fprintf(f, "%sTUNNEL_SRC_MAC", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) fprintf(f, "%sTUNNEL_DST_MAC", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) fprintf(f, "%sTUNNEL_SRC_IP", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) fprintf(f, "%sTUNNEL_DST_IP", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) fprintf(f, "%sTUNNEL_PROTOCOL", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) fprintf(f, "%sTUNNEL_TOS", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) fprintf(f, "%sTUNNEL_SRC_PORT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) fprintf(f, "%sTUNNEL_DST_PORT", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TUNNEL_TCPFLAGS) fprintf(f, "%sTUNNEL_TCP_FLAGS", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_VXLAN) fprintf(f, "%sVXLAN", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TIMESTAMP_START) fprintf(f, "%sTIMESTAMP_START", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TIMESTAMP_END) fprintf(f, "%sTIMESTAMP_END", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) fprintf(f, "%sTIMESTAMP_ARRIVAL", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_TIME) fprintf(f, "%sTIMESTAMP_EXPORT", write_sep(sep, &count)); if (config.nfacctd_stitching) { fprintf(f, "%sTIMESTAMP_MIN", write_sep(sep, &count)); fprintf(f, "%sTIMESTAMP_MAX", write_sep(sep, &count)); } if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) fprintf(f, "%sEXPORT_PROTO_SEQNO", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) fprintf(f, "%sEXPORT_PROTO_VERSION", write_sep(sep, &count)); if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) fprintf(f, "%sEXPORT_PROTO_SYSID", write_sep(sep, &count)); /* all custom primitives printed here */ { char cp_str[SRVBUFLEN]; int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { custom_primitive_header_print(cp_str, SRVBUFLEN, &config.cpptrs.primitive[cp_idx], FALSE); fprintf(f, "%s%s", write_sep(sep, &count), cp_str); } } if (!is_event) { fprintf(f, "%sPACKETS", write_sep(sep, &count)); if (config.what_to_count & COUNT_FLOWS) fprintf(f, "%sFLOWS", write_sep(sep, &count)); fprintf(f, "%sBYTES\n", write_sep(sep, &count)); } else fprintf(f, "\n"); } void P_fprintf_csv_string(FILE *f, struct pkt_vlen_hdr_primitives *pvlen, pm_cfgreg_t wtc, char *sep, char *empty_string) { char *string_ptr = NULL; vlen_prims_get(pvlen, wtc, &string_ptr); if (!string_ptr) string_ptr = empty_string; fprintf(f, "%s%s", sep, string_ptr); } pmacct-1.7.8/src/sfv5_module.h0000644000175000017500000000314714354105275015207 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SFV5_MODULE_H #define SFV5_MODULE_H #define IES_PER_SFV5_MODULES_DB_ENTRY 32 #define SFV5_MODULES_DB_ENTRIES 8 /* structures */ struct sfv5_modules_db_field { u_int32_t type; u_char *ptr; u_int32_t len; }; struct sfv5_modules_db { struct sfv5_modules_db_field ie[IES_PER_SFV5_MODULES_DB_ENTRY]; }; struct sfv5_modules_desc { u_int32_t type; /* ie. flow, counter, etc. */ struct sfv5_modules_db db[SFV5_MODULES_DB_ENTRIES]; }; /* functions */ extern void sfv5_modules_db_init(); extern struct sfv5_modules_db_field *sfv5_modules_db_get_ie(u_int32_t); extern struct sfv5_modules_db_field *sfv5_modules_get_next_ie(u_int32_t); extern struct sfv5_modules_db_field *sfv5_modules_db_get_next_ie(u_int32_t); extern struct sfv5_modules_desc sfv5_modules; #endif //SFV5_MODULE_H pmacct-1.7.8/src/nfacctd.h0000644000175000017500000004531114354105275014360 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NFACCTD_H #define NFACCTD_H /* NetFlow Export Version 5 Header Format */ struct struct_header_v5 { u_int16_t version; /* Version = 5 */ u_int16_t count; /* The number of records in PDU. */ u_int32_t SysUptime; /* Current time in msecs since router booted */ u_int32_t unix_secs; /* Current seconds since 0000 UTC 1970 */ u_int32_t unix_nsecs; /* Residual nanoseconds since 0000 UTC 1970 */ u_int32_t flow_sequence; /* Sequence number of total flows seen */ unsigned char engine_type; /* Type of flow switching engine (RP,VIP,etc.) */ unsigned char engine_id; /* Slot number of the flow switching engine */ u_int16_t sampling; }; /* NetFlow Export Version 9 Header Format */ struct struct_header_v9 { u_int16_t version; /* version = 9 */ u_int16_t count; /* The number of records in PDU. */ u_int32_t SysUptime; /* Current time in msecs since router booted */ u_int32_t unix_secs; /* Current seconds since 0000 UTC 1970 */ u_int32_t flow_sequence; /* Sequence number of total flows seen */ u_int32_t source_id; /* Source id */ }; struct struct_header_ipfix { u_int16_t version; /* version = 10 */ u_int16_t len; /* Total length of the IPFIX Message */ u_int32_t unix_secs; /* Current seconds since 0000 UTC 1970 */ u_int32_t flow_sequence; /* Sequence number of total flows seen */ u_int32_t source_id; /* Source id */ }; /* NetFlow Export version 5 */ struct struct_export_v5 { struct in_addr srcaddr; /* Source IP Address */ struct in_addr dstaddr; /* Destination IP Address */ struct in_addr nexthop; /* Next hop router's IP Address */ u_int16_t input; /* Input interface index */ u_int16_t output; /* Output interface index */ u_int32_t dPkts; /* Packets sent in Duration (milliseconds between 1st & last packet in this flow) */ u_int32_t dOctets; /* Octets sent in Duration (milliseconds between 1st & last packet in this flow) */ u_int32_t First; /* SysUptime at start of flow */ u_int32_t Last; /* and of last packet of the flow */ u_int16_t srcport; /* TCP/UDP source port number (.e.g, FTP, Telnet, etc.,or equivalent) */ u_int16_t dstport; /* TCP/UDP destination port number (.e.g, FTP, Telnet, etc.,or equivalent) */ unsigned char pad; /* pad to word boundary */ unsigned char tcp_flags; /* Cumulative OR of tcp flags */ unsigned char prot; /* IP protocol, e.g., 6=TCP, 17=UDP, etc... */ unsigned char tos; /* IP Type-of-Service */ u_int16_t src_as; /* source peer/origin Autonomous System */ u_int16_t dst_as; /* dst peer/origin Autonomous System */ unsigned char src_mask; /* source route's mask bits */ unsigned char dst_mask; /* destination route's mask bits */ u_int16_t pad_1; /* pad to word boundary */ }; /* NetFlow Export version 9 */ struct template_field_v9 { u_int16_t type; u_int16_t len; }; struct template_hdr_v9 { u_int16_t template_id; u_int16_t num; }; struct options_template_hdr_v9 { u_int16_t template_id; u_int16_t scope_len; u_int16_t option_len; }; /* IPFIX: option field count and scope field count apparently inverted compared to NetFlow v9 */ struct options_template_hdr_ipfix { u_int16_t template_id; u_int16_t option_count; u_int16_t scope_count; }; struct data_hdr_v9 { u_int16_t flow_id; /* == 0: template; == 1: options template; >= 256: data */ u_int16_t flow_len; }; /* defines */ #define DEFAULT_NFACCTD_PORT 2100 #define NETFLOW_MSG_SIZE PKT_MSG_SIZE #define V5_MAXFLOWS 30 /* max records in V5 packet */ #define TEMPLATE_CACHE_ENTRIES 1021 #define NF_TIME_MSECS 0 /* times are in msecs */ #define NF_TIME_SECS 1 /* times are in secs */ #define NF_TIME_NEW 2 /* ignore netflow engine times and generate new ones */ #define IPFIX_TPL_EBIT 0x8000 /* IPFIX telmplate enterprise bit */ #define IPFIX_VARIABLE_LENGTH 65535 #define PMACCT_PEN 43874 /* NetFlow V9 stuff */ #define NF9_TEMPLATE_FLOWSET_ID 0 #define NF9_OPTIONS_FLOWSET_ID 1 #define NF9_MIN_RECORD_FLOWSET_ID 256 #define NF9_MAX_DEFINED_FIELD 384 #define IES_PER_TPL_EXT_DB_ENTRY 32 #define TPL_EXT_DB_ENTRIES 8 #define TPL_LIST_ENTRIES 256 #define TPL_TYPE_LEGACY 0 #define TPL_TYPE_EXT_DB 1 /* Flowset record types the we care about */ #define NF9_IN_BYTES 1 #define NF9_IN_PACKETS 2 #define NF9_FLOWS 3 #define NF9_L4_PROTOCOL 4 #define NF9_SRC_TOS 5 #define NF9_TCP_FLAGS 6 #define NF9_L4_SRC_PORT 7 #define NF9_IPV4_SRC_ADDR 8 #define NF9_SRC_MASK 9 #define NF9_INPUT_SNMP 10 #define NF9_L4_DST_PORT 11 #define NF9_IPV4_DST_ADDR 12 #define NF9_DST_MASK 13 #define NF9_OUTPUT_SNMP 14 #define NF9_IPV4_NEXT_HOP 15 #define NF9_SRC_AS 16 #define NF9_DST_AS 17 #define NF9_BGP_IPV4_NEXT_HOP 18 #define NF9_MUL_DST_PKTS 19 #define NF9_MUL_DST_BYTES 20 /* ... */ #define NF9_LAST_SWITCHED 21 #define NF9_FIRST_SWITCHED 22 #define NF9_OUT_BYTES 23 #define NF9_OUT_PACKETS 24 /* ... */ #define NF9_IPV6_SRC_ADDR 27 #define NF9_IPV6_DST_ADDR 28 #define NF9_IPV6_SRC_MASK 29 #define NF9_IPV6_DST_MASK 30 #define NF9_ICMP_TYPE 32 /* ... */ #define NF9_ENGINE_TYPE 38 #define NF9_ENGINE_ID 39 /* ... */ #define NF9_IPV4_SRC_PREFIX 44 #define NF9_IPV4_DST_PREFIX 45 /* ... */ #define NF9_MPLS_TOP_LABEL_ADDR 47 /* ... */ #define NF9_IN_SRC_MAC 56 #define NF9_OUT_DST_MAC 57 #define NF9_IN_VLAN 58 #define NF9_OUT_VLAN 59 #define NF9_IP_PROTOCOL_VERSION 60 #define NF9_DIRECTION 61 #define NF9_IPV6_NEXT_HOP 62 #define NF9_BGP_IPV6_NEXT_HOP 63 /* ... */ #define NF9_MPLS_LABEL_1 70 #define NF9_MPLS_LABEL_2 71 #define NF9_MPLS_LABEL_3 72 #define NF9_MPLS_LABEL_4 73 #define NF9_MPLS_LABEL_5 74 #define NF9_MPLS_LABEL_6 75 #define NF9_MPLS_LABEL_7 76 #define NF9_MPLS_LABEL_8 77 #define NF9_MPLS_LABEL_9 78 #define NF9_MPLS_LABEL_10 79 #define NF9_IN_DST_MAC 80 #define NF9_OUT_SRC_MAC 81 /* ... */ #define NF9_FLOW_BYTES 85 #define NF9_FLOW_PACKETS 86 /* ... */ #define NF9_FWD_STATUS 89 #define NF9_MPLS_VPN_RD 90 /* ... */ #define NF9_LAYER2_PKT_SECTION_DATA 104 /* ... */ #define NF9_PEER_DST_AS 128 #define NF9_PEER_SRC_AS 129 #define NF9_EXPORTER_IPV4_ADDRESS 130 #define NF9_EXPORTER_IPV6_ADDRESS 131 /* ... */ #define NF9_MPLS_TOP_LABEL_IPV6_ADDR 140 /* ... */ #define NF9_FIRST_SWITCHED_SEC 150 #define NF9_LAST_SWITCHED_SEC 151 #define NF9_FIRST_SWITCHED_MSEC 152 #define NF9_LAST_SWITCHED_MSEC 153 #define NF9_FIRST_SWITCHED_USEC 154 #define NF9_LAST_SWITCHED_USEC 155 /* ... */ #define NF9_FIRST_SWITCHED_DELTA_MICRO 158 #define NF9_LAST_SWITCHED_DELTA_MICRO 159 #define NF9_SYS_UPTIME_MSEC 160 /* ... */ #define NF9_IPV6_DST_PREFIX 169 #define NF9_IPV6_SRC_PREFIX 170 /* ... */ #define NF9_UDP_SRC_PORT 180 #define NF9_UDP_DST_PORT 181 #define NF9_TCP_SRC_PORT 182 #define NF9_TCP_DST_PORT 183 /* ... */ #define NF9_POST_NAT_IPV4_SRC_ADDR 225 #define NF9_POST_NAT_IPV4_DST_ADDR 226 #define NF9_POST_NAT_IPV4_SRC_PORT 227 #define NF9_POST_NAT_IPV4_DST_PORT 228 /* ... */ #define NF9_NAT_EVENT 230 /* ... */ #define NF9_INITIATOR_OCTETS 231 #define NF9_RESPONDER_OCTETS 232 #define NF9_FW_EVENT 233 #define NF9_INGRESS_VRFID 234 #define NF9_EGRESS_VRFID 235 /* ... */ #define NF9_DOT1QVLANID 243 #define NF9_DOT1QPRIORITY 244 #define NF9_DOT1QCVLANID 245 /* ... */ #define NF9_PSEUDOWIREID 249 /* ... */ #define NF9_INPUT_PHYSINT 252 #define NF9_OUTPUT_PHYSINT 253 #define NF9_POST_DOT1QVLANID 254 #define NF9_POST_DOT1QCVLANID 255 #define NF9_ETHERTYPE 256 /* ... */ #define NF9_DATALINK_FRAME_SECTION 315 /* ... */ #define NF9_OBSERVATION_TIME_SEC 322 #define NF9_OBSERVATION_TIME_MSEC 323 /* ... */ #define NF9_LAYER2_SEGMENT_ID 351 #define NF9_LAYER2OCTETDELTACOUNT 352 /* ... */ #define NF9_DATALINK_FRAME_TYPE 408 /* ... */ #define NF9_ASA_XLATE_IPV4_SRC_ADDR 40001 #define NF9_ASA_XLATE_IPV4_DST_ADDR 40002 #define NF9_ASA_XLATE_L4_SRC_PORT 40003 #define NF9_ASA_XLATE_L4_DST_PORT 40004 #define NF9_ASA_XLATE_EVENT 40005 /* Sampling */ #define NF9_SAMPLING_INTERVAL 34 #define NF9_SAMPLING_ALGORITHM 35 #define NF9_FLOW_SAMPLER_ID 48 #define NF9_FLOW_SAMPLER_MODE 49 #define NF9_FLOW_SAMPLER_INTERVAL 50 #define NF9_SELECTOR_ID 302 #define NF9_SELECTOR_ALGORITHM 304 #define NF9_SAMPLING_PKT_INTERVAL 305 #define NF9_SAMPLING_PKT_SPACE 306 /* Classification */ #define NF9_APPLICATION_DESC 94 #define NF9_APPLICATION_ID 95 #define NF9_APPLICATION_NAME 96 /* Options scoping: NetFlow v9 */ #define NF9_OPT_SCOPE_SYSTEM 1 #define NF9_OPT_SCOPE_IF 2 #define NF9_OPT_SCOPE_LC 3 #define NF9_OPT_SCOPE_CACHE 4 #define NF9_OPT_SCOPE_TPL 5 /* Options scoping: IPFIX */ #define IPFIX_SCOPE_OBS_POINT_ID 138 #define IPFIX_SCOPE_LINECARD_ID 141 #define IPFIX_SCOPE_PORT_ID 142 #define IPFIX_SCOPE_METER_PROCESS_ID 143 #define IPFIX_SCOPE_EXPORT_PROCESS_ID 144 #define IPFIX_SCOPE_TEMPLATE_ID 145 #define IPFIX_SCOPE_OBS_DOMAIN_ID 149 /* dataLinkFrameType */ #define NF9_DL_F_TYPE_UNKNOWN 0 #define NF9_DL_F_TYPE_ETHERNET 1 #define NF9_DL_F_TYPE_802DOT11 2 /* layer2SegmentId */ #define NF9_L2_SID_RESERVED 0x00 #define NF9_L2_SID_VXLAN 0x01 #define NF9_L2_SID_NVGRE 0x02 /* CUSTOM TYPES START HERE: supported in IPFIX only with pmacct PEN */ #define NF9_CUST_TAG 1 #define NF9_CUST_TAG2 2 #define NF9_CUST_LABEL 3 /* CUSTOM TYPES END HERE */ #define MAX_TPL_DESC_LIST 90 static char __attribute__((unused)) *tpl_desc_list[] = { "", "in bytes", "in packets", "flows", "L4 protocol", "tos", "tcp flags", "L4 src port", "IPv4 src addr", "IPv4 src mask", "input snmp", "L4 dst port", "IPv4 dst addr", "IPv4 dst mask", "output snmp", "IPv4 next hop", "src as", "dst as", "BGP IPv4 next hop", "", "", "last switched", "first switched", "out bytes", "out packets", "", "", "IPv6 src addr", "IPv6 dst addr", "IPv6 src mask", "IPv6 dst mask", "", "icmp type", "", "sampling interval", "sampling algorithm", "", "", "", "", "", "", "", "", "", "", "", "", "sampler ID", "sampler mode", "sampler interval", "", "", "", "", "", "in src mac", "out dst mac", "", "", "ip version", "direction", "IPv6 next hop", "IPv6 BGP next hop", "", "", "", "", "", "", "mpls label 1", "mpls label 2", "mpls label 3", "mpls label 4", "mpls label 5", "mpls label 6", "mpls label 7", "mpls label 8", "mpls label 9", "mpls label 10", "in dst mac", "out src mac", "", "", "", "", "", "", "", "forwarding status", "mpls vpn rd" }; #define MAX_OPT_TPL_DESC_LIST 100 static char __attribute__((unused)) *opt_tpl_desc_list[] = { "", "scope", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "sampler ID", "sampler algorithm", "sampler interval", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "sampler name", "", "", "", "", "", "", "", "", "", "app desc", "app id", "app name", "", "", "", "" }; /* Ordered Template field */ struct otpl_field { u_int16_t off; u_int16_t len; u_int16_t tpl_len; }; /* Unsorted Template field */ struct utpl_field { u_int32_t pen; u_int16_t type; u_int16_t off; u_int16_t len; u_int16_t tpl_len; u_int8_t repeat_id; }; /* Template field database */ struct tpl_field_db { struct utpl_field ie[IES_PER_TPL_EXT_DB_ENTRY]; }; /* Template field ordered list */ struct tpl_field_list { u_int8_t type; char *ptr; }; struct template_cache_entry { struct host_addr agent; /* NetFlow Exporter agent */ u_int32_t source_id; /* Exporter Observation Domain */ u_int16_t template_id; /* template ID */ u_int16_t template_type; /* Data = 0, Options = 1 */ u_int16_t num; /* number of fields described into template */ u_int16_t len; /* total length of the described flowset */ u_int8_t vlen; /* flag for variable-length fields */ struct otpl_field tpl[NF9_MAX_DEFINED_FIELD]; struct tpl_field_db ext_db[TPL_EXT_DB_ENTRIES]; struct tpl_field_list list[TPL_LIST_ENTRIES]; struct template_cache_entry *next; }; struct template_cache { u_int16_t num; struct template_cache_entry *c[TEMPLATE_CACHE_ENTRIES]; }; struct NF_dissect { u_int8_t hdrVersion; u_int16_t hdrCount; /* NetFlow v5 and v5 and v5 and v5 and v5 and v9 */ u_char *hdrBasePtr; u_char *hdrEndPtr; u_int32_t hdrLen; u_char *flowSetBasePtr; u_char *flowSetEndPtr; u_int32_t flowSetLen; u_char *elemBasePtr; u_char *elemEndPtr; u_int32_t elemLen; }; /* functions */ extern void process_v5_packet(unsigned char *, u_int16_t, struct packet_ptrs *, struct plugin_requests *, u_int16_t, struct NF_dissect *); extern void process_v9_packet(unsigned char *, u_int16_t, struct packet_ptrs_vector *, struct plugin_requests *, u_int16_t, struct NF_dissect *, int *); extern void process_raw_packet(unsigned char *, u_int16_t, struct packet_ptrs_vector *, struct plugin_requests *); extern void NF_evaluate_flow_type(struct flow_chars *, struct template_cache_entry *, struct packet_ptrs *); extern u_int16_t NF_evaluate_direction(struct template_cache_entry *, struct packet_ptrs *); extern void NF_process_classifiers(struct packet_ptrs *, struct packet_ptrs *, unsigned char *, struct template_cache_entry *); extern pm_class_t NF_evaluate_classifiers(struct xflow_status_entry_class *, pm_class_t *, struct xflow_status_entry *); extern void reset_mac(struct packet_ptrs *); extern void reset_mac_vlan(struct packet_ptrs *); extern void reset_ip4(struct packet_ptrs *); extern void reset_ip6(struct packet_ptrs *); extern void reset_dummy_v4(struct packet_ptrs *, u_char *); extern void notify_malf_packet(short int, char *, char *, struct sockaddr *, u_int32_t); extern int NF_find_id(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); extern void NF_compute_once(); extern struct xflow_status_entry *nfv5_check_status(struct packet_ptrs *); extern struct xflow_status_entry *nfv9_check_status(struct packet_ptrs *, u_int32_t, u_int32_t, u_int32_t, u_int8_t); extern void nfv9_datalink_frame_section_handler(struct packet_ptrs *); extern struct template_cache tpl_cache; extern cdada_map_t *tpl_data_map, *tpl_opt_map; extern struct host_addr debug_a; extern char debug_agent_addr[50]; extern u_int16_t debug_agent_port; extern u_int16_t modulo_template(u_int16_t, struct sockaddr *, u_int16_t); extern struct template_cache_entry *handle_template(struct template_hdr_v9 *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int16_t, u_int32_t); extern struct template_cache_entry *find_template(u_int16_t, struct sockaddr *, u_int16_t, u_int32_t); extern struct template_cache_entry *insert_template(struct template_hdr_v9 *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); extern struct template_cache_entry *refresh_template(struct template_hdr_v9 *, struct template_cache_entry *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); extern void log_template_header(struct template_cache_entry *, struct sockaddr *, u_int16_t, u_int32_t, u_int8_t); extern void log_opt_template_field(u_int8_t, u_int32_t *, u_int16_t, u_int16_t, u_int16_t, u_int8_t); extern void log_template_field(u_int8_t, u_int32_t *, u_int16_t, u_int16_t, u_int16_t, u_int8_t); extern void log_template_footer(struct template_cache_entry *, u_int16_t, u_int8_t); extern struct template_cache_entry *insert_opt_template(void *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); extern struct template_cache_entry *refresh_opt_template(void *, struct template_cache_entry *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); extern struct utpl_field *ext_db_get_ie(struct template_cache_entry *, u_int32_t, u_int16_t, u_int8_t); extern struct utpl_field *ext_db_get_next_ie(struct template_cache_entry *, u_int16_t, u_int8_t *); extern int resolve_vlen_template(u_char *, u_int16_t, struct template_cache_entry *); extern int get_ipfix_vlen(u_char *, u_int16_t, u_int16_t *); extern struct template_cache_entry *nfacctd_offline_read_json_template(char *, char *, int); extern void load_templates_from_file(char *); extern void save_template(struct template_cache_entry *, char *); extern u_int16_t calc_template_keylen(); extern u_char *compose_template_key(pm_hash_serial_t *, u_int16_t, struct sockaddr *, u_int32_t); extern struct template_cache_entry *handle_template_v2(struct template_hdr_v9 *, struct packet_ptrs *, u_int16_t, u_int32_t, u_int16_t *, u_int16_t, u_int32_t); extern struct template_cache_entry *compose_template(struct template_hdr_v9 *, struct sockaddr *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); extern struct template_cache_entry *compose_opt_template(void *, struct sockaddr *, u_int16_t, u_int32_t, u_int16_t *, u_int8_t, u_int16_t, u_int32_t); #ifdef WITH_KAFKA extern void NF_init_kafka_host(void *); #endif #ifdef WITH_ZMQ extern void NF_init_zmq_host(void *, int *); #endif extern void NF_mpls_vpn_rd_fromie90(struct packet_ptrs *); extern struct utpl_field *(*get_ext_db_ie_by_type)(struct template_cache_entry *, u_int32_t, u_int16_t, u_int8_t); #endif //NFACCTD_H pmacct-1.7.8/src/kafka_plugin.c0000644000175000017500000010043414354105275015402 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "kafka_common.h" #include "plugin_cmn_json.h" #include "plugin_cmn_avro.h" #include "kafka_plugin.h" #ifndef WITH_JANSSON #error "--enable-kafka requires --enable-jansson" #endif /* Functions */ void kafka_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; unsigned char *pipebuf; struct pollfd pfd; struct insert_data idata; int timeout, refresh_timeout; int ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; unsigned char *dataptr; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "Kafka Plugin", config.name); P_set_signals(); P_init_default_values(); P_config_checks(); pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); timeout = config.sql_refresh_time*1000; if (!config.message_broker_output) config.message_broker_output = PRINT_OUTPUT_JSON; if (config.message_broker_output & PRINT_OUTPUT_JSON) { compose_json(config.what_to_count, config.what_to_count_2); } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO p_avro_acct_schema = p_avro_schema_build_acct_data(config.what_to_count, config.what_to_count_2); p_avro_schema_add_writer_id(p_avro_acct_schema); p_avro_acct_init_schema = p_avro_schema_build_acct_init(); p_avro_acct_close_schema = p_avro_schema_build_acct_close(); if (config.avro_schema_file) { char avro_schema_file[SRVBUFLEN]; if (strlen(config.avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'avro_schema_file' too long. Exiting.\n", config.name, config.type); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_data", avro_schema_file, p_avro_acct_schema); write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_init", avro_schema_file, p_avro_acct_init_schema); write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_close", avro_schema_file, p_avro_acct_close_schema); } if (config.kafka_avro_schema_registry) { #ifdef WITH_SERDES if (config.sql_multi_values) { Log(LOG_ERR, "ERROR ( %s/%s ): 'kafka_avro_schema_registry' is not compatible with 'kafka_multi_values'. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { Log(LOG_ERR, "ERROR ( %s/%s ): 'kafka_avro_schema_registry' is not compatible with 'avro_json' output. Exiting.\n", config.name, config.type); exit_gracefully(1); } #else Log(LOG_ERR, "ERROR ( %s/%s ): 'kafka_avro_schema_registry' requires --enable-serdes. Exiting.\n", config.name, config.type); exit_gracefully(1); #endif } #endif } if ((config.sql_table && strchr(config.sql_table, '$')) && config.sql_multi_values) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'kafka_topic' is not compatible with 'kafka_multi_values'. Exiting.\n", config.name, config.type); exit_gracefully(1); } if ((config.sql_table && strchr(config.sql_table, '$')) && config.amqp_routing_key_rr) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'kafka_topic' is not compatible with 'kafka_topic_rr'. Exiting.\n", config.name, config.type); exit_gracefully(1); } /* setting function pointers */ if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) insert_func = P_sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) insert_func = P_sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) insert_func = P_sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) insert_func = P_sum_mac_insert; #endif else insert_func = P_cache_insert; purge_func = kafka_cache_purge; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); memset(&idata, 0, sizeof(idata)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); set_primptrs_funcs(&extras); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); idata.now = time(NULL); /* print_refresh time init: deadline */ refresh_deadline = idata.now; P_init_refresh_deadline(&refresh_deadline, config.sql_refresh_time, config.sql_startup_delay, config.sql_history_roundoff); if (config.sql_history) { basetime_init = P_init_historical_acct; basetime_eval = P_eval_historical_acct; basetime_cmp = P_cmp_historical_acct; (*basetime_init)(idata.now); } /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* setting some defaults */ if (!config.sql_host) config.sql_host = default_kafka_broker_host; if (!config.kafka_broker_port) config.kafka_broker_port = default_kafka_broker_port; if (!config.sql_table) config.sql_table = default_kafka_topic; p_kafka_init_host_struct(&kafkap_kafka_host); #if defined(WITH_AVRO) && defined(WITH_SERDES) if (config.kafka_avro_schema_registry) { if (strchr(config.sql_table, '$')) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'kafka_topic' is not compatible with 'avro_schema_registry'. Exiting.\n", config.name, config.type); exit_gracefully(1); } kafkap_kafka_host.sd_schema[AVRO_ACCT_DATA_SID] = compose_avro_schema_registry_name_2(config.sql_table, FALSE, p_avro_acct_schema, "acct", "data", config.kafka_avro_schema_registry); kafkap_kafka_host.sd_schema[AVRO_ACCT_INIT_SID] = compose_avro_schema_registry_name_2(config.sql_table, FALSE, p_avro_acct_init_schema, "acct", "init", config.kafka_avro_schema_registry); kafkap_kafka_host.sd_schema[AVRO_ACCT_CLOSE_SID] = compose_avro_schema_registry_name_2(config.sql_table, FALSE, p_avro_acct_close_schema, "acct", "close", config.kafka_avro_schema_registry); if (!kafkap_kafka_host.sd_schema[AVRO_ACCT_DATA_SID] || !kafkap_kafka_host.sd_schema[AVRO_ACCT_INIT_SID] || !kafkap_kafka_host.sd_schema[AVRO_ACCT_CLOSE_SID]) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to register schema information. Exiting.\n", config.name, config.type); exit_gracefully(1); } } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; timeout = refresh_timeout; /* in case we have more timeouts to factor in */ ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: P_update_time_reference(&idata); if (idata.now > refresh_deadline) P_cache_handle_flush_event(&pt, &prt, &tost); recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } void kafka_cache_purge(struct chained_cache *queue[], int index, int safe_action) { struct pkt_primitives *data = NULL; struct pkt_bgp_primitives *pbgp = NULL; struct pkt_nat_primitives *pnat = NULL; struct pkt_mpls_primitives *pmpls = NULL; struct pkt_tunnel_primitives *ptun = NULL; u_char *pcust = NULL; struct pkt_vlen_hdr_primitives *pvlen = NULL; struct pkt_bgp_primitives empty_pbgp; struct pkt_nat_primitives empty_pnat; struct pkt_mpls_primitives empty_pmpls; struct pkt_tunnel_primitives empty_ptun; u_char *empty_pcust = NULL; char dyn_kafka_topic[SRVBUFLEN], *orig_kafka_topic = NULL; char elem_part_key[SRVBUFLEN], tmpbuf[SRVBUFLEN]; int j, stop, is_topic_dyn = FALSE, qn = 0, ret, saved_index = index; int mv_num = 0, mv_num_save = 0; time_t start, duration; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); struct dynname_tokens writer_id_tokens; //TODO solve these warnings correctly (void)pvlen; (void)pcust; (void)ptun; (void)pmpls; (void)pnat; (void)pbgp; (void)data; char *json_buf = NULL; int json_buf_off = 0; #ifdef WITH_AVRO avro_writer_t p_avro_writer = {0}; char *p_avro_buf = NULL; int p_avro_buffer_full = FALSE; size_t p_avro_len = 0; #endif p_kafka_init_host_conf(&kafkap_kafka_host, config.kafka_config_file); if (strchr(config.sql_table, '$')) { is_topic_dyn = TRUE; orig_kafka_topic = config.sql_table; } if (config.amqp_routing_key_rr) orig_kafka_topic = config.sql_table; p_kafka_init_topic_rr(&kafkap_kafka_host); p_kafka_set_topic_rr(&kafkap_kafka_host, config.amqp_routing_key_rr); empty_pcust = malloc(config.cpptrs.len); if (!empty_pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() empty_pcust. Exiting.\n", config.name, config.type); exit_gracefully(1); } memset(&empty_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&empty_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&empty_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&empty_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(empty_pcust, 0, config.cpptrs.len); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); memset(&dummy_data, 0, sizeof(dummy_data)); memset(tmpbuf, 0, sizeof(tmpbuf)); p_kafka_connect_to_produce(&kafkap_kafka_host); p_kafka_set_broker(&kafkap_kafka_host, config.sql_host, config.kafka_broker_port); if (config.kafka_partition_key && strchr(config.kafka_partition_key, '$')) dyn_partition_key = TRUE; else dyn_partition_key = FALSE; if (!is_topic_dyn && !config.amqp_routing_key_rr) p_kafka_set_topic(&kafkap_kafka_host, config.sql_table); if (config.kafka_partition_dynamic && !config.kafka_partition_key) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_partition_dynamic needs a kafka_partition_key to operate. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (config.kafka_partition_dynamic && config.kafka_partition) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_partition_dynamic and kafka_partition are mutually exclusive. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (!config.kafka_partition_dynamic && !config.kafka_partition) config.kafka_partition = RD_KAFKA_PARTITION_UA; p_kafka_set_partition(&kafkap_kafka_host, config.kafka_partition); if (!dyn_partition_key) p_kafka_set_key(&kafkap_kafka_host, config.kafka_partition_key, config.kafka_partition_keylen); if (config.message_broker_output & PRINT_OUTPUT_JSON) p_kafka_set_content_type(&kafkap_kafka_host, PM_KAFKA_CNT_TYPE_STR); else if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) p_kafka_set_content_type(&kafkap_kafka_host, PM_KAFKA_CNT_TYPE_BIN); else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) p_kafka_set_content_type(&kafkap_kafka_host, PM_KAFKA_CNT_TYPE_STR); else { Log(LOG_ERR, "ERROR ( %s/%s ): Unsupported kafka_output value specified. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (!config.writer_id_string) { config.writer_id_string = DYNNAME_DEFAULT_WRITER_ID; } dynname_tokens_prepare(config.writer_id_string, &writer_id_tokens, DYN_STR_WRITER_ID); for (j = 0, stop = 0; (!stop) && P_preprocess_funcs[j]; j++) stop = P_preprocess_funcs[j](queue, &index, j); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); #if defined(WITH_AVRO) && defined(WITH_SERDES) if (config.kafka_avro_schema_registry) { if (is_topic_dyn) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'kafka_topic' is not compatible with 'avro_schema_registry'. Exiting.\n", config.name, config.type); exit_gracefully(1); } } #endif if (config.message_broker_output & PRINT_OUTPUT_JSON) { if (config.sql_multi_values) { json_buf = malloc(config.sql_multi_values); if (!json_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (json_buf). Exiting ..\n", config.name, config.type); exit_gracefully(1); } else memset(json_buf, 0, config.sql_multi_values); } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (!config.avro_buffer_size) config.avro_buffer_size = LARGEBUFLEN; p_avro_buf = malloc(config.avro_buffer_size); if (!p_avro_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (p_avro_buf). Exiting ..\n", config.name, config.type); exit_gracefully(1); } else { memset(p_avro_buf, 0, config.avro_buffer_size); } if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { p_avro_writer = avro_writer_memory(p_avro_buf, config.avro_buffer_size); } #endif } if (config.print_markers) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { void *json_obj = NULL; char *json_str = NULL; json_obj = compose_purge_init_json(config.name, writer_pid); if (json_obj) json_str = compose_json_str(json_obj); if (json_str) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_kafka_produce_data(&kafkap_kafka_host, json_str, strlen(json_str)); free(json_str); json_str = NULL; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_init_schema); avro_value_t p_avro_value = compose_avro_acct_init(config.name, writer_pid, p_avro_iface); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { if (!config.kafka_avro_schema_registry) { p_avro_len = avro_writer_tell(p_avro_writer); } #ifdef WITH_SERDES else { void *p_avro_local_buf = NULL; if (serdes_schema_serialize_avro(kafkap_kafka_host.sd_schema[AVRO_ACCT_INIT_SID], &p_avro_value, &p_avro_local_buf, &p_avro_len, kafkap_kafka_host.errstr, sizeof(kafkap_kafka_host.errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): serdes_schema_serialize_avro() failed for %s: %s\n", config.name, config.type, "acct_init", kafkap_kafka_host.errstr); exit_gracefully(1); } else { p_avro_buf = p_avro_local_buf; } } #endif ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, p_avro_len); if (!config.kafka_avro_schema_registry) avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_local_buf, strlen(p_avro_local_buf)); free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #endif } } for (j = 0; j < index; j++) { char *json_str = NULL; if (queue[j]->valid != PRINT_CACHE_COMMITTED) continue; data = &queue[j]->primitives; if (queue[j]->pbgp) pbgp = queue[j]->pbgp; else pbgp = &empty_pbgp; if (queue[j]->pnat) pnat = queue[j]->pnat; else pnat = &empty_pnat; if (queue[j]->pmpls) pmpls = queue[j]->pmpls; else pmpls = &empty_pmpls; if (queue[j]->ptun) ptun = queue[j]->ptun; else ptun = &empty_ptun; if (queue[j]->pcust) pcust = queue[j]->pcust; else pcust = empty_pcust; if (queue[j]->pvlen) pvlen = queue[j]->pvlen; else pvlen = NULL; if (queue[j]->valid == PRINT_CACHE_FREE) continue; if (dyn_partition_key) { prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(elem_part_key, SRVBUFLEN, config.kafka_partition_key, &prim_ptrs, DYN_STR_KAFKA_PART); p_kafka_set_key(&kafkap_kafka_host, elem_part_key, strlen(elem_part_key)); } if (config.message_broker_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *json_obj = json_object(); int idx; for (idx = 0; idx < N_PRIMITIVES && cjhandler[idx]; idx++) cjhandler[idx](json_obj, queue[j]); add_writer_name_and_pid_json(json_obj, &writer_id_tokens); json_str = compose_json_str(json_obj); #endif } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_schema); avro_value_t p_avro_value = compose_avro_acct_data(config.what_to_count, config.what_to_count_2, queue[j]->flow_type, &queue[j]->primitives, pbgp, pnat, pmpls, ptun, pcust, pvlen, queue[j]->bytes_counter, queue[j]->packet_counter, queue[j]->flow_counter, queue[j]->tcp_flags, queue[j]->tunnel_tcp_flags, &queue[j]->basetime, queue[j]->stitch, p_avro_iface); add_writer_name_and_pid_avro_v2(p_avro_value, &writer_id_tokens); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { size_t p_avro_value_size; avro_value_sizeof(&p_avro_value, &p_avro_value_size); if (!config.kafka_avro_schema_registry) { if (p_avro_value_size > config.avro_buffer_size) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): avro_buffer_size too small (%u)\n", config.name, config.type, config.avro_buffer_size); exit_gracefully(1); } else if (p_avro_value_size >= (config.avro_buffer_size - avro_writer_tell(p_avro_writer))) { p_avro_buffer_full = TRUE; j--; } else if (avro_value_write(p_avro_writer, &p_avro_value)) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): avro_value_write() faiiled: %s\n", config.name, config.type, avro_strerror()); exit_gracefully(1); } else { mv_num++; } p_avro_len = avro_writer_tell(p_avro_writer); } #ifdef WITH_SERDES else { void *p_avro_local_buf = NULL; p_avro_len = 0; if (p_avro_buf) { free(p_avro_buf); p_avro_buf = NULL; } if (serdes_schema_serialize_avro(kafkap_kafka_host.sd_schema[AVRO_ACCT_DATA_SID], &p_avro_value, &p_avro_local_buf, &p_avro_len, kafkap_kafka_host.errstr, sizeof(kafkap_kafka_host.errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): serdes_schema_serialize_avro() failed for %s: %s\n", config.name, config.type, "acct_data", kafkap_kafka_host.errstr); exit_gracefully(1); } else { p_avro_buf = p_avro_local_buf; mv_num++; } } #endif } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { size_t p_avro_locbuf_len = strlen(p_avro_local_buf); if (p_avro_locbuf_len > config.avro_buffer_size) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): avro_buffer_size too small (%u)\n", config.name, config.type, config.avro_buffer_size); exit_gracefully(1); } else if (p_avro_locbuf_len >= (config.avro_buffer_size - strlen(p_avro_buf))) { p_avro_buffer_full = TRUE; j--; } else { strcat(p_avro_buf, p_avro_local_buf); mv_num++; } free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #else if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_avro_acct_data(): AVRO object not created due to missing --enable-avro\n", config.name, config.type); #endif } if (config.message_broker_output & PRINT_OUTPUT_JSON) { char *tmp_str = NULL; if (json_str && config.sql_multi_values) { int json_strlen = (strlen(json_str) ? (strlen(json_str) + 1) : 0); if (json_strlen >= (config.sql_multi_values - json_buf_off)) { if (json_strlen >= config.sql_multi_values) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_multi_values not large enough to store JSON elements. Exiting ..\n", config.name, config.type); exit_gracefully(1); } tmp_str = json_str; json_str = json_buf; } else { strcat(json_buf, json_str); mv_num++; string_add_newline(json_buf); json_buf_off = strlen(json_buf); free(json_str); json_str = NULL; } } if (json_str) { if (is_topic_dyn) { prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &prim_ptrs, DYN_STR_KAFKA_TOPIC); p_kafka_set_topic(&kafkap_kafka_host, dyn_kafka_topic); } if (config.amqp_routing_key_rr) { P_handle_table_dyn_rr(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &kafkap_kafka_host.topic_rr); p_kafka_set_topic(&kafkap_kafka_host, dyn_kafka_topic); } Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_kafka_produce_data(&kafkap_kafka_host, json_str, strlen(json_str)); if (config.sql_multi_values) { json_str = tmp_str; strcpy(json_buf, json_str); mv_num_save = mv_num; mv_num = 1; string_add_newline(json_buf); json_buf_off = strlen(json_buf); } free(json_str); json_str = NULL; if (!ret) { if (!config.sql_multi_values) qn++; else qn += mv_num_save; } else break; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (!config.sql_multi_values || (mv_num >= config.sql_multi_values) || p_avro_buffer_full) { if (is_topic_dyn) { prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &prim_ptrs, DYN_STR_KAFKA_TOPIC); p_kafka_set_topic(&kafkap_kafka_host, dyn_kafka_topic); } if (config.amqp_routing_key_rr) { P_handle_table_dyn_rr(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &kafkap_kafka_host.topic_rr); p_kafka_set_topic(&kafkap_kafka_host, dyn_kafka_topic); } if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, p_avro_len); if (!config.kafka_avro_schema_registry) avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, strlen(p_avro_buf)); memset(p_avro_buf, 0, config.avro_buffer_size); } p_avro_buffer_full = FALSE; mv_num_save = mv_num; mv_num = 0; if (!ret) qn += mv_num_save; else break; } #endif } } if (config.sql_multi_values) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { if (json_buf && json_buf_off) { /* no handling of dyn routing keys here: not compatible */ Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_buf); ret = p_kafka_produce_data(&kafkap_kafka_host, json_buf, strlen(json_buf)); if (!ret) qn += mv_num; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { if (p_avro_len) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, p_avro_len); if (!config.kafka_avro_schema_registry) avro_writer_free(p_avro_writer); if (!ret) qn += mv_num; } } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { if (strlen(p_avro_buf)) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, strlen(p_avro_buf)); if (!ret) qn += mv_num; } } #endif } } duration = time(NULL)-start; if (config.print_markers) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { void *json_obj = NULL; char *json_str = NULL; json_obj = compose_purge_close_json(config.name, writer_pid, qn, saved_index, duration); if (json_obj) json_str = compose_json_str(json_obj); if (json_str) { sleep(1); /* Let's give a small delay to facilitate purge_close being the last message in batch in case of partitioned topics */ Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_kafka_produce_data(&kafkap_kafka_host, json_str, strlen(json_str)); free(json_str); json_str = NULL; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_close_schema); avro_value_t p_avro_value = compose_avro_acct_close(config.name, writer_pid, qn, saved_index, duration, p_avro_iface); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { if (!config.kafka_avro_schema_registry) { p_avro_len = avro_writer_tell(p_avro_writer); } #ifdef WITH_SERDES else { void *p_avro_local_buf = NULL; if (serdes_schema_serialize_avro(kafkap_kafka_host.sd_schema[AVRO_ACCT_CLOSE_SID], &p_avro_value, &p_avro_local_buf, &p_avro_len, kafkap_kafka_host.errstr, sizeof(kafkap_kafka_host.errstr))) { Log(LOG_ERR, "ERROR ( %s/%s ): kafka_cache_purge(): serdes_schema_serialize_avro() failed for %s: %s\n", config.name, config.type, "acct_close", kafkap_kafka_host.errstr); exit_gracefully(1); } else { p_avro_buf = p_avro_local_buf; } } #endif ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_buf, p_avro_len); if (!config.kafka_avro_schema_registry) avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { ret = p_kafka_produce_data(&kafkap_kafka_host, p_avro_local_buf, strlen(p_avro_local_buf)); free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #endif } } p_kafka_close(&kafkap_kafka_host, FALSE); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, qn, saved_index, duration); if (config.sql_trigger_exec && !safe_action) P_trigger_exec(config.sql_trigger_exec); if (empty_pcust) free(empty_pcust); if (json_buf) free(json_buf); #ifdef WITH_AVRO if (p_avro_buf) free(p_avro_buf); #endif } pmacct-1.7.8/src/sql_common_m.c0000644000175000017500000002174114354105275015435 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "plugin_common.h" #include "sql_common.h" void AddToLRUTail(struct db_cache *Cursor) { if (Cursor == lru_tail) return; if (Cursor->lru_prev) { if (Cursor->lru_next) { Cursor->lru_prev->lru_next = Cursor->lru_next; Cursor->lru_next->lru_prev = Cursor->lru_prev; } else Cursor->lru_prev->lru_next = NULL; } else { if (Cursor->lru_next) Cursor->lru_next->lru_prev = NULL; } Cursor->lru_prev = lru_tail; Cursor->lru_prev->lru_next = Cursor; Cursor->lru_next = NULL; lru_tail = Cursor; } void RetireElem(struct db_cache *Cursor) { assert(Cursor->prev); assert(Cursor->lru_prev); if (Cursor->lru_next) { Cursor->lru_prev->lru_next = Cursor->lru_next; Cursor->lru_next->lru_prev = Cursor->lru_prev; } else { /* no lru_next: we are tail! */ assert(Cursor == lru_tail); Cursor->lru_prev->lru_next = NULL; lru_tail = Cursor->lru_prev; } if (Cursor->next) { Cursor->prev->next = Cursor->next; Cursor->next->prev = Cursor->prev; } else Cursor->prev->next = NULL; if (Cursor->pbgp) free(Cursor->pbgp); if (Cursor->pnat) free(Cursor->pnat); if (Cursor->pmpls) free(Cursor->pmpls); if (Cursor->ptun) free(Cursor->ptun); if (Cursor->pcust) free(Cursor->pcust); if (Cursor->pvlen) free(Cursor->pvlen); if (Cursor->stitch) free(Cursor->stitch); free(Cursor); } void BuildChain(struct db_cache *Cursor, struct db_cache *newElem) { Cursor->next = newElem; newElem->prev = Cursor; newElem->chained = TRUE; } void ReBuildChain(struct db_cache *Cursor, struct db_cache *newElem) { assert(Cursor != newElem); if (newElem->next) { newElem->prev->next = newElem->next; newElem->next->prev = newElem->prev; } else newElem->prev->next = NULL; Cursor->next = newElem; newElem->prev = Cursor; newElem->next = NULL; } void SwapChainedElems(struct db_cache *Cursor, struct db_cache *staleElem) { struct db_cache *auxPtr; assert(Cursor != staleElem); assert(Cursor->prev); assert(staleElem->prev); /* Specific cases first */ if (Cursor == staleElem->prev) { staleElem->prev = Cursor->prev; Cursor->next = staleElem->next; staleElem->next = Cursor; Cursor->prev = staleElem; staleElem->prev->next = staleElem; if (Cursor->next) Cursor->next->prev = Cursor; } else if (staleElem == Cursor->prev) { Cursor->prev = staleElem->prev; staleElem->next = Cursor->next; Cursor->next = staleElem; staleElem->prev = Cursor; Cursor->prev->next = Cursor; if (staleElem->next) staleElem->next->prev = staleElem; } /* General case */ else { auxPtr = Cursor->prev; Cursor->prev = staleElem->prev; Cursor->prev->next = Cursor; staleElem->prev = auxPtr; staleElem->prev->next = staleElem; auxPtr = Cursor->next; Cursor->next = staleElem->next; if (Cursor->next) Cursor->next->prev = Cursor; staleElem->next = auxPtr; if (staleElem->next) staleElem->next->prev = staleElem; } } void SQL_SetENV() { char *ptrs[16]; int count = 0, i; INIT_BUF(envbuf); memset(ptrs, 0, sizeof(ptrs)); if (config.sql_db) { strncat(envbuf.ptr, "SQL_DB=", (envbuf.end-envbuf.ptr - 1)); strncat(envbuf.ptr, config.sql_db, envbuf.end-envbuf.ptr); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (config.sql_table) { strncat(envbuf.ptr, "SQL_TABLE=", envbuf.end-envbuf.ptr); strncat(envbuf.ptr, config.sql_table, envbuf.end-envbuf.ptr); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (config.sql_host) { strncat(envbuf.ptr, "SQL_HOST=", envbuf.end-envbuf.ptr); strncat(envbuf.ptr, config.sql_host, envbuf.end-envbuf.ptr); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (config.sql_user) { strncat(envbuf.ptr, "SQL_USER=", envbuf.end-envbuf.ptr); strncat(envbuf.ptr, config.sql_user, envbuf.end-envbuf.ptr); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "SQL_REFRESH_TIME=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", config.sql_refresh_time); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (config.sampling_rate >= 1 || config.ext_sampling_rate >= 1) { char *tmpptr; strncat(envbuf.ptr, "SAMPLING_RATE=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", config.sampling_rate ? config.sampling_rate : config.ext_sampling_rate); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (config.sql_backup_host) { strncat(envbuf.ptr, "SQL_RECOVERY_BACKUP_HOST=", envbuf.end-envbuf.ptr); strncat(envbuf.ptr, config.sql_backup_host, envbuf.end-envbuf.ptr); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "SQL_MAX_WRITERS=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", dump_writers_get_max()); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } for (i = 0; i < count; i++) putenv(ptrs[i]); } void SQL_SetENV_child(const struct insert_data *idata) { char *ptrs[N_FUNCS]; int count = 0, i; memset(ptrs, 0, sizeof(ptrs)); { char *tmpptr; strncat(envbuf.ptr, "INSERT_QUERIES_NUMBER=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", idata->iqn); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "UPDATE_QUERIES_NUMBER=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", idata->uqn); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "ELAPSED_TIME=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%lu", idata->elap_time); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "TOTAL_ELEM_NUMBER=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", idata->ten); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "EFFECTIVE_ELEM_NUMBER=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%u", idata->een); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (idata->basetime) { char *tmpptr; strncat(envbuf.ptr, "SQL_HISTORY_BASETIME=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%lu", idata->basetime); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (idata->timeslot) { char *tmpptr; strncat(envbuf.ptr, "SQL_HISTORY_TIMESLOT=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%lu", idata->timeslot); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } if (idata->dyn_table) { char *tmpptr; strncat(envbuf.ptr, "EFFECTIVE_SQL_TABLE=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); pm_strftime(tmpptr, envbuf.end-tmpptr, config.sql_table, &idata->basetime, config.timestamps_utc); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } { char *tmpptr; strncat(envbuf.ptr, "SQL_ACTIVE_WRITERS=", envbuf.end-envbuf.ptr); tmpptr = envbuf.ptr + strlen(envbuf.ptr); snprintf(tmpptr, envbuf.end-tmpptr, "%d", dump_writers_get_active()); ptrs[count] = envbuf.ptr; envbuf.ptr += strlen(envbuf.ptr)+1; count++; } for (i = 0; i < count; i++) putenv(ptrs[i]); } pmacct-1.7.8/src/kafka_common.c0000644000175000017500000004767614354105275015416 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_common.h" #include "kafka_common.h" #include "base64.h" struct p_kafka_host kafkap_kafka_host; struct p_kafka_host bgp_daemon_msglog_kafka_host; struct p_kafka_host bmp_daemon_msglog_kafka_host; struct p_kafka_host sfacctd_counter_kafka_host; struct p_kafka_host telemetry_kafka_host; struct p_kafka_host telemetry_daemon_msglog_kafka_host; struct p_kafka_host nfacctd_kafka_host; int kafkap_ret_err_cb; int dyn_partition_key; char default_kafka_broker_host[] = "127.0.0.1"; int default_kafka_broker_port = 9092; char default_kafka_topic[] = "pmacct.acct"; /* Functions */ void p_kafka_init_host_struct(struct p_kafka_host *kafka_host) { if (kafka_host) { memset(kafka_host, 0, sizeof(struct p_kafka_host)); P_broker_timers_set_retry_interval(&kafka_host->btimers, PM_KAFKA_DEFAULT_RETRY); } } void p_kafka_init_host_conf(struct p_kafka_host *kafka_host, char *config_file) { if (kafka_host) { p_kafka_set_config_file(kafka_host, config_file); kafka_host->cfg = rd_kafka_conf_new(); if (kafka_host->cfg) { rd_kafka_conf_set_log_cb(kafka_host->cfg, p_kafka_logger); rd_kafka_conf_set_error_cb(kafka_host->cfg, p_kafka_msg_error); rd_kafka_conf_set_dr_msg_cb(kafka_host->cfg, p_kafka_msg_delivered); rd_kafka_conf_set_stats_cb(kafka_host->cfg, p_kafka_stats); rd_kafka_conf_set_opaque(kafka_host->cfg, kafka_host); p_kafka_apply_global_config(kafka_host); if (config.debug) { const char **res; size_t res_len, idx; res = rd_kafka_conf_dump(kafka_host->cfg, &res_len); for (idx = 0; idx < res_len; idx += 2) Log(LOG_DEBUG, "DEBUG ( %s/%s ): librdkafka global config: %s = %s\n", config.name, config.type, res[idx], res[idx + 1]); rd_kafka_conf_dump_free(res, res_len); } } } } void p_kafka_init_host(struct p_kafka_host *kafka_host, char *config_file) { p_kafka_init_host_struct(kafka_host); p_kafka_init_host_conf(kafka_host, config_file); } void p_kafka_unset_topic(struct p_kafka_host *kafka_host) { if (kafka_host && kafka_host->topic) { rd_kafka_topic_destroy(kafka_host->topic); kafka_host->topic = NULL; } } void p_kafka_set_topic(struct p_kafka_host *kafka_host, char *topic) { if (kafka_host && kafka_host->rk) { kafka_host->topic_cfg = rd_kafka_topic_conf_new(); p_kafka_apply_topic_config(kafka_host); if (config.debug) { const char **res; size_t res_len, idx; res = rd_kafka_topic_conf_dump(kafka_host->topic_cfg, &res_len); for (idx = 0; idx < res_len; idx += 2) Log(LOG_DEBUG, "DEBUG ( %s/%s ): librdkafka '%s' topic config: %s = %s\n", config.name, config.type, topic, res[idx], res[idx + 1]); rd_kafka_conf_dump_free(res, res_len); } /* This needs to be done here otherwise kafka_host->topic_cfg is null * and the partitioner cannot be set */ if (config.kafka_partition_dynamic && kafka_host->topic_cfg) p_kafka_set_dynamic_partitioner(kafka_host); /* destroy current allocation before making a new one */ if (kafka_host->topic) p_kafka_unset_topic(kafka_host); if (kafka_host->topic_cfg) { kafka_host->topic = rd_kafka_topic_new(kafka_host->rk, topic, kafka_host->topic_cfg); kafka_host->topic_cfg = NULL; /* rd_kafka_topic_new() destroys conf as per rdkafka.h */ } } } rd_kafka_t *p_kafka_get_handler(struct p_kafka_host *kafka_host) { if (kafka_host) return kafka_host->rk; return NULL; } char *p_kafka_get_broker(struct p_kafka_host *kafka_host) { if (kafka_host && strlen(kafka_host->broker)) return kafka_host->broker; return NULL; } char *p_kafka_get_topic(struct p_kafka_host *kafka_host) { if (kafka_host && kafka_host->topic) return (char*)rd_kafka_topic_name(kafka_host->topic); return NULL; } void p_kafka_init_topic_rr(struct p_kafka_host *kafka_host) { if (kafka_host) memset(&kafka_host->topic_rr, 0, sizeof(struct p_table_rr)); } void p_kafka_set_topic_rr(struct p_kafka_host *kafka_host, int topic_rr) { if (kafka_host) kafka_host->topic_rr.max = topic_rr; } int p_kafka_get_topic_rr(struct p_kafka_host *kafka_host) { if (kafka_host) return kafka_host->topic_rr.max; return FALSE; } void p_kafka_set_broker(struct p_kafka_host *kafka_host, char *host, int port) { int ret, multiple_brokers = FALSE; if (strchr(host, ',')) multiple_brokers = TRUE; if (kafka_host && kafka_host->rk) { /* if host is a comma-separated list of brokers, assume port is part of the definition */ if (multiple_brokers) snprintf(kafka_host->broker, SRVBUFLEN, "%s", host); else { if (host && port) snprintf(kafka_host->broker, SRVBUFLEN, "%s:%u", host, port); else if (host && !port) snprintf(kafka_host->broker, SRVBUFLEN, "%s", host); } if ((ret = rd_kafka_brokers_add(kafka_host->rk, kafka_host->broker)) == 0) { Log(LOG_WARNING, "WARN ( %s/%s ): Invalid 'kafka_broker_host' or 'kafka_broker_port' specified (%s).\n", config.name, config.type, kafka_host->broker); } else Log(LOG_DEBUG, "DEBUG ( %s/%s ): %u broker(s) successfully added.\n", config.name, config.type, ret); } } void p_kafka_set_content_type(struct p_kafka_host *kafka_host, int content_type) { if (kafka_host) kafka_host->content_type = content_type; } int p_kafka_get_content_type(struct p_kafka_host *kafka_host) { if (kafka_host) return kafka_host->content_type; return FALSE; } void p_kafka_set_partition(struct p_kafka_host *kafka_host, int partition) { if (kafka_host) { if (!partition) kafka_host->partition = RD_KAFKA_PARTITION_UA; else if (partition == FALSE_NONZERO) kafka_host->partition = 0; else kafka_host->partition = partition; } } int p_kafka_get_partition(struct p_kafka_host *kafka_host) { if (kafka_host) return kafka_host->partition; return FALSE; } void p_kafka_set_dynamic_partitioner(struct p_kafka_host *kafka_host) { rd_kafka_topic_conf_set_partitioner_cb(kafka_host->topic_cfg, &rd_kafka_msg_partitioner_consistent_random); } void p_kafka_set_key(struct p_kafka_host *kafka_host, char *key, int key_len) { if (kafka_host) { kafka_host->key = key; kafka_host->key_len = key_len; } } char *p_kafka_get_key(struct p_kafka_host *kafka_host) { if (kafka_host) return kafka_host->key; return NULL; } void p_kafka_set_config_file(struct p_kafka_host *kafka_host, char *config_file) { if (kafka_host) { kafka_host->config_file = config_file; } } void p_kafka_get_version() { printf("rdkafka %s\n", rd_kafka_version_str()); } int p_kafka_parse_config_entry(char *buf, char *type, char **key, char **value) { char *value_ptr, *token; int index, type_match = FALSE; if (buf && type && key && value) { value_ptr = buf; (*key) = NULL; (*value) = NULL; index = 0; while ((token = extract_token(&value_ptr, ','))) { index++; trim_spaces(token); if (index == 1) { lower_string(token); if (!strcmp(token, type)) type_match = TRUE; else break; } else if (index == 2) { (*key) = token; break; } } if (strlen(value_ptr)) { trim_spaces(value_ptr); (*value) = value_ptr; index++; } if (type_match && index != 3) return ERR; } else return ERR; return type_match; } void p_kafka_apply_global_config(struct p_kafka_host *kafka_host) { FILE *file; char buf[SRVBUFLEN], errstr[SRVBUFLEN], *key, *value; int lineno = 1, ret; if (kafka_host && kafka_host->config_file && kafka_host->cfg) { if ((file = fopen(kafka_host->config_file, "r")) == NULL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found. librdkafka global config not loaded.\n", config.name, config.type, kafka_host->config_file); return; } else Log(LOG_INFO, "INFO ( %s/%s ): [%s] Reading librdkafka global config.\n", config.name, config.type, kafka_host->config_file); while (!feof(file)) { if (fgets(buf, SRVBUFLEN, file)) { if ((ret = p_kafka_parse_config_entry(buf, "global", &key, &value)) > 0) { ret = rd_kafka_conf_set(kafka_host->cfg, key, value, errstr, sizeof(errstr)); if (ret != RD_KAFKA_CONF_OK) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] key=%s value=%s failed: %s\n", config.name, config.type, kafka_host->config_file, lineno, key, value, errstr); } } else { if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line malformed. Ignored.\n", config.name, config.type, kafka_host->config_file, lineno); } } } lineno++; } fclose(file); } } void p_kafka_apply_topic_config(struct p_kafka_host *kafka_host) { FILE *file; char buf[SRVBUFLEN], errstr[SRVBUFLEN], *key, *value; int lineno = 1, ret; if (kafka_host && kafka_host->config_file && kafka_host->topic_cfg) { if ((file = fopen(kafka_host->config_file, "r")) == NULL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found. librdkafka topic configuration not loaded.\n", config.name, config.type, kafka_host->config_file); return; } else Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] Reading librdkafka topic configuration.\n", config.name, config.type, kafka_host->config_file); while (!feof(file)) { if (fgets(buf, SRVBUFLEN, file)) { if ((ret = p_kafka_parse_config_entry(buf, "topic", &key, &value)) > 0) { ret = rd_kafka_topic_conf_set(kafka_host->topic_cfg, key, value, errstr, sizeof(errstr)); if (ret != RD_KAFKA_CONF_OK) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] key=%s value=%s failed: %s\n", config.name, config.type, kafka_host->config_file, lineno, key, value, errstr); } } else { if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line malformed. Ignored.\n", config.name, config.type, kafka_host->config_file, lineno); } } } lineno++; } fclose(file); } } void p_kafka_logger(const rd_kafka_t *rk, int level, const char *fac, const char *buf) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): RDKAFKA-%i-%s: %s: %s\n", config.name, config.type, level, fac, rd_kafka_name(rk), buf); } void p_kafka_msg_delivered(rd_kafka_t *rk, const rd_kafka_message_t *rk_msg, void *opaque) { struct p_kafka_host *kafka_host = (struct p_kafka_host *) opaque; if (rk_msg->err) { Log(LOG_ERR, "ERROR ( %s/%s ): Kafka message delivery failed: %s\n", config.name, config.type, rd_kafka_err2str(rk_msg->err)); } else { if (config.debug) { if (p_kafka_get_content_type(kafka_host) == PM_KAFKA_CNT_TYPE_STR) { char *payload_str = (char *) rk_msg->payload; char saved = payload_str[rk_msg->len - 1]; payload_str[rk_msg->len - 1] = '\0'; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Kafka message delivery successful (%zd bytes): %p\n", config.name, config.type, rk_msg->len, rk_msg->payload); payload_str[rk_msg->len - 1] = saved; } else { size_t base64_data_len = 0; u_char *base64_data = base64_encode(rk_msg->payload, rk_msg->len, &base64_data_len); Log(LOG_DEBUG, "DEBUG ( %s/%s ): Kafka message delivery successful (%zd bytes): %s\n", config.name, config.type, rk_msg->len, base64_data); if (base64_data) base64_freebuf(base64_data); } } } } void p_kafka_msg_error(rd_kafka_t *rk, int err, const char *reason, void *opaque) { kafkap_ret_err_cb = ERR; } int p_kafka_stats(rd_kafka_t *rk, char *json, size_t json_len, void *opaque) { Log(LOG_INFO, "INFO ( %s/%s ): %s\n", config.name, config.type, json); /* We return 0 since we don't want to hold data any further; see librdkafka header/docs for more info. */ return FALSE; } int p_kafka_connect_to_produce(struct p_kafka_host *kafka_host) { if (kafka_host) { rd_kafka_conf_t* cfg = rd_kafka_conf_dup(kafka_host->cfg); if (cfg == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to clone kafka config object\n", config.name, config.type); p_kafka_close(kafka_host, TRUE); return ERR; } kafka_host->rk = rd_kafka_new(RD_KAFKA_PRODUCER, cfg, kafka_host->errstr, sizeof(kafka_host->errstr)); if (!kafka_host->rk) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to create new Kafka producer: %s\n", config.name, config.type, kafka_host->errstr); p_kafka_close(kafka_host, TRUE); return ERR; } if (config.debug) rd_kafka_set_log_level(kafka_host->rk, LOG_DEBUG); } else return ERR; return SUCCESS; } int p_kafka_produce_data_to_part(struct p_kafka_host *kafka_host, void *data, size_t data_len, int part, int do_free) { int ret = SUCCESS; int flag = RD_KAFKA_MSG_F_COPY; kafkap_ret_err_cb = FALSE; if (do_free) { flag = RD_KAFKA_MSG_F_FREE; } if (kafka_host && kafka_host->rk && kafka_host->topic) { ret = rd_kafka_produce(kafka_host->topic, part, flag, data, data_len, kafka_host->key, kafka_host->key_len, NULL); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to produce to topic %s partition %i: %s\n", config.name, config.type, rd_kafka_topic_name(kafka_host->topic), part, rd_kafka_err2str(rd_kafka_last_error())); p_kafka_close(kafka_host, TRUE); return ERR; } } else return ERR; rd_kafka_poll(kafka_host->rk, 0); return ret; } int p_kafka_produce_data(struct p_kafka_host *kafka_host, void *data, size_t data_len) { return p_kafka_produce_data_to_part(kafka_host, data, data_len, kafka_host->partition, FALSE); } int p_kafka_produce_data_and_free(struct p_kafka_host *kafka_host, void *data, size_t data_len) { return p_kafka_produce_data_to_part(kafka_host, data, data_len, kafka_host->partition, TRUE); } int p_kafka_connect_to_consume(struct p_kafka_host *kafka_host) { if (kafka_host) { rd_kafka_conf_t* cfg = rd_kafka_conf_dup(kafka_host->cfg); if (cfg == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to clone kafka config object\n", config.name, config.type); p_kafka_close(kafka_host, TRUE); return ERR; } kafka_host->rk = rd_kafka_new(RD_KAFKA_CONSUMER, cfg, kafka_host->errstr, sizeof(kafka_host->errstr)); if (!kafka_host->rk) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to create new Kafka producer: %s\n", config.name, config.type, kafka_host->errstr); p_kafka_close(kafka_host, TRUE); return ERR; } if (config.debug) rd_kafka_set_log_level(kafka_host->rk, LOG_DEBUG); } else return ERR; return SUCCESS; } int p_kafka_manage_consumer(struct p_kafka_host *kafka_host, int is_start) { int ret = SUCCESS; kafkap_ret_err_cb = FALSE; if (kafka_host && kafka_host->rk && kafka_host->topic && !validate_truefalse(is_start)) { if (is_start) { ret = rd_kafka_consume_start(kafka_host->topic, kafka_host->partition, RD_KAFKA_OFFSET_END); if (ret == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): Failed to start consuming topic %s partition %i: %s\n", config.name, config.type, rd_kafka_topic_name(kafka_host->topic), kafka_host->partition, rd_kafka_err2str(rd_kafka_last_error())); p_kafka_close(kafka_host, TRUE); return ERR; } } else { rd_kafka_consume_stop(kafka_host->topic, kafka_host->partition); p_kafka_close(kafka_host, FALSE); } } else return ERR; return ret; } int p_kafka_consume_poller(struct p_kafka_host *kafka_host, void **data, int timeout) { rd_kafka_message_t *kafka_msg; int ret = SUCCESS; if (kafka_host && data && timeout) { kafka_msg = rd_kafka_consume(kafka_host->topic, kafka_host->partition, timeout); if (!kafka_msg) ret = FALSE; /* timeout */ else ret = TRUE; /* got data */ (*data) = kafka_msg; } else { (*data) = NULL; ret = ERR; } return ret; } int p_kafka_consume_data(struct p_kafka_host *kafka_host, void *data, u_char *payload, size_t payload_len) { rd_kafka_message_t *kafka_msg = (rd_kafka_message_t *) data; int ret = 0; if (kafka_host && data && payload && payload_len) { if (kafka_msg->payload && kafka_msg->len) { if (kafka_msg->len <= payload_len) { memcpy(payload, kafka_msg->payload, kafka_msg->len); ret = kafka_msg->len; } else ret = ERR; } else ret = 0; } else ret = ERR; rd_kafka_message_destroy(kafka_msg); return ret; } void p_kafka_close(struct p_kafka_host *kafka_host, int set_fail) { if (kafka_host && !validate_truefalse(set_fail)) { if (set_fail) { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to Kafka: p_kafka_close()\n", config.name, config.type); P_broker_timers_set_last_fail(&kafka_host->btimers, time(NULL)); } else { /* Wait for messages to be delivered */ if (kafka_host->rk) p_kafka_check_outq_len(kafka_host); } if (kafka_host->topic) { rd_kafka_topic_destroy(kafka_host->topic); kafka_host->topic = NULL; } if (kafka_host->topic_cfg) { rd_kafka_topic_conf_destroy(kafka_host->topic_cfg); kafka_host->topic_cfg = NULL; } if (kafka_host->rk) { rd_kafka_destroy(kafka_host->rk); kafka_host->rk = NULL; } if (kafka_host->cfg) { rd_kafka_conf_destroy(kafka_host->cfg); kafka_host->cfg = NULL; } } } int p_kafka_check_outq_len(struct p_kafka_host *kafka_host) { int outq_len = 0, old_outq_len = 0, retries = 0; if (kafka_host->rk) { while ((outq_len = rd_kafka_outq_len(kafka_host->rk)) > 0) { if (outq_len == old_outq_len) { if (retries < PM_KAFKA_OUTQ_LEN_RETRIES) retries++; else { Log(LOG_ERR, "ERROR ( %s/%s ): Connection failed to Kafka: p_kafka_check_outq_len() (%u)\n", config.name, config.type, outq_len); p_kafka_close(kafka_host, TRUE); return outq_len; } } else old_outq_len = outq_len; rd_kafka_poll(kafka_host->rk, 100); sleep(1); } } else return ERR; return SUCCESS; } #if defined WITH_JANSSON int write_and_free_json_kafka(void *kafka_log, void *obj) { char *orig_kafka_topic = NULL, dyn_kafka_topic[SRVBUFLEN]; struct p_kafka_host *alog = (struct p_kafka_host *) kafka_log; int ret = ERR; char *tmpbuf = NULL; json_t *json_obj = (json_t *) obj; tmpbuf = json_dumps(json_obj, JSON_PRESERVE_ORDER); json_decref(json_obj); if (tmpbuf) { if (alog->topic_rr.max) { orig_kafka_topic = p_kafka_get_topic(alog); P_handle_table_dyn_rr(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &alog->topic_rr); p_kafka_set_topic(alog, dyn_kafka_topic); } ret = p_kafka_produce_data_and_free(alog, tmpbuf, strlen(tmpbuf)); if (alog->topic_rr.max) p_kafka_set_topic(alog, orig_kafka_topic); } return ret; } #else int write_and_free_json_kafka(void *kafka_log, void *obj) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): write_and_free_json_kafka(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); } #endif int write_binary_kafka(void *kafka_log, void *obj, size_t len) { char *orig_kafka_topic = NULL, dyn_kafka_topic[SRVBUFLEN]; struct p_kafka_host *alog = (struct p_kafka_host *) kafka_log; int ret = ERR; if (obj && len) { if (alog->topic_rr.max) { orig_kafka_topic = p_kafka_get_topic(alog); P_handle_table_dyn_rr(dyn_kafka_topic, SRVBUFLEN, orig_kafka_topic, &alog->topic_rr); p_kafka_set_topic(alog, dyn_kafka_topic); } ret = p_kafka_produce_data(alog, obj, len); if (alog->topic_rr.max) p_kafka_set_topic(alog, orig_kafka_topic); } return ret; } pmacct-1.7.8/src/util.c0000644000175000017500000027257314354105275013742 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "util-data.h" #ifdef WITH_KAFKA #include "kafka_common.h" #endif #ifdef WITH_MYSQL #include "mysql_plugin.h" #endif #ifdef WITH_PGSQL #include "pgsql_plugin.h" #endif #ifdef WITH_SQLITE3 #include "sqlite3_plugin.h" #endif #ifdef WITH_RABBITMQ #include "amqp_plugin.h" #endif #ifdef WITH_KAFKA #include "kafka_plugin.h" #endif #ifdef WITH_REDIS #include "hiredis/hiredis.h" #endif #include "pmacct-data.h" #include "ip_flow.h" #include "classifier.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include #include #include struct _devices_struct _devices[] = { #if defined DLT_LOOP {null_handler, DLT_LOOP}, #endif {null_handler, DLT_NULL}, {eth_handler, DLT_EN10MB}, {ppp_handler, DLT_PPP}, #if defined DLT_IEEE802_11 {ieee_802_11_handler, DLT_IEEE802_11}, #endif #if defined DLT_LINUX_SLL {sll_handler, DLT_LINUX_SLL}, #endif #if defined DLT_RAW {raw_handler, DLT_RAW}, #endif {NULL, -1}, }; /* Global variables */ primptrs_func primptrs_funcs[PRIMPTRS_FUNCS_N]; /* functions */ void setnonblocking(int sock) { int opts; opts = fcntl(sock, F_GETFL); opts = (opts | O_NONBLOCK); fcntl(sock, F_SETFL, opts); } void setblocking(int sock) { int opts; opts = fcntl(sock, F_GETFL); opts & O_NONBLOCK ? opts ^= O_NONBLOCK : opts; fcntl(sock, F_SETFL, opts); } int daemonize() { int fdd; pid_t pid; pid = fork(); switch (pid) { case -1: return -1; case 0: break; default: exit(0); } if (setsid() == -1) return -1; fdd = open("/dev/null", O_RDWR, 0); if (fdd != -1) { dup2(fdd, 0); dup2(fdd, 1); dup2(fdd, 2); if (fdd > 2) close(fdd); } return 0; } char *extract_token(char **string, int delim) { char *token, *delim_ptr; if (!strlen(*string)) return NULL; start: if ((delim_ptr = strchr(*string, delim))) { *delim_ptr = '\0'; token = *string; *string = delim_ptr+1; if (!strlen(token)) goto start; } else { token = *string; *string += strlen(*string); if (!strlen(token)) return NULL; } return token; } char *extract_plugin_name(char **string) { char *name, *delim_ptr; char name_start = '['; char name_end = ']'; if ((delim_ptr = strchr(*string, name_start))) { *delim_ptr = '\0'; name = delim_ptr+1; if ((delim_ptr = strchr(name, name_end))) *delim_ptr = '\0'; else { printf("ERROR: Not weighted parhentesis: '[%s'\n", name); exit(1); } } else return NULL; return name; } /* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ char *copy_argv(register char **argv) { register char **p; register unsigned int len = 0; char *buf; char *src, *dst; p = argv; if (*p == 0) return NULL; while (*p) len += strlen(*p++) + 1; buf = (char *)malloc(len); if (buf == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): copy_argv: malloc()\n", config.name, config.type); return NULL; } p = argv; dst = buf; while ((src = *p++) != NULL) { while ((*dst++ = *src++) != '\0'); dst[-1] = ' '; } dst[-1] = '\0'; return buf; } void trim_spaces(char *buf) { char *tmp_buf; int i, len; len = strlen(buf); tmp_buf = (char *)malloc(len + 1); if (tmp_buf == NULL) { Log(LOG_ERR, "ERROR: trim_spaces: malloc() failed.\n"); return; } /* trimming spaces at beginning of the string */ for (i = 0; i <= len; i++) { if (!isspace(buf[i])) { if (i != 0) { strlcpy(tmp_buf, &buf[i], len+1-i); strlcpy(buf, tmp_buf, len+1-i); } break; } } /* trimming spaces at the end of the string */ for (i = strlen(buf)-1; i >= 0; i--) { if (isspace(buf[i])) buf[i] = '\0'; else break; } free(tmp_buf); } void trim_all_spaces(char *buf) { char *tmp_buf; int i = 0, len, quotes = FALSE; len = strlen(buf); tmp_buf = (char *)malloc(len + 1); if (tmp_buf == NULL) { Log(LOG_ERR, "ERROR: trim_all_spaces: malloc() failed.\n"); return; } /* trimming all spaces */ while (i <= len) { if (buf[i] == '\'') { if (!quotes) quotes = TRUE; else if (quotes) quotes = FALSE; } if (isspace(buf[i]) && !quotes) { strlcpy(tmp_buf, &buf[i+1], len); strlcpy(&buf[i], tmp_buf, len); len--; } else i++; } free(tmp_buf); } void strip_quotes(char *buf) { char *ptr, *tmp_buf; int i = 0, len; len = strlen(buf); tmp_buf = (char *) malloc(len + 1); if (tmp_buf == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): strip_quotes: malloc() failed.\n", config.name, config.type); return; } ptr = buf; /* stripping all quote marks using a temporary buffer to avoid string corruption by strcpy() */ while (i <= len) { if (ptr[i] == '\'') { strcpy(tmp_buf, &ptr[i+1]); strcpy(&buf[i], tmp_buf); len--; } else i++; } free(tmp_buf); } int isblankline(char *line) { int len, j, n_spaces = 0; if (!line) return FALSE; len = strlen(line); for (j = 0; j < len; j++) if (isspace(line[j])) n_spaces++; if (n_spaces == len) return TRUE; else return FALSE; } int iscomment(char *line) { int len, j, first_char = TRUE; if (!line) return FALSE; len = strlen(line); for (j = 0; j <= len; j++) { if (!isspace(line[j])) first_char--; if (!first_char) { if (line[j] == '!' || line[j] == '#') return TRUE; else return FALSE; } } return FALSE; } void string_add_newline(char *buf) { int len = strlen(buf); buf[len] = '\n'; len++; buf[len] = '\0'; } time_t roundoff_time(time_t t, char *value) { struct tm *rounded; int len, j; rounded = localtime(&t); rounded->tm_sec = 0; /* default round off */ if (value) { len = strlen(value); for (j = 0; j < len; j++) { if (value[j] == 'm') rounded->tm_min = 0; else if (value[j] == 'h') { rounded->tm_min = 0; rounded->tm_hour = 0; } else if (value[j] == 'd') { rounded->tm_min = 0; rounded->tm_hour = 0; rounded->tm_mday = 1; } else if (value[j] == 'w') { rounded->tm_min = 0; rounded->tm_hour = 0; while (rounded->tm_wday > 1) { rounded->tm_mday--; rounded->tm_wday--; } } else if (value[j] == 'M') { rounded->tm_min = 0; rounded->tm_hour = 0; rounded->tm_mday = 1; rounded->tm_mon = 0; } else Log(LOG_WARNING, "WARN ( %s/%s ): ignoring unknown round off value: %c\n", config.name, config.type, value[j]); } } t = mktime(rounded); return t; } /* op = 0 (add); op = 1 (sub) */ time_t calc_monthly_timeslot(time_t t, int howmany, int op) { time_t base = t, final; struct tm *tmt; if (!config.timestamps_utc) tmt = localtime(&t); else tmt = gmtime(&t); while (howmany) { tmt->tm_mday = 1; if (op == ADD) tmt->tm_mon++; else if (op == SUB) tmt->tm_mon--; howmany--; } final = mktime(tmt); return (final-base); } FILE *open_output_file(char *filename, char *mode, int lock) { FILE *file = NULL; uid_t owner = -1; gid_t group = -1; struct stat st; int ret, fd; if (!filename || !mode) return file; if (config.files_uid) owner = config.files_uid; if (config.files_gid) group = config.files_gid; /* create dir structure to get to file, if needed */ ret = mkdir_multilevel(filename, TRUE, owner, group); if (ret) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): mkdir_multilevel() failed.\n", config.name, config.type, filename); return file; } /* handling FIFOs */ if (!stat(filename, &st)) { if (st.st_mode & S_IFIFO) { fd = open(filename, (O_RDWR|O_NONBLOCK)); if (fd == ERR) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): open() failed (%s).\n", config.name, config.type, filename, strerror(errno)); return file; } else { file = fdopen(fd, mode); if (!file) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): fdopen() failed (%s).\n", config.name, config.type, filename, strerror(errno)); return file; } } } } /* handling regular files */ if (!file) file = fopen(filename, mode); if (file) { fd = fileno(file); if (chown(filename, owner, group) == -1) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] open_output_file(): chown() failed (%s).\n", config.name, config.type, filename, strerror(errno)); if (lock) { if (file_lock(fd)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): file_lock() failed.\n", config.name, config.type, filename); file = NULL; } } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] open_output_file(): fopen() failed (%s).\n", config.name, config.type, filename, strerror(errno)); file = NULL; } return file; } void link_latest_output_file(char *link_filename, char *filename_to_link) { int ret, rewrite_latest = FALSE; char buf[SRVBUFLEN]; uid_t owner = -1; gid_t group = -1; if (!link_filename || !filename_to_link) return; buf[0] = '\0'; if (config.files_uid) owner = config.files_uid; if (config.files_gid) group = config.files_gid; /* create dir structure to get to file, if needed */ ret = mkdir_multilevel(link_filename, TRUE, owner, group); if (ret) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] link_latest_output_file(): mkdir_multilevel() failed.\n", config.name, config.type, link_filename); return; } /* if a file with same name exists let's investigate if filename_to_link is newer */ ret = access(link_filename, F_OK); if (!ret) { struct stat s1, s2; memset(&s1, 0, sizeof(struct stat)); memset(&s2, 0, sizeof(struct stat)); ret = readlink(link_filename, buf, SRVBUFLEN); /* filename_to_link is newer than buf or buf is un-existing */ stat(buf, &s1); stat(filename_to_link, &s2); if (s2.st_mtime >= s1.st_mtime) rewrite_latest = TRUE; } else rewrite_latest = TRUE; if (rewrite_latest) { unlink(link_filename); ret = symlink(filename_to_link, link_filename); if (!ret) { if (lchown(link_filename, owner, group) == -1) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] link_latest_output_file(): unable to chown().\n", config.name, config.type, link_filename); } } } } void close_output_file(FILE *f) { if (f) fclose(f); } void dynname_tokens_prepare(char *s, struct dynname_tokens *tokens, int type) { char *ptr_str = NULL, *ptr_var = NULL, *ptr_text = NULL; int var_mode = FALSE, var_close = FALSE, text_mode = FALSE, text_close = FALSE; int token_idx = 0, rlen = 0, slen, var_len = 0, text_len = 0, dollar = FALSE, ret; char var_buf[VERYSHORTBUFLEN], text_buf[VERYSHORTBUFLEN]; assert(type <= DYN_STR_MAX); slen = strlen(s); memset(tokens, 0, sizeof(struct dynname_tokens)); for (ptr_str = s; rlen < slen; rlen++) { process_dollar: /* Let's reckon and handle '$' signs */ if (ptr_str[rlen] == '\x24') { dollar = TRUE; /* if we are processing a variable, let's close it to process the upcoming one */ if (var_mode && var_len) { var_close = TRUE; } /* if we are processing text, let's close it to process the upcoming variable */ if (text_mode && text_len) { text_close = TRUE; } /* variable parsing */ if (!var_mode) { var_mode = TRUE; ptr_var = &ptr_str[rlen]; } } else { /* Collecting text */ if (!var_mode && !text_mode) { text_mode = TRUE; ptr_text = &ptr_str[rlen]; } } process_closing: /* Let's close the current variable parsing, two cases: * we were parsing a variable and found a new one starting up; * separator character hit, time to switch to text mode; */ if (var_close) { if (var_len > 1 /* dollar plus at least one valid char */ && var_len < sizeof(var_buf)) { int reg_idx, reg_match = FALSE; memset(var_buf, 0, sizeof(var_buf)); strncpy(var_buf, ptr_var + 1, var_len - 1); for (reg_idx = 0; dynname_token_dict_registry[reg_idx].id; reg_idx++) { if (dynname_token_dict_registry[reg_idx].id == type) { ret = dynname_token_dict_registry[reg_idx].func(tokens, var_buf, token_idx); if (ret == E_NOTFOUND) { Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): unknown variable '%s' in dictionary '%s'.\n", config.name, config.type, var_buf, dynname_token_dict_registry[reg_idx].desc); exit_gracefully(1); } reg_match = TRUE; break; } } if (!reg_match) { assert(dynname_token_dict_registry[reg_idx].id == DYN_STR_UNKNOWN); dynname_token_dict_registry[reg_idx].func(tokens, var_buf, token_idx); /* exit */ } token_idx++; } else { ptr_var[var_len] = '\0'; Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): invalid variable '%s' in '%s'.\n", config.name, config.type, ptr_var, s); exit_gracefully(1); } ptr_var = NULL; var_mode = FALSE; var_close = FALSE; var_len = 0; goto process_dollar; } /* We were collecting text and found a new variable starting up: Let's close text and open variable */ if (text_close) { if (text_len && text_len < sizeof(text_buf)) { memset(text_buf, 0, sizeof(text_buf)); strncpy(text_buf, ptr_text, text_len); tokens->func[token_idx] = dynname_text_token_handler; tokens->static_arg[token_idx] = strdup(text_buf); token_idx++; } else { ptr_text[text_len] = '\0'; Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): invalid text '%s' in '%s'.\n", config.name, config.type, ptr_text, s); exit_gracefully(1); } ptr_text = NULL; text_mode = FALSE; text_close = FALSE; text_len = 0; goto process_dollar; } if (var_mode) { if (dollar) { dollar = FALSE; var_len++; continue; } /* valid charset for a variable: a-z, A-Z, 0-9, _ */ if ((ptr_str[rlen] >= '\x30' && ptr_str[rlen] <= '\x39') || (ptr_str[rlen] >= '\x41' && ptr_str[rlen] <= '\x5a') || (ptr_str[rlen] >= '\x61' && ptr_str[rlen] <= '\x7a') || (ptr_str[rlen] == '\x5f')) { var_len++; } else { var_close = TRUE; goto process_closing; } } if (text_mode) { text_len++; } if (token_idx == DYNNAME_TOKENS_MAX) { Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): too many tokens (text / variable combination) defined in '%s'.\n", config.name, config.type, s); exit_gracefully(1); } } if (var_mode) { if (var_len > 1 /* dollar plus at least one valid char */ && var_len < sizeof(var_buf)) { int reg_idx, reg_match = FALSE; memset(var_buf, 0, sizeof(var_buf)); strncpy(var_buf, ptr_var + 1, var_len - 1); for (reg_idx = 0; dynname_token_dict_registry[reg_idx].id; reg_idx++) { if (dynname_token_dict_registry[reg_idx].id == type) { tokens->type = &dynname_token_dict_registry[reg_idx]; ret = dynname_token_dict_registry[reg_idx].func(tokens, var_buf, token_idx); if (ret == E_NOTFOUND) { Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): unknown variable '%s' in dictionary '%s'.\n", config.name, config.type, var_buf, dynname_token_dict_registry[reg_idx].desc); exit_gracefully(1); } reg_match = TRUE; break; } } if (!reg_match) { assert(dynname_token_dict_registry[reg_idx].id == DYN_STR_UNKNOWN); dynname_token_dict_registry[reg_idx].func(tokens, var_buf, token_idx); /* exit */ } } else { ptr_var[var_len] = '\0'; Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): invalid variable '%s' in '%s'.\n", config.name, config.type, ptr_var, s); exit_gracefully(1); } } if (text_mode) { if (text_len && text_len < sizeof(text_buf)) { memset(text_buf, 0, sizeof(text_buf)); strncpy(text_buf, ptr_text, text_len); tokens->func[token_idx] = dynname_text_token_handler; tokens->static_arg[token_idx] = strdup(text_buf); } else { ptr_text[text_len] = '\0'; Log(LOG_ERR, "ERROR ( %s/%s ): dynname_tokens_prepare(): invalid text '%s' in '%s'.\n", config.name, config.type, ptr_text, s); exit_gracefully(1); } } } void dynname_tokens_free(struct dynname_tokens *tokens) { int idx; for (idx = 0; idx < DYNNAME_TOKENS_MAX; idx++) { tokens->func[idx] = NULL; if (tokens->static_arg[idx]) { free(tokens->static_arg[idx]); tokens->static_arg[idx] = NULL; } } } int dynname_tokens_compose(char *s, int slen, struct dynname_tokens *tokens, void *dyn_arg) { int ret = FALSE, idx; for (idx = 0; (idx < DYNNAME_TOKENS_MAX) && tokens->func[idx]; idx++) { ret = (*tokens->func[idx])(s, slen, tokens->static_arg[idx], dyn_arg); if (ret != FALSE) { Log(LOG_WARNING, "WARN ( %s/%s ): dynname_tokens_compose(): string too short when dynamic composing %s.\n", config.name, config.type, tokens->type->desc); break; } } return ret; } int dynname_text_token_handler(char *s, int slen, char *static_arg, void *dyn_arg) { int st_len = strlen(s); int sa_len = strlen(static_arg); int ret = FALSE; if ((st_len + sa_len) < slen) { strcat(s, static_arg); } else { ret = ERR; } return ret; } int dwi_proc_name_handler(char *s, int slen, char *static_arg, void *dyn_arg) { int st_len = strlen(s); int ret = FALSE; char *name = NULL; if (config.type_id == PLUGIN_ID_CORE) { name = config.proc_name; } else { name = config.name; } if (strlen(name) + st_len < slen) { strcat(s, name); } else { ret = ERR; } return ret; } int dwi_writer_pid_handler(char *s, int slen, char *static_arg, void *dyn_arg) { int st_len = strlen(s); int ret = FALSE; char pid[SUPERSHORTBUFLEN]; snprintf(pid, sizeof(pid), "%d", getpid()); if (strlen(pid) + st_len < slen) { strcat(s, pid); } else { ret = ERR; } return ret; } int dwi_pmacct_build_handler(char *s, int slen, char *static_arg, void *dyn_arg) { int st_len = strlen(s); int pb_len = strlen(PMACCT_BUILD); int ret = FALSE; if (pb_len + st_len < slen) { strcat(s, PMACCT_BUILD); } else { ret = ERR; } return ret; } int dtdr_writer_id(void *tkns, char *var_name, int var_idx) { struct dynname_tokens *tokens = tkns; int dindex = 0, ret = E_NOTFOUND; for (dindex = 0; strcmp(dynname_writer_id_dictionary[dindex].key, ""); dindex++) { if (!strcasecmp(dynname_writer_id_dictionary[dindex].key, var_name)) { tokens->func[var_idx] = dynname_writer_id_dictionary[dindex].func; tokens->static_arg[var_idx] = FALSE; ret = FALSE; break; } } return ret; } int dtdr_unknown(void *tkns, char *var_name, int var_idx) { Log(LOG_ERR, "ERROR ( %s/%s ): dtdr_unknown(): unknown dynname_tokens_prepare() type.\n", config.name, config.type); exit_gracefully(1); return FALSE; } /* Future: tokenization part to be moved away from runtime */ int handle_dynname_internal_strings(char *new, int newlen, char *old, struct primitives_ptrs *prim_ptrs, int type) { /* applies only to DYN_STR_PRINT_FILE and DYN_STR_SQL_TABLE */ char ref_string[] = "$ref", hst_string[] = "$hst"; /* applies to all */ char psi_string[] = "$peer_src_ip", tag_string[] = "$tag", tag2_string[] = "$tag2"; char post_tag_string[] = "$post_tag", post_tag2_string[] = "$post_tag2"; /* applies only to DYN_STR_KAFKA_PART */ char src_host_string[] = "$src_host", dst_host_string[] = "$dst_host"; char src_port_string[] = "$src_port", dst_port_string[] = "$dst_port"; char proto_string[] = "$proto", in_iface_string[] = "$in_iface"; char buf[newlen], *ptr_start, *ptr_end, *ptr_var, *ptr_substr, *last_char; int oldlen, var_num, var_len, rem_len, sub_len; if (!new || !old || !prim_ptrs) return ERR; oldlen = strlen(old); if (oldlen <= newlen) strcpy(new, old); else return ERR; for (var_num = 0, ptr_substr = new, ptr_var = strchr(ptr_substr, '$'); ptr_var; var_num++) { rem_len = newlen - (ptr_var - new); /* tokenizing: valid charset: a-z, A-Z, 0-9, _ */ for (var_len = 1, last_char = NULL; var_len < rem_len; var_len++) { if ((ptr_var[var_len] >= '\x30' && ptr_var[var_len] <= '\x39') || (ptr_var[var_len] >= '\x41' && ptr_var[var_len] <= '\x5a') || (ptr_var[var_len] >= '\x61' && ptr_var[var_len] <= '\x7a') || ptr_var[var_len] == '\x5f') last_char = &ptr_var[var_len]; else { if ((*last_char) == '\x5f') var_len--; break; } } /* string tests */ sub_len = 0; if ((type == DYN_STR_SQL_TABLE || type == DYN_STR_PRINT_FILE) && !strncmp(ptr_var, ref_string, var_len)) { int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += 4; len = strlen(ptr_end); snprintf(buf, newlen, "%u", config.sql_refresh_time); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_SQL_TABLE || type == DYN_STR_PRINT_FILE) && !strncmp(ptr_var, hst_string, var_len)) { int len, howmany; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += 4; len = strlen(ptr_end); howmany = sql_history_to_secs(config.sql_history, config.sql_history_howmany); snprintf(buf, newlen, "%u", howmany); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if (!strncmp(ptr_var, psi_string, var_len)) { char empty_peer_src_ip[] = "null"; char peer_src_ip[INET6_ADDRSTRLEN]; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(psi_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->pbgp) addr_to_str(peer_src_ip, &prim_ptrs->pbgp->peer_src_ip); else strlcpy(peer_src_ip, empty_peer_src_ip, strlen(peer_src_ip)); escape_ip_uscores(peer_src_ip); snprintf(buf, newlen, "%s", peer_src_ip); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if (!strncmp(ptr_var, tag_string, var_len)) { pm_id_t zero_tag = 0; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(tag_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%" PRIu64 "", prim_ptrs->data->primitives.tag); else snprintf(buf, newlen, "%" PRIu64 "", zero_tag); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if (!strncmp(ptr_var, tag2_string, var_len)) { pm_id_t zero_tag = 0; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(tag2_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%" PRIu64 "", prim_ptrs->data->primitives.tag2); else snprintf(buf, newlen, "%" PRIu64 "", zero_tag); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if (!strncmp(ptr_var, post_tag_string, var_len)) { int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(post_tag_string); len = strlen(ptr_end); snprintf(buf, newlen, "%" PRIu64 "", config.post_tag); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if (!strncmp(ptr_var, post_tag2_string, var_len)) { int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(post_tag2_string); len = strlen(ptr_end); snprintf(buf, newlen, "%" PRIu64 "", config.post_tag2); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, src_host_string, var_len)) { char empty_src_host[] = "null"; char src_host[INET6_ADDRSTRLEN]; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(src_host_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) addr_to_str(src_host, &prim_ptrs->data->primitives.src_ip); else strlcpy(src_host, empty_src_host, strlen(src_host)); escape_ip_uscores(src_host); snprintf(buf, newlen, "%s", src_host); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, dst_host_string, var_len)) { char empty_dst_host[] = "null"; char dst_host[INET6_ADDRSTRLEN]; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(dst_host_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) addr_to_str(dst_host, &prim_ptrs->data->primitives.dst_ip); else strlcpy(dst_host, empty_dst_host, strlen(dst_host)); escape_ip_uscores(dst_host); snprintf(buf, newlen, "%s", dst_host); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, src_port_string, var_len)) { u_int16_t zero_port = 0; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(src_port_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%hu", prim_ptrs->data->primitives.src_port); else snprintf(buf, newlen, "%hu", zero_port); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, dst_port_string, var_len)) { u_int16_t zero_port = 0; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(dst_port_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%hu", prim_ptrs->data->primitives.dst_port); else snprintf(buf, newlen, "%hu", zero_port); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, proto_string, var_len)) { int null_proto = -1; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(proto_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%d", prim_ptrs->data->primitives.proto); else snprintf(buf, newlen, "%d", null_proto); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, in_iface_string, var_len)) { int null_in_iface = 0; int len; ptr_start = ptr_var; ptr_end = ptr_start; ptr_end += strlen(in_iface_string); len = strlen(ptr_end); if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%u", prim_ptrs->data->primitives.ifindex_in); else snprintf(buf, newlen, "%u", null_in_iface); sub_len = strlen(buf); if ((sub_len + len) >= newlen) return ERR; strncat(buf, ptr_end, len); len = strlen(buf); *ptr_start = '\0'; if (len >= rem_len) return ERR; strncat(new, buf, rem_len); } if (sub_len) ptr_substr = ptr_var + sub_len; else ptr_substr = ptr_var + var_len; ptr_var = strchr(ptr_substr, '$'); } return SUCCESS; } int have_dynname_nontime(char *str) { char tzone_string[] = "$tzone", *ptr, *newptr; int tzone_strlen = strlen(tzone_string); for (newptr = ptr = str; (newptr = strchr(ptr, '$')); ptr = newptr, ptr++) { if (strncmp(newptr, tzone_string, tzone_strlen)) return TRUE; } return FALSE; } void escape_ip_uscores(char *str) { int idx, len = 0; if (str) len = strlen(str); for (idx = 0; idx < len; idx++) { if (str[idx] == '.' || str[idx] == ':') str[idx] = '_'; } } int handle_dynname_internal_strings_same(char *s, int max, char *tmp, struct primitives_ptrs *prim_ptrs, int type) { int ret; ret = handle_dynname_internal_strings(tmp, max, s, prim_ptrs, type); strlcpy(s, tmp, max); return ret; } int sql_history_to_secs(int mu, int howmany) { int ret = 0; if (mu == COUNT_SECONDLY) ret = howmany; else if (mu == COUNT_MINUTELY) ret = howmany*60; else if (mu == COUNT_HOURLY) ret = howmany*3600; else if (mu == COUNT_DAILY) ret = howmany*86400; else if (mu == COUNT_WEEKLY) ret = howmany*86400*7; else if (mu == COUNT_MONTHLY) ret = howmany*86400*30; /* XXX: this is an approx! */ return ret; } void write_pid_file(char *filename) { FILE *file; char pid[10]; uid_t owner = -1; gid_t group = -1; unlink(filename); if (config.files_uid) owner = config.files_uid; if (config.files_gid) group = config.files_gid; file = fopen(filename,"w"); if (file) { if (chown(filename, owner, group) == -1) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown(): %s\n", config.name, config.type, filename, strerror(errno)); if (file_lock(fileno(file))) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, filename); return; } sprintf(pid, "%d\n", getpid()); fwrite(pid, strlen(pid), 1, file); file_unlock(fileno(file)); fclose(file); } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, config.type, filename); return; } } void write_pid_file_plugin(char *filename, char *type, char *name) { int len = strlen(filename) + strlen(type) + strlen(name) + 3; FILE *file; char *fname, pid[10], minus[] = "-"; uid_t owner = -1; gid_t group = -1; fname = malloc(len); if (!fname) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename); return; } memset(fname, 0, len); strcpy(fname, filename); strcat(fname, minus); strcat(fname, type); strcat(fname, minus); strcat(fname, name); config.pidfile = fname; unlink(fname); if (config.files_uid) owner = config.files_uid; if (config.files_gid) group = config.files_gid; file = fopen(fname, "w"); if (file) { if (chown(fname, owner, group) == -1) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown(): %s\n", config.name, config.type, fname, strerror(errno)); if (file_lock(fileno(file))) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, fname); goto exit_lane; } sprintf(pid, "%d\n", getpid()); fwrite(pid, strlen(pid), 1, file); file_unlock(fileno(file)); fclose(file); } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, config.type, fname); goto exit_lane; } return; exit_lane: config.pidfile = NULL; free(fname); } void remove_pid_file(char *filename) { unlink(filename); } int file_lock(int fd) { int ret; #if defined SOLARIS flock_t lock; lock.l_type = F_WRLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; ret = fcntl(fd, F_SETLK, &lock); return((ret == -1) ? -1 : 0); #else ret = lockf(fd, F_LOCK, 0); return ret; #endif } int file_unlock(int fd) { int ret; #if defined SOLARIS flock_t lock; lock.l_type = F_UNLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; ret = fcntl(fd, F_SETLK, &lock); return((ret == -1) ? -1 : 0); #else ret = lockf(fd, F_ULOCK, 0); return ret; #endif } int sanitize_buf_net(char *filename, char *buf, int rows) { if (!sanitize_buf(buf)) { if (!strchr(buf, '/')) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Missing '/' separator. Ignoring.\n", config.name, config.type, filename, rows); return TRUE; } } else return TRUE; return FALSE; } int sanitize_buf(char *buf) { int x = 0, valid_char = 0; trim_all_spaces(buf); while (x < strlen(buf)) { if (!isspace(buf[x])) valid_char++; x++; } if (!valid_char) return TRUE; if (buf[0] == '!') return TRUE; return FALSE; } int check_not_valid_char(char *filename, char *buf, int c) { if (!buf) return FALSE; if (strchr(buf, c)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Invalid symbol '%c' detected.\n", config.name, config.type, filename, c); return TRUE; } else return FALSE; } void mark_columns(char *buf) { int len, x, word = FALSE, quotes = FALSE; if (!buf) return; len = strlen(buf); for (x = 0; x < len; x++) { if (buf[x] == '\'') { if (!quotes) quotes = TRUE; else if (quotes) quotes = FALSE; } if ((isalpha(buf[x])||isdigit(buf[x])||ispunct(buf[x])) && !word) word = TRUE; if (isspace(buf[x]) && word && !quotes) { buf[x] = '|'; word = FALSE; } } /* removing trailing '|' if any */ x = strlen(buf); word = FALSE; while (x > 0) { if (buf[x] == '|' && !word) buf[x] = '\0'; if ((isalpha(buf[x])||isdigit(buf[x])||ispunct(buf[x])) && !word) word = TRUE; x--; } } int Setsocksize(int s, int level, int optname, void *optval, socklen_t optlen) { int ret = 0, saved, value; socklen_t len = sizeof(int); memcpy(&value, optval, sizeof(int)); getsockopt(s, level, optname, &saved, &len); if (value > saved) { for (; value; value >>= 1) { ret = setsockopt(s, level, optname, &value, optlen); if (ret >= 0) break; } if (!value) setsockopt(s, level, optname, &saved, len); } return ret; } void *map_shared(void *addr, size_t len, int prot, int flags, int fd, off_t off) { #if defined USE_DEVZERO void *mem; int devzero; devzero = open ("/dev/zero", O_RDWR); if (devzero < 0) return MAP_FAILED; mem = mmap(addr, len, prot, flags, devzero, off); close(devzero); return mem; #else /* MAP_ANON or MAP_ANONYMOUS */ return (void *)mmap(addr, len, prot, flags, fd, off); #endif } void lower_string(char *string) { int i = 0; if (!string) return; while (string[i] != '\0') { string[i] = tolower(string[i]); i++; } } void evaluate_sums(u_int64_t *wtc, u_int64_t *wtc_2, char *name, char *type) { int tag = FALSE; int tag2 = FALSE; int class = FALSE; int ndpi_class = FALSE; int flows = FALSE; if (*wtc & COUNT_TAG) { *wtc ^= COUNT_TAG; tag = TRUE; } if (*wtc & COUNT_TAG2) { *wtc ^= COUNT_TAG2; tag2 = TRUE; } if (*wtc & COUNT_CLASS) { *wtc ^= COUNT_CLASS; class = TRUE; } if (*wtc_2 & COUNT_NDPI_CLASS) { *wtc_2 ^= COUNT_NDPI_CLASS; ndpi_class = TRUE; } if (*wtc & COUNT_FLOWS) { *wtc ^= COUNT_FLOWS; flows = TRUE; } if (*wtc & COUNT_SUM_MAC) { if (*wtc != COUNT_SUM_MAC) { *wtc = COUNT_SUM_MAC; Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type); } } if (*wtc & COUNT_SUM_HOST) { if (*wtc != COUNT_SUM_HOST) { *wtc = COUNT_SUM_HOST; Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type); } } else if (*wtc & COUNT_SUM_NET) { if (*wtc != COUNT_SUM_NET) { *wtc = COUNT_SUM_NET; Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type); } } else if (*wtc & COUNT_SUM_AS) { if (*wtc != COUNT_SUM_AS) { *wtc = COUNT_SUM_AS; Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type); } } else if (*wtc & COUNT_SUM_PORT) { if (*wtc != COUNT_SUM_PORT) { *wtc = COUNT_SUM_PORT; Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type); } } if (tag) *wtc |= COUNT_TAG; if (tag2) *wtc |= COUNT_TAG2; if (class) *wtc |= COUNT_CLASS; if (ndpi_class) *wtc_2 |= COUNT_NDPI_CLASS; if (flows) *wtc |= COUNT_FLOWS; } void stop_all_childs() { PM_sigint_handler(0); /* it does same thing */ } void pm_strftime(char *s, int max, char *format, const time_t *time_ref, int utc) { time_t time_loc; struct tm *tm_loc; if (time_ref && (*time_ref)) time_loc = (*time_ref); else time_loc = time(NULL); if (!utc) tm_loc = localtime(&time_loc); else tm_loc = gmtime(&time_loc); strftime(s, max, format, tm_loc); insert_rfc3339_timezone(s, max, tm_loc); } /* format is expected in s; tmp being just a temporary buffer; both s and tmp are expected to be of at least max space */ void pm_strftime_same(char *s, int max, char *tmp, const time_t *time_ref, int utc) { time_t time_loc; struct tm *tm_loc; if (time_ref && (*time_ref)) time_loc = (*time_ref); else time_loc = time(NULL); if (!utc) tm_loc = localtime(&time_loc); else tm_loc = gmtime(&time_loc); strftime(tmp, max, s, tm_loc); insert_rfc3339_timezone(tmp, max, tm_loc); strlcpy(s, tmp, max); } void insert_rfc3339_timezone(char *s, int slen, const struct tm *nowtm) { char buf[8], tzone_string[] = "$tzone"; char *ptr_start = strstr(s, tzone_string), *ptr_end; if (ptr_start) { ptr_end = ptr_start + 6 /* $tzone */; strftime(buf, 8, "%z", nowtm); if (!strcmp(buf, "+0000")) { ptr_start[0] = 'Z'; ptr_start++; strcpy(ptr_start, ptr_end); } else { /* ie. '+0200', '-0100', etc. */ if (strlen(buf) == 5) { ptr_start[0] = buf[0]; ptr_start[1] = buf[1]; ptr_start[2] = buf[2]; ptr_start[3] = ':'; ptr_start[4] = buf[3]; ptr_start[5] = buf[4]; } } } } void append_rfc3339_timezone(char *s, int slen, const struct tm *nowtm) { int len = strlen(s), max = (slen - len); char buf[8], zulu[] = "Z"; strftime(buf, 8, "%z", nowtm); if (!strcmp(buf, "+0000")) { if (max) strcat(s, zulu); } else { if (max >= 7) { s[len] = buf[0]; len++; s[len] = buf[1]; len++; s[len] = buf[2]; len++; s[len] = ':'; len++; s[len] = buf[3]; len++; s[len] = buf[4]; len++; s[len] = '\0'; } } } int read_SQLquery_from_file(char *path, char *buf, int size) { FILE *f; char *ptr; int ret; memset(buf, 0, size); f = fopen(path, "r"); if (!f) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file does not exist.\n", config.name, config.type, path); return(0); } ret = fread(buf, size, 1, f); if (ret != 1 && !feof(f)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to read from SQL schema: %s\n", config.name, config.type, path, strerror(errno)); return(0); } fclose(f); ptr = strrchr(buf, ';'); if (!ptr) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] missing trailing ';' in SQL query.\n", config.name, config.type, path); return(0); } else *ptr = '\0'; return (int)*ptr-(int)*buf; } void stick_bosbit(u_char *label) { u_char *ptr; ptr = label+2; *ptr |= 0x1; } int check_bosbit(u_char *label) { u_char *ptr; ptr = label+2; if (*ptr & 0x1) return TRUE; else return FALSE; } u_int32_t decode_mpls_label(u_char *label) { u_int32_t ret = 0; u_char label_ttl[4]; memset(label_ttl, 0, 4); memcpy(label_ttl, label, 3); ret = ntohl(*(uint32_t *)(label_ttl)); ret = ((ret & 0xfffff000 /* label mask */) >> 12 /* label shift */); return ret; } void encode_mpls_label(char *out_label, u_int32_t in_label) { u_int32_t tmp; u_char loc_label[4]; memset(out_label, 0, 3); tmp = in_label; tmp <<= 4; /* label shift */ memcpy(loc_label, &tmp, 4); out_label[0] = loc_label[2]; out_label[1] = loc_label[1]; out_label[2] = loc_label[0]; } /* * timeval_cmp(): returns > 0 if a > b; < 0 if a < b; 0 if a == b. */ int timeval_cmp(struct timeval *a, struct timeval *b) { if (a->tv_sec > b->tv_sec) return 1; if (a->tv_sec < b->tv_sec) return -1; if (a->tv_sec == b->tv_sec) { if (a->tv_usec > b->tv_usec) return 1; if (a->tv_usec < b->tv_usec) return -1; if (a->tv_usec == b->tv_usec) return 0; } return INT_MIN; /* silence compiler warning */ } void signal_kittens(int sig, int amicore_check) { struct plugins_list_entry *list = plugins_list; struct channels_list_entry *chptr = channels_list; /* round #1: safety check, am i the core process? */ if (amicore_check) { if (!chptr || chptr->core_pid != getpid()) { return; } } /* round #2: do it */ list = plugins_list; while (list) { if (memcmp(list->type.string, "core", sizeof("core"))) { kill(list->pid, sig); } list = list->next; } } /* * exit_all(): Core Process exit lane. Not meant to be a nice shutdown method: it is * an exit() replacement that sends kill signals to the plugins. */ void exit_all(int status) { #if defined (SOLARIS) signal(SIGCHLD, SIG_IGN); #else signal(SIGCHLD, ignore_falling_child); #endif signal_kittens(SIGKILL, TRUE); wait(NULL); if (config.pidfile) remove_pid_file(config.pidfile); exit(status); } /* exit_plugin(): meant to be called on exit by plugins; it is a simple wrapper to enforce some final operations before shutting down */ void exit_plugin(int status) { if (config.pidfile) remove_pid_file(config.pidfile); exit(status); } void exit_gracefully(int status) { if (!config.is_forked) { if (config.type_id == PLUGIN_ID_CORE) exit_all(status); else exit_plugin(status); } else exit(status); } void reset_tag_label_status(struct packet_ptrs_vector *pptrsv) { pptrsv->v4.tag = FALSE; pptrsv->vlan4.tag = FALSE; pptrsv->mpls4.tag = FALSE; pptrsv->vlanmpls4.tag = FALSE; pptrsv->v4.tag2 = FALSE; pptrsv->vlan4.tag2 = FALSE; pptrsv->mpls4.tag2 = FALSE; pptrsv->vlanmpls4.tag2 = FALSE; pretag_free_label(&pptrsv->v4.label); pretag_free_label(&pptrsv->vlan4.label); pretag_free_label(&pptrsv->mpls4.label); pretag_free_label(&pptrsv->vlanmpls4.label); pptrsv->v6.tag = FALSE; pptrsv->vlan6.tag = FALSE; pptrsv->mpls6.tag = FALSE; pptrsv->vlanmpls6.tag = FALSE; pptrsv->v6.tag2 = FALSE; pptrsv->vlan6.tag2 = FALSE; pptrsv->mpls6.tag2 = FALSE; pptrsv->vlanmpls6.tag2 = FALSE; pretag_free_label(&pptrsv->v6.label); pretag_free_label(&pptrsv->vlan6.label); pretag_free_label(&pptrsv->mpls6.label); pretag_free_label(&pptrsv->vlanmpls6.label); } void reset_net_status(struct packet_ptrs *pptrs) { pptrs->lm_mask_src = FALSE; pptrs->lm_mask_dst = FALSE; pptrs->lm_method_src = FALSE; pptrs->lm_method_dst = FALSE; } void reset_net_status_v(struct packet_ptrs_vector *pptrsv) { pptrsv->v4.lm_mask_src = FALSE; pptrsv->vlan4.lm_mask_src = FALSE; pptrsv->mpls4.lm_mask_src = FALSE; pptrsv->vlanmpls4.lm_mask_src = FALSE; pptrsv->v4.lm_mask_dst = FALSE; pptrsv->vlan4.lm_mask_dst = FALSE; pptrsv->mpls4.lm_mask_dst = FALSE; pptrsv->vlanmpls4.lm_mask_dst = FALSE; pptrsv->v4.lm_method_src = FALSE; pptrsv->vlan4.lm_method_src = FALSE; pptrsv->mpls4.lm_method_src = FALSE; pptrsv->vlanmpls4.lm_method_src = FALSE; pptrsv->v4.lm_method_dst = FALSE; pptrsv->vlan4.lm_method_dst = FALSE; pptrsv->mpls4.lm_method_dst = FALSE; pptrsv->vlanmpls4.lm_method_dst = FALSE; pptrsv->v6.lm_mask_src = FALSE; pptrsv->vlan6.lm_mask_src = FALSE; pptrsv->mpls6.lm_mask_src = FALSE; pptrsv->vlanmpls6.lm_mask_src = FALSE; pptrsv->v6.lm_mask_dst = FALSE; pptrsv->vlan6.lm_mask_dst = FALSE; pptrsv->mpls6.lm_mask_dst = FALSE; pptrsv->vlanmpls6.lm_mask_dst = FALSE; pptrsv->v6.lm_method_src = FALSE; pptrsv->vlan6.lm_method_src = FALSE; pptrsv->mpls6.lm_method_src = FALSE; pptrsv->vlanmpls6.lm_method_src = FALSE; pptrsv->v6.lm_method_dst = FALSE; pptrsv->vlan6.lm_method_dst = FALSE; pptrsv->mpls6.lm_method_dst = FALSE; pptrsv->vlanmpls6.lm_method_dst = FALSE; } void reset_shadow_status(struct packet_ptrs_vector *pptrsv) { pptrsv->v4.shadow = FALSE; pptrsv->vlan4.shadow = FALSE; pptrsv->mpls4.shadow = FALSE; pptrsv->vlanmpls4.shadow = FALSE; pptrsv->v6.shadow = FALSE; pptrsv->vlan6.shadow = FALSE; pptrsv->mpls6.shadow = FALSE; pptrsv->vlanmpls6.shadow = FALSE; } void reset_fallback_status(struct packet_ptrs *pptrs) { pptrs->renormalized = FALSE; } void set_default_preferences(struct configuration *cfg) { if (!cfg->proc_name) cfg->proc_name = default_proc_name; if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { if (!cfg->nfacctd_net) cfg->nfacctd_net = NF_NET_KEEP; if (!cfg->nfacctd_as) cfg->nfacctd_as = NF_AS_KEEP; set_truefalse_nonzero(&cfg->nfacctd_disable_checks); } if (!cfg->bgp_daemon_peer_as_src_type) cfg->bgp_daemon_peer_as_src_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_std_comm_type) cfg->bgp_daemon_src_std_comm_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_ext_comm_type) cfg->bgp_daemon_src_ext_comm_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_lrg_comm_type) cfg->bgp_daemon_src_lrg_comm_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_as_path_type) cfg->bgp_daemon_src_as_path_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_local_pref_type) cfg->bgp_daemon_src_local_pref_type = BGP_SRC_PRIMITIVES_KEEP; if (!cfg->bgp_daemon_src_med_type) cfg->bgp_daemon_src_med_type = BGP_SRC_PRIMITIVES_KEEP; } void set_shadow_status(struct packet_ptrs *pptrs) { pptrs->shadow = TRUE; } void set_sampling_table(struct packet_ptrs_vector *pptrsv, u_char *t) { pptrsv->v4.sampling_table = t; pptrsv->vlan4.sampling_table = t; pptrsv->mpls4.sampling_table = t; pptrsv->vlanmpls4.sampling_table = t; pptrsv->v6.sampling_table = t; pptrsv->vlan6.sampling_table = t; pptrsv->mpls6.sampling_table = t; pptrsv->vlanmpls6.sampling_table = t; } void *pm_malloc(size_t size) { unsigned char *obj; obj = (unsigned char *) malloc(size); if (!obj) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to grab enough memory (requested: %zu bytes). Exiting ...\n", config.name, config.type, size); exit_gracefully(1); } return obj; } void *pm_tsearch(const void *key, void **rootp, int (*compar)(const void *key1, const void *key2), size_t alloc_size) { void *alloc_key, *ret_key; if (alloc_size) { alloc_key = malloc(alloc_size); memcpy(alloc_key, key, alloc_size); ret_key = __pm_tsearch(alloc_key, rootp, compar); if ((*(void **) ret_key) != alloc_key) free(alloc_key); return ret_key; } else return __pm_tsearch(key, rootp, compar); } void pm_tdestroy(void **root, void (*free_node)(void *nodep)) { /* in implementations where tdestroy() is not defined, tdelete() against the root node of the tree would destroy also the last few remaining bits */ #if (defined HAVE_TDESTROY) __pm_tdestroy((*root), free_node); #endif (*root) = NULL; } void load_allow_file(char *filename, struct hosts_table *t) { struct stat st; FILE *file; char buf[SRVBUFLEN]; int index = 0; if (filename) { if ((file = fopen(filename, "r")) == NULL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename); goto handle_error; } memset(t->table, 0, sizeof(t->table)); while (!feof(file)) { if (index >= MAX_MAP_ENTRIES) break; /* XXX: we shouldn't exit silently */ memset(buf, 0, SRVBUFLEN); if (fgets(buf, SRVBUFLEN, file)) { if (!sanitize_buf(buf)) { if (str_to_addr_mask(buf, &t->table[index].addr, &t->table[index].mask)) index++; else Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad IP address '%s'. Ignored.\n", config.name, config.type, filename, buf); } } } t->num = index; /* Set to -1 to distinguish between no map and empty map conditions */ if (!t->num) t->num = -1; fclose(file); stat(filename, &st); t->timestamp = st.st_mtime; } return; handle_error: if (t->timestamp) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back old map.\n", config.name, config.type, filename); stat(filename, &st); t->timestamp = st.st_mtime; } else exit_gracefully(1); } int check_allow(struct hosts_table *allow, struct sockaddr *sa) { int index; if (!allow || !sa) return FALSE; for (index = 0; index < allow->num; index++) { if (host_addr_mask_sa_cmp(&allow->table[index].addr, &allow->table[index].mask, sa) == 0) return TRUE; } return FALSE; } int BTA_find_id(struct id_table *t, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2) { struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status; struct xflow_status_map_cache *xsmc = NULL; int ret = 0; pptrs->bta_af = 0; if (bta_map_caching && xsentry) { if (pptrs->l3_proto == ETHERTYPE_IP) xsmc = &xsentry->bta_v4; else if (pptrs->l3_proto == ETHERTYPE_IPV6) xsmc = &xsentry->bta_v6; } if (bta_map_caching && xsmc && timeval_cmp(&xsmc->stamp, &reload_map_tstamp) > 0) { *tag = xsmc->tag; *tag2 = xsmc->tag2; ret = xsmc->ret; memcpy(&pptrs->lookup_bgp_port, &xsmc->port, sizeof(s_uint16_t)); } else { if (find_id_func) { ret = find_id_func(t, pptrs, tag, tag2); if (xsmc) { xsmc->tag = *tag; xsmc->tag2 = *tag2; xsmc->ret = ret; memcpy(&xsmc->port, &pptrs->lookup_bgp_port, sizeof(s_uint16_t)); gettimeofday(&xsmc->stamp, NULL); } } } if (ret & PRETAG_MAP_RCODE_ID) pptrs->bta_af = ETHERTYPE_IP; else if (ret & BTA_MAP_RCODE_ID_ID2) pptrs->bta_af = ETHERTYPE_IPV6; return ret; } void calc_refresh_timeout(time_t deadline, time_t now, int *timeout) { if (deadline >= now) *timeout = ((deadline-now)+1)*1000; else *timeout = 0; } /* secs version of calc_refresh_timeout() */ void calc_refresh_timeout_sec(time_t deadline, time_t now, int *timeout) { if (deadline >= now) *timeout = ((deadline-now)+1); else *timeout = 0; } int load_tags(char *filename, struct pretag_filter *filter, char *value_ptr) { char *count_token, *range_ptr; pm_id_t value = 0, range = 0; int changes = 0; char *endptr_v, *endptr_r; u_int8_t neg; if (!filter || !value_ptr) return changes; trim_all_spaces(value_ptr); filter->num = 0; while ((count_token = extract_token(&value_ptr, ',')) && changes < MAX_PRETAG_MAP_ENTRIES/4) { neg = pt_check_neg(&count_token, NULL); range_ptr = pt_check_range(count_token); value = strtoull(count_token, &endptr_v, 10); if (range_ptr) range = strtoull(range_ptr, &endptr_r, 10); else range = value; if (range_ptr && range <= value) { Log(LOG_ERR, "WARN ( %s/%s ): [%s] Range value is expected in format low-high. '%" PRIu64 "-%" PRIu64 "'.\n", config.name, config.type, filename, value, range); changes++; break; } filter->table[filter->num].neg = neg; filter->table[filter->num].n = value; filter->table[filter->num].r = range; filter->num++; changes++; } return changes; } int load_labels(char *filename, struct pretag_label_filter *filter, char *value_ptr) { char *count_token, *value; int changes = 0; u_int8_t neg = 0; if (!filter || !value_ptr) return changes; filter->num = 0; while ((count_token = extract_token(&value_ptr, ',')) && changes < MAX_PRETAG_MAP_ENTRIES/4) { neg = pt_check_neg(&count_token, NULL); value = count_token; filter->table[filter->num].neg = neg; filter->table[filter->num].v = value; filter->table[filter->num].len = strlen(value); filter->num++; changes++; } return changes; } /* return value: TRUE: We want it! FALSE: Discard it! */ int evaluate_tags(struct pretag_filter *filter, pm_id_t tag) { int index; if (filter->num == 0) return FALSE; /* no entries in the filter array: tag filtering disabled */ for (index = 0; index < filter->num; index++) { if (filter->table[index].n <= tag && filter->table[index].r >= tag) return (FALSE | filter->table[index].neg); else if (filter->table[index].neg) return FALSE; } return TRUE; } int evaluate_labels(struct pretag_label_filter *filter, pt_label_t *label) { int index, ret; int null_label_len = 4; /* 'null' excluding terminating zero */ char *null_label = "null"; if (filter->num == 0) return FALSE; /* no entries in the filter array: tag filtering disabled */ if (!label->val) { label->val = null_label; label->len = null_label_len; } for (index = 0; index < filter->num; index++) { if (filter->table[index].len != label->len) { ret = TRUE; } else { ret = FALSE; } if (!ret) { ret = memcmp(filter->table[index].v, label->val, filter->table[index].len); } /* cleanup */ if (label->val == null_label) { label->val = NULL; label->len = 0; } if (!ret) { return (FALSE | filter->table[index].neg); } else { if (filter->table[index].neg) { return FALSE; } } } return TRUE; } char *write_sep(char *sep, int *count) { static char empty_sep[] = ""; if (*count) return sep; else { (*count)++; return empty_sep; } } void version_daemon(int acct_type, char *header) { struct utsname utsbuf; printf("%s %s [%s]\n\n", header, PMACCT_VERSION, PMACCT_BUILD); printf("Arguments:\n"); printf("%s\n", PMACCT_COMPILE_ARGS); printf("\n"); printf("Libs:\n"); printf("cdada %s\n", cdada_get_ver()); printf("%s\n", pcap_lib_version()); #ifdef WITH_MYSQL MY_mysql_get_version(); #endif #ifdef WITH_PGSQL PG_postgresql_get_version(); #endif #ifdef WITH_SQLITE3 SQLI_sqlite3_get_version(); #endif #ifdef WITH_RABBITMQ p_amqp_get_version(); #endif #ifdef WITH_KAFKA p_kafka_get_version(); #endif #ifdef WITH_JANSSON printf("jansson %s\n", JANSSON_VERSION); #endif #ifdef WITH_GEOIPV2 printf("MaxmindDB %s\n", MMDB_lib_version()); #endif #ifdef WITH_ZMQ printf("ZeroMQ %u.%u.%u\n", ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH); #endif #ifdef WITH_REDIS printf("Redis %u.%u.%u\n", HIREDIS_MAJOR, HIREDIS_MINOR, HIREDIS_PATCH); #endif #ifdef WITH_GNUTLS printf("GnuTLS %u.%u.%u\n", GNUTLS_VERSION_MAJOR, GNUTLS_VERSION_MINOR, GNUTLS_VERSION_PATCH); #endif #ifdef WITH_AVRO printf("avro-c\n"); #endif #ifdef WITH_SERDES printf("serdes\n"); #endif #ifdef WITH_UNYTE_UDP_NOTIF printf("unyte-udp-notif\n"); #endif #ifdef WITH_NDPI printf("nDPI %s\n", ndpi_revision()); #endif #ifdef WITH_NFLOG printf("netfilter_log\n"); #endif if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM) { printf("\n"); printf("Plugins:\n"); printf("memory\n"); printf("print\n"); printf("nfprobe\n"); printf("sfprobe\n"); printf("tee\n"); #ifdef WITH_MYSQL printf("mysql\n"); #endif #ifdef WITH_PGSQL printf("postgresql\n"); #endif #ifdef WITH_SQLITE3 printf("sqlite\n"); #endif #ifdef WITH_RABBITMQ printf("amqp\n"); #endif #ifdef WITH_KAFKA printf("kafka\n"); #endif } printf("\n"); if (!uname(&utsbuf)) { printf("System:\n"); printf("%s %s %s %s\n", utsbuf.sysname, utsbuf.release, utsbuf.version, utsbuf.machine); printf("\n"); } #if defined __clang__ #ifndef PM_COMPILER_NAME #define PM_COMPILER_NAME "clang" #endif #ifndef PM_COMPILER_VERSION #define PM_COMPILER_VERSION __clang_major__, __clang_minor__, __clang_patchlevel__ #endif #endif #if defined __GNUC__ #ifndef PM_COMPILER_NAME #define PM_COMPILER_NAME "gcc" #endif #ifndef PM_COMPILER_VERSION #define PM_COMPILER_VERSION __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ #endif #endif #if defined PM_COMPILER_NAME && defined PM_COMPILER_VERSION printf("Compiler:\n"); printf("%s %d.%d.%d\n", PM_COMPILER_NAME, PM_COMPILER_VERSION); printf("\n"); #endif printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } #ifdef WITH_JANSSON char *compose_json_str(void *obj) { char *tmpbuf = NULL; tmpbuf = json_dumps(obj, JSON_PRESERVE_ORDER); json_decref(obj); return tmpbuf; } void write_and_free_json(FILE *f, void *obj) { char *tmpbuf = NULL; json_t *json_obj = (json_t *) obj; if (!f) return; /* Waiting for jansson issue #256 on GitHub to be solved, ie. introduction of trailing newline chars, in order to switch to json_dumpf() */ tmpbuf = json_dumps(json_obj, JSON_PRESERVE_ORDER); json_decref(json_obj); if (tmpbuf) { fprintf(f, "%s\n", tmpbuf); free(tmpbuf); } } void add_writer_name_and_pid_json(void *obj, struct dynname_tokens *tokens) { char wid[SHORTSHORTBUFLEN]; json_t *json_obj = (json_t *) obj; memset(wid, 0, sizeof(wid)); dynname_tokens_compose(wid, sizeof(wid), tokens, NULL); json_object_set_new_nocheck(json_obj, "writer_id", json_string(wid)); } #else char *compose_json_str(void *obj) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_json_str(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); return NULL; } void write_and_free_json(FILE *f, void *obj) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): write_and_free_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); } void add_writer_name_and_pid_json(void *obj, struct dynname_tokens *tokens) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): add_writer_name_and_pid_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type); } #endif void write_file_binary(FILE *f, void *obj, size_t len) { if (!f) return; if (obj && len) fwrite(obj, len, 1, f); } void compose_timestamp(char *buf, int buflen, struct timeval *tv, int usec, int since_epoch, int rfc3339, int utc) { int slen; time_t time1; struct tm *time2; if (buflen < VERYSHORTBUFLEN) return; if (since_epoch) { if (usec) snprintf(buf, buflen, "%ld.%.6ld", tv->tv_sec, (long)tv->tv_usec); else snprintf(buf, buflen, "%ld", tv->tv_sec); } else { time1 = tv->tv_sec; if (!utc) time2 = localtime(&time1); else time2 = gmtime(&time1); if (tv->tv_sec) { if (!rfc3339) slen = strftime(buf, buflen, "%Y-%m-%d %H:%M:%S", time2); else slen = strftime(buf, buflen, "%Y-%m-%dT%H:%M:%S", time2); } else { if (!rfc3339) slen = snprintf(buf, buflen, "0000-00-00 00:00:00"); else slen = snprintf(buf, buflen, "0000-00-00T00:00:00"); } if (usec) snprintf((buf + slen), (buflen - slen), ".%.6ld", (long)tv->tv_usec); if (rfc3339) append_rfc3339_timezone(buf, buflen, time2); } } void print_primitives(int acct_type, char *header) { int idx; printf("%s %s (%s)\n", header, PMACCT_VERSION, PMACCT_BUILD); for (idx = 0; strcmp(_primitives_matrix[idx].name, ""); idx++) { if ((acct_type == ACCT_NF && _primitives_matrix[idx].nfacctd) || (acct_type == ACCT_SF && _primitives_matrix[idx].sfacctd) || (acct_type == ACCT_PM && _primitives_matrix[idx].pmacctd)) { if (strcmp(_primitives_matrix[idx].desc, "")) /* entry */ printf("%-32s : %-64s\n", _primitives_matrix[idx].name, _primitives_matrix[idx].desc); else /* title */ printf("\n%s\n", _primitives_matrix[idx].name); } } } void set_primptrs_funcs(struct extra_primitives *extras) { int idx = 0; memset(primptrs_funcs, 0, sizeof(primptrs_funcs)); if (extras->off_pkt_bgp_primitives) { primptrs_funcs[idx] = primptrs_set_bgp; idx++; } if (extras->off_pkt_lbgp_primitives) { primptrs_funcs[idx] = primptrs_set_lbgp; idx++; } if (extras->off_pkt_nat_primitives) { primptrs_funcs[idx] = primptrs_set_nat; idx++; } if (extras->off_pkt_mpls_primitives) { primptrs_funcs[idx] = primptrs_set_mpls; idx++; } if (extras->off_pkt_tun_primitives) { primptrs_funcs[idx] = primptrs_set_tun; idx++; } if (extras->off_custom_primitives) { primptrs_funcs[idx] = primptrs_set_custom; idx++; } if (extras->off_pkt_extras) { primptrs_funcs[idx] = primptrs_set_extras; idx++; } if (extras->off_pkt_vlen_hdr_primitives) { primptrs_funcs[idx] = primptrs_set_vlen_hdr; idx++; } } void primptrs_set_bgp(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pbgp = (struct pkt_bgp_primitives *) (base + extras->off_pkt_bgp_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_lbgp(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->plbgp = (struct pkt_legacy_bgp_primitives *) (base + extras->off_pkt_lbgp_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_nat(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pnat = (struct pkt_nat_primitives *) (base + extras->off_pkt_nat_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_mpls(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pmpls = (struct pkt_mpls_primitives *) (base + extras->off_pkt_mpls_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_tun(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->ptun = (struct pkt_tunnel_primitives *) (base + extras->off_pkt_tun_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_custom(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pcust = (base + extras->off_custom_primitives); prim_ptrs->vlen_next_off = 0; } void primptrs_set_extras(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pextras = (struct pkt_extras *) (base + extras->off_pkt_extras); prim_ptrs->vlen_next_off = 0; } void primptrs_set_vlen_hdr(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs) { prim_ptrs->pvlen = (struct pkt_vlen_hdr_primitives *) (base + extras->off_pkt_vlen_hdr_primitives); prim_ptrs->vlen_next_off = extras->off_pkt_vlen_hdr_primitives + PvhdrSz + prim_ptrs->pvlen->tot_len; } int custom_primitives_vlen(struct custom_primitives_ptrs *cpptrs) { int cpptrs_idx, vlen_prims = 0; struct custom_primitive_entry *cpe; for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) { cpe = cpptrs->primitive[cpptrs_idx].ptr; if (cpe->len == PM_VARIABLE_LENGTH) vlen_prims++; } return vlen_prims; } void custom_primitives_reconcile(struct custom_primitives_ptrs *cpptrs, struct custom_primitives *registry) { int cpptrs_idx, registry_idx; int pad = 0; /* first pass: linking */ for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) { for (registry_idx = 0; registry->primitive[registry_idx].len && registry_idx < registry->num; registry_idx++) { if (!strcmp(cpptrs->primitive[cpptrs_idx].name, registry->primitive[registry_idx].name)) { if (registry->primitive[registry_idx].len == PM_VARIABLE_LENGTH) { cpptrs->primitive[cpptrs_idx].ptr = ®istry->primitive[registry_idx]; cpptrs->primitive[cpptrs_idx].off = PM_VARIABLE_LENGTH; } else if (cpptrs->len + registry->primitive[registry_idx].len < UINT16_MAX) { cpptrs->primitive[cpptrs_idx].ptr = ®istry->primitive[registry_idx]; cpptrs->primitive[cpptrs_idx].off = cpptrs->len; cpptrs->len += registry->primitive[registry_idx].alloc_len; } else { Log(LOG_WARNING, "WARN ( %s/%s ): Max allocatable space for custom primitives finished (%s).\n", config.name, config.type, cpptrs->primitive[cpptrs_idx].name); cpptrs->primitive[cpptrs_idx].ptr = NULL; } break; } } } /* second pass: verification and finish-off */ for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) { if (!cpptrs->primitive[cpptrs_idx].ptr) { Log(LOG_ERR, "ERROR ( %s/%s ): Unknown primitive '%s'\n", config.name, config.type, cpptrs->primitive[cpptrs_idx].name); exit_gracefully(1); } else { struct custom_primitive_entry *cpe = cpptrs->primitive[cpptrs_idx].ptr; if (cpptrs->primitive[cpptrs_idx].off != PM_VARIABLE_LENGTH) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Custom primitive '%s': type=%" PRIx64 " off=%u len=%u\n", config.name, config.type, cpptrs->primitive[cpptrs_idx].name, cpe->type, cpptrs->primitive[cpptrs_idx].off, cpe->len); } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Custom primitive '%s': type=%" PRIx64 " len=vlen\n", config.name, config.type, cpptrs->primitive[cpptrs_idx].name, cpe->type); } } } if (cpptrs->len) pad = 8 - (cpptrs->len % 8); cpptrs->len += pad; /* padding to a safe 64-bit boundary */ } void custom_primitive_header_print(char *out, int outlen, struct custom_primitive_ptrs *cp_entry, int formatted) { char format[VERYSHORTBUFLEN]; if (out && cp_entry) { memset(out, 0, outlen); if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT || cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) { if (formatted) { snprintf(format, VERYSHORTBUFLEN, "%%-%d", cps_flen[cp_entry->ptr->len] > strlen(cp_entry->ptr->name) ? cps_flen[cp_entry->ptr->len] : (int)strlen(cp_entry->ptr->name)); strncat(format, "s", VERYSHORTBUFLEN - 1); } else snprintf(format, VERYSHORTBUFLEN, "%s", "%s"); } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_STRING || cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { if (formatted) { snprintf(format, VERYSHORTBUFLEN, "%%-%d", cp_entry->ptr->len > strlen(cp_entry->ptr->name) ? cp_entry->ptr->len : (int)strlen(cp_entry->ptr->name)); strncat(format, "s", VERYSHORTBUFLEN - 1); } else snprintf(format, VERYSHORTBUFLEN, "%s", "%s"); } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_IP) { int len = 0; len = INET6_ADDRSTRLEN; if (formatted) { snprintf(format, VERYSHORTBUFLEN, "%%-%d", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name)); strncat(format, "s", VERYSHORTBUFLEN - 1); } else snprintf(format, VERYSHORTBUFLEN, "%s", "%s"); } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) { int len = ETHER_ADDRSTRLEN; if (formatted) { snprintf(format, VERYSHORTBUFLEN, "%%-%d", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name)); strncat(format, "s", VERYSHORTBUFLEN - 1); } else snprintf(format, VERYSHORTBUFLEN, "%s", "%s"); } snprintf(out, outlen, format, cp_entry->ptr->name); } } void custom_primitive_value_print(char *out, int outlen, u_char *in, struct custom_primitive_ptrs *cp_entry, int formatted) { char format[SHORTBUFLEN]; if (in && out && cp_entry) { memset(out, 0, outlen); if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT || cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) { char double_fmt[] = "ll", semantics[VERYSHORTBUFLEN]; if (cp_entry->ptr->len == 8) snprintf(semantics, VERYSHORTBUFLEN, "%s%s", double_fmt, cps_type[cp_entry->ptr->semantics]); else /* XXX: limit to 1, 2 and 4 bytes lengths? */ snprintf(semantics, VERYSHORTBUFLEN, "%s", cps_type[cp_entry->ptr->semantics]); if (formatted) snprintf(format, SHORTBUFLEN, "%%-%d%s", cps_flen[cp_entry->ptr->len] > strlen(cp_entry->ptr->name) ? cps_flen[cp_entry->ptr->len] : (int)strlen(cp_entry->ptr->name), semantics); else snprintf(format, SHORTBUFLEN, "%%%s", semantics); if (cp_entry->ptr->len == 1) { u_int8_t t8; memcpy(&t8, (in+cp_entry->off), 1); snprintf(out, outlen, format, t8); } else if (cp_entry->ptr->len == 2) { u_int16_t t16, st16; memcpy(&t16, (in+cp_entry->off), 2); st16 = ntohs(t16); snprintf(out, outlen, format, st16); } else if (cp_entry->ptr->len == 4) { u_int32_t t32, st32; memcpy(&t32, (in+cp_entry->off), 4); st32 = ntohl(t32); snprintf(out, outlen, format, st32); } else if (cp_entry->ptr->len == 8) { u_int64_t t64, st64; memcpy(&t64, (in+cp_entry->off), 8); st64 = pm_ntohll(t64); snprintf(out, outlen, format, st64); } } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_STRING || cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { if (formatted) snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", cp_entry->ptr->len > strlen(cp_entry->ptr->name) ? cp_entry->ptr->len : (int)strlen(cp_entry->ptr->name), cps_type[cp_entry->ptr->semantics]); else snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]); snprintf(out, outlen, format, (in+cp_entry->off)); } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_IP) { struct host_addr ip_addr; char ip_str[INET6_ADDRSTRLEN]; int len = 0; memset(&ip_addr, 0, sizeof(ip_addr)); memset(ip_str, 0, sizeof(ip_str)); len = INET6_ADDRSTRLEN; if (cp_entry->ptr->len == 4) { ip_addr.family = AF_INET; memcpy(&ip_addr.address.ipv4, in+cp_entry->off, 4); } else if (cp_entry->ptr->len == 16) { ip_addr.family = AF_INET6; memcpy(&ip_addr.address.ipv6, in+cp_entry->off, 16); } addr_to_str(ip_str, &ip_addr); if (formatted) snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name), cps_type[cp_entry->ptr->semantics]); else snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]); snprintf(out, outlen, format, ip_str); } else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) { char eth_str[ETHER_ADDRSTRLEN]; int len = ETHER_ADDRSTRLEN; memset(eth_str, 0, sizeof(eth_str)); etheraddr_string((u_char *)(in + cp_entry->off), eth_str); if (formatted) snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name), cps_type[cp_entry->ptr->semantics]); else snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]); snprintf(out, outlen, format, eth_str); } } } void custom_primitives_debug(void *pcust, void *pvlen) { char empty_string[] = ""; int cp_idx; if (!pcust) return; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { char cph_str[SRVBUFLEN]; custom_primitive_header_print(cph_str, SRVBUFLEN, &config.cpptrs.primitive[cp_idx], TRUE); if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cpv_str[SRVBUFLEN]; custom_primitive_value_print(cpv_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], TRUE); Log(LOG_DEBUG, "DEBUG ( %s/%s ): custom_primitive_value_debug(): PCUST ARRAY: name=%s value=%s\n", config.name, config.type, cph_str, cpv_str); } else { if (pvlen) { /* vlen primitives not supported in formatted outputs: we should never get here */ char *label_ptr = NULL; vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; Log(LOG_DEBUG, "DEBUG ( %s/%s ): custom_primitive_value_debug(): PCUST ARRAY: name=%s value=%s\n", config.name, config.type, cph_str, label_ptr); } } } } int mkdir_multilevel(const char *path, int trailing_filename, uid_t owner, gid_t group) { char opath[SRVBUFLEN]; char *p; int ret = 0, len = 0; strlcpy(opath, path, sizeof(opath)); for (p = opath; *p; p++, len++) { if (*p == '/') { *p = '\0'; if (len && access(opath, F_OK)) { ret = mkdir(opath, (S_IRWXU|S_IRWXG|S_IRWXO)); if (ret) return ret; if (chown(opath, owner, group) == -1) return ret; } *p = '/'; } } /* do a last mkdir in case the path was not terminated by a traiing '/' and we do not expect the last part to be a filename, ie. trailing_filename set to 0 */ if (!trailing_filename && access(opath, F_OK)) { ret = mkdir(opath, (S_IRWXU|S_IRWXG|S_IRWXO)); if (ret) return ret; } return ret; } char bin_to_hex(int nib) { return (nib < 10) ? ('0' + nib) : ('A' - 10 + nib); } int hex_to_bin(int a) { if (a >= '0' && a <= '9') return a - '0'; else if (a >= 'a' && a <= 'f') return a - 'a' + 10; else if (a >= 'A' && a <= 'F') return a - 'A' + 10; return ERR; } int serialize_hex(const u_char *a, u_char *buf, int len) { int b = 0, i = 0; for (; i < len; i++) { u_char byte; byte = a[i]; buf[b++] = bin_to_hex(byte >> 4); buf[b++] = bin_to_hex(byte & 0x0f); // separate the bytes with a dash if (i < (len - 1)) buf[b++] = '-'; } if (buf[b-1] == '-') { buf[b-1] = '\0'; return b; } else { buf[b] = '\0'; return (b+1); } } int serialize_bin(const u_char *hex, u_char *bin, int len) { int i = 0; for (; i < len; i++) { if (hex[0] == '-') { hex++; continue; } *bin++ = hex_to_bin(hex[0]) * 16 + hex_to_bin(hex[1]); hex += 2; } return i; } unsigned char *vlen_prims_copy(struct pkt_vlen_hdr_primitives *src) { unsigned char *dst = NULL; int len = 0; if (!src) return NULL; len = PvhdrSz + src->tot_len; dst = malloc(len); if (dst) { vlen_prims_init((struct pkt_vlen_hdr_primitives *) dst, src->tot_len); memcpy(dst, src, len); } return dst; } void vlen_prims_init(struct pkt_vlen_hdr_primitives *hdr, int add_len) { if (!hdr) return; assert(PvhdrSz); memset(hdr, 0, PvhdrSz + add_len); } void vlen_prims_free(struct pkt_vlen_hdr_primitives *hdr) { if (!hdr) return; free(hdr); } int vlen_prims_cmp(struct pkt_vlen_hdr_primitives *src, struct pkt_vlen_hdr_primitives *dst) { if (!src || !dst) return ERR; if (src->tot_len != dst->tot_len) return (src->tot_len - dst->tot_len); return memcmp(src, dst, (src->tot_len + PvhdrSz)); } int vlen_prims_get(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc, char **res) { pm_label_t *label_ptr; char *ptr = (char *) hdr; int x, rlen; if (res) *res = NULL; if (!hdr || !wtc || !res) return ERR; ptr += PvhdrSz; label_ptr = (pm_label_t *) ptr; for (x = 0, rlen = 0; x < hdr->num && rlen < hdr->tot_len; x++) { if (label_ptr->type == wtc) { if (label_ptr->len) { ptr += PmLabelTSz; *res = ptr; } return label_ptr->len; } else { ptr += (PmLabelTSz + label_ptr->len); rlen += (PmLabelTSz + label_ptr->len); label_ptr = (pm_label_t *) ptr; } } return FALSE; } void vlen_prims_debug(struct pkt_vlen_hdr_primitives *hdr) { pm_label_t *label_ptr; char *ptr = (char *) hdr; int x = 0; Log(LOG_DEBUG, "DEBUG ( %s/%s ): vlen_prims_debug(): VLEN ARRAY: num: %u tot_len: %u\n", config.name, config.type, hdr->num, hdr->tot_len); ptr += PvhdrSz; for (x = 0; x < hdr->num; x++) { label_ptr = (pm_label_t *) ptr; ptr += PmLabelTSz; Log(LOG_DEBUG, "DEBUG ( %s/%s ): vlen_prims_debug(): LABEL #%u: type: %" PRIx64 " len: %u val: %s\n", config.name, config.type, x, label_ptr->type, label_ptr->len, ptr); } } void vlen_prims_insert(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc, int len, u_char *val, int copy_type /*, optional realloc */) { pm_label_t *label_ptr; char *ptr = (char *) hdr; ptr += (PvhdrSz + hdr->tot_len); label_ptr = (pm_label_t *) ptr; label_ptr->type = wtc; label_ptr->len = len; ptr += PmLabelTSz; if (len) { switch (copy_type) { case PM_MSG_BIN_COPY: memcpy(ptr, val, len); break; case PM_MSG_STR_COPY: strncpy(ptr, (char *)val, len); break; case PM_MSG_STR_COPY_ZERO: label_ptr->len++; /* terminating zero */ strncpy(ptr, (char *)val, len); ptr[len] = '\0'; break; default: break; } } hdr->num++; hdr->tot_len += (PmLabelTSz + label_ptr->len); } int vlen_prims_delete(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc /*, optional realloc */) { pm_label_t *label_ptr; char *ptr = (char *) hdr; int x = 0, ret = 0, jump = 0, off = 0; ptr += PvhdrSz; off += PvhdrSz; for (x = 0; x < hdr->num; x++) { label_ptr = (pm_label_t *) ptr; if (label_ptr->type == wtc) { char *new_ptr = ptr; jump = label_ptr->len; new_ptr += (PmLabelTSz + jump); off += (PmLabelTSz + jump); memset(ptr, 0, PmLabelTSz + jump); if (x + 1 < hdr->num) memcpy(ptr, new_ptr, hdr->tot_len - off); hdr->num--; hdr->tot_len -= (PmLabelTSz + jump); /* XXX: optional realloc() */ ret = (PmLabelTSz + jump); break; } else { ptr += (PmLabelTSz + label_ptr->len); off += (PmLabelTSz + label_ptr->len); } } return ret; } int delete_line_from_file(int index, char *path) { int len = strlen(path) + 5; int line_idx; char tmpbuf[LARGEBUFLEN]; char *copy_path; FILE *file = fopen(path, "r+"); FILE *file_copy; copy_path = malloc(len); memset(copy_path, 0, len); strcpy(copy_path, path); strcat(copy_path, ".copy"); file_copy = fopen(copy_path, "w"); if (file == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, path); return -1; } if (file_lock(fileno(file))) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, path); return -1; } line_idx = 0; while (fgets(tmpbuf, LARGEBUFLEN, file)) { if (line_idx != index) fwrite(tmpbuf, 1, strlen(tmpbuf), file_copy); line_idx++; } fclose(file); unlink(path); fclose(file_copy); rename(copy_path, path); file_unlock(fileno(file)); free(copy_path); return 0; } void set_truefalse_nonzero(int *value) { if (!value) return; if (!(*value)) (*value) = TRUE; else if ((*value) == FALSE_NONZERO) (*value) = FALSE; } void hash_init_key(pm_hash_key_t *key) { if (!key) return; memset(key->val, 0, key->len); } int hash_alloc_key(pm_hash_key_t *key, u_int16_t key_len) { if (!key || !key_len) return ERR; if (!key->val) { key->val = malloc(key_len); if (key->val) { key->len = key_len; hash_init_key(key); } else return ERR; } else { key->val = realloc(key->val, key_len); if (key->val) key->len = key_len; else return ERR; } return SUCCESS; } int hash_dup_key(pm_hash_key_t *dst, pm_hash_key_t *src) { if (!src || !dst) return ERR; if (hash_alloc_key(dst, src->len) == ERR) return ERR; memcpy(dst->val, src->val, src->len); return SUCCESS; } void hash_destroy_key(pm_hash_key_t *key) { if (!key) return; free(key->val); memset(key, 0, sizeof(pm_hash_key_t)); } int hash_init_serial(pm_hash_serial_t *serial, u_int16_t key_len) { if (!serial || !key_len) return ERR; memset(serial, 0, sizeof(pm_hash_serial_t)); return hash_alloc_key(&serial->key, key_len); } void hash_destroy_serial(pm_hash_serial_t *serial) { if (!serial) return; hash_destroy_key(&serial->key); memset(serial, 0, sizeof(pm_hash_serial_t)); } void hash_serial_set_off(pm_hash_serial_t *serial, u_int16_t off) { if (!serial) return; serial->off = off; } u_int16_t hash_serial_get_off(pm_hash_serial_t *serial) { if (!serial) return ERR; return serial->off; } pm_hash_key_t *hash_serial_get_key(pm_hash_serial_t *serial) { if (!serial) return NULL; return &serial->key; } u_int16_t hash_key_get_len(pm_hash_key_t *key) { if (!key) return ERR; return key->len; } u_char *hash_key_get_val(pm_hash_key_t *key) { if (!key) return NULL; return key->val; } void hash_serial_append(pm_hash_serial_t *serial, char *val, u_int16_t len, int realloc) { u_int16_t key_len, key_off, rem_len; int ret; if (!serial || !val || !len) return; key_len = hash_key_get_len(&serial->key); key_off = hash_serial_get_off(serial); rem_len = (key_len - key_off); if (len > rem_len) { if (!realloc) return; else { ret = hash_alloc_key(&serial->key, (hash_key_get_len(&serial->key) + (len - rem_len))); if (ret == ERR) return; } } memcpy((hash_key_get_val(&serial->key) + key_off), val, len); hash_serial_set_off(serial, (key_off + len)); } int hash_key_cmp(pm_hash_key_t *a, pm_hash_key_t *b) { if (a->len != b->len) return (a->len - b->len); return memcmp(a->val, b->val, b->len); } void dump_writers_init() { dump_writers.active = 0; dump_writers.max = config.dump_max_writers; if (dump_writers.list) memset(dump_writers.list, 0, (dump_writers.max * sizeof(pid_t))); dump_writers.flags = FALSE; } void dump_writers_count() { u_int16_t idx, count; for (idx = 0, count = 0; idx < dump_writers.max; idx++) { if (dump_writers.list[idx]) { if (kill(dump_writers.list[idx], 0) != -1) count++; else dump_writers.list[idx] = 0; } } dump_writers.active = count; if (dump_writers.active == dump_writers.max) dump_writers.flags = CHLD_ALERT; else dump_writers.flags = FALSE; } u_int32_t dump_writers_get_flags() { return dump_writers.flags; } u_int16_t dump_writers_get_active() { return dump_writers.active; } u_int16_t dump_writers_get_max() { return dump_writers.max; } int dump_writers_add(pid_t pid) { u_int16_t idx; int ret = FALSE; if (dump_writers.flags != CHLD_ALERT) { for (idx = 0; idx < dump_writers.max; idx++) { if (!dump_writers.list[idx]) { dump_writers.list[idx] = pid; break; } } ret = TRUE; } return ret; } int pm_scandir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const void *, const void *)) { DIR *d; struct dirent *entry; size_t entry_sz; int idx = 0; *namelist = NULL; if ((d = opendir(dir)) == NULL) return ERR; while ((entry = readdir(d))) { if (!select || (select && (*select)(entry))) { *namelist = (struct dirent **) realloc((void *)(*namelist), (size_t)((idx + 1) * sizeof(struct dirent *))); if (*namelist == NULL) { closedir(d); return ERR; } entry_sz = sizeof(struct dirent) - sizeof(entry->d_name) + strlen(entry->d_name) + 1; (*namelist)[idx] = (struct dirent *) malloc(entry_sz); if ((*namelist)[idx] == NULL) { closedir(d); return ERR; } memcpy((*namelist)[idx], entry, entry_sz); idx++; } } if (closedir(d)) return ERR; if (idx && (compar != NULL)) qsort((void *)(*namelist), (size_t) idx, sizeof(struct dirent *), compar); return idx; } void pm_scandir_free(struct dirent ***namelist, int num) { int idx; if (*namelist) { for (idx = 0; idx < num; idx++) free((*namelist)[idx]); free((*namelist)); *namelist = NULL; } } int pm_alphasort(const void *a, const void *b) { const struct dirent *dira = a; const struct dirent *dirb = b; return(strcmp(dira->d_name, dirb->d_name)); } void generate_random_string(char *s, const int len) { static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; int i; for (i = 0; i < len; ++i) { s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; } s[len] = '\0'; } void pm_pcap_device_initialize(struct pm_pcap_devices *map) { memset(map, 0, sizeof(struct pm_pcap_devices)); } void open_pcap_savefile(struct pm_pcap_device *dev_ptr, char *file) { char errbuf[PCAP_ERRBUF_SIZE]; int idx; if ((dev_ptr->dev_desc = pcap_open_offline(file, errbuf)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core ): pcap_open_offline(): %s\n", config.name, errbuf); exit_gracefully(1); } dev_ptr->link_type = pcap_datalink(dev_ptr->dev_desc); for (idx = 0; _devices[idx].link_type != -1; idx++) { if (dev_ptr->link_type == _devices[idx].link_type) dev_ptr->data = &_devices[idx]; } if (!dev_ptr->data || !dev_ptr->data->handler) { Log(LOG_ERR, "ERROR ( %s/core ): pcap_savefile: unsupported link layer.\n", config.name); exit_gracefully(1); } dev_ptr->active = TRUE; } void P_broker_timers_set_last_fail(struct p_broker_timers *btimers, time_t timestamp) { if (btimers) btimers->last_fail = timestamp; } time_t P_broker_timers_get_last_fail(struct p_broker_timers *btimers) { if (btimers) return btimers->last_fail; return FALSE; } void P_broker_timers_unset_last_fail(struct p_broker_timers *btimers) { if (btimers) btimers->last_fail = FALSE; } void P_broker_timers_set_retry_interval(struct p_broker_timers *btimers, int interval) { if (btimers) btimers->retry_interval = interval; } int P_broker_timers_get_retry_interval(struct p_broker_timers *btimers) { if (btimers) return btimers->retry_interval; return ERR; } char *ip_proto_print(u_int8_t ip_proto_id, char *str, int len) { char *ret = NULL; if (!config.num_protos && (ip_proto_id < protocols_number)) { ret = (char *) _protocols[ip_proto_id].name; } else { snprintf(str, len, "%u", ip_proto_id); ret = str; } return ret; } void parse_hostport(const char *s, struct sockaddr *addr, socklen_t *len) { char *orig, *host, *port; struct addrinfo hints, *res; int herr; if ((host = orig = strdup(s)) == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), strdup() out of memory\n", config.name, config.type); exit_gracefully(1); } trim_spaces(host); trim_spaces(orig); if ((port = strrchr(host, ':')) == NULL || *(++port) == '\0' || *host == '\0') { Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), invalid '%s' argument\n", config.name, config.type, orig); exit_gracefully(1); } *(port - 1) = '\0'; /* Accept [host]:port for numeric IPv6 addresses */ if (*host == '[' && *(port - 2) == ']') { host++; *(port - 2) = '\0'; } memset(&hints, '\0', sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; if ((herr = getaddrinfo(host, port, &hints, &res)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), address lookup failed\n", config.name, config.type); exit_gracefully(1); } if (res == NULL || res->ai_addr == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), no addresses found for [%s]:%s\n", config.name, config.type, host, port); exit_gracefully(1); } if (res->ai_addrlen > *len) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), address too long.\n", config.name, config.type); exit_gracefully(1); } memcpy(addr, res->ai_addr, res->ai_addrlen); free(orig); *len = res->ai_addrlen; } bool is_prime(u_int32_t num) { int div = 6; if (num == 2 || num == 3) return TRUE; if (num % 2 == 0 || num % 3 == 0) return FALSE; while (div * div - 2 * div + 1 <= num) { if (num % (div - 1) == 0) return FALSE; if (num % (div + 1) == 0) return FALSE; div += 6; } return TRUE; } u_int32_t next_prime(u_int32_t num) { u_int32_t orig = num; while (!is_prime(++num)); if (num < orig) return 0; /* it wrapped */ else return num; } char *null_terminate(char *str, int len) { char *loc = NULL; if (str[len - 1] == '\0') loc = strdup(str); else { loc = malloc(len + 1); memcpy(loc, str, len); loc[len] = '\0'; } return loc; } char *uint_print(void *value, int len, int flip) { char *buf = NULL; ssize_t buflen = 0; switch(len) { case 1: { u_int8_t *u8 = (u_int8_t *) value; buflen = snprintf(NULL, 0, "%u", (*u8)); buf = malloc(buflen + 1); snprintf(buf, (buflen + 1), "%u", (*u8)); } break; case 2: { u_int16_t u16h, *u16 = (u_int16_t *) value; if (flip) u16h = ntohs((*u16)); else u16h = (*u16); buflen = snprintf(NULL, 0, "%u", u16h); buf = malloc(buflen + 1); snprintf(buf, (buflen + 1), "%u", u16h); } break; case 4: { u_int32_t u32h, *u32 = (u_int32_t *) value; if (flip) u32h = ntohl((*u32)); else u32h = (*u32); buflen = snprintf(NULL, 0, "%u", u32h); buf = malloc(buflen + 1); snprintf(buf, (buflen + 1), "%u", u32h); } break; case 8: { u_int64_t u64h, *u64 = (u_int64_t *) value; if (flip) u64h = pm_ntohll((*u64)); else u64h = (*u64); buflen = snprintf(NULL, 0, "%"PRIu64, u64h); buf = malloc(buflen + 1); snprintf(buf, (buflen + 1), "%"PRIu64, u64h); } break; } return buf; } void reload_logs(char *header) { int logf; if (config.syslog) { closelog(); logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; Log(LOG_WARNING, "WARN ( %s/%s ): specified syslog facility is not supported; logging to console.\n", config.name, config.type); } openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/%s ): Start logging ...\n", config.name, config.type); } if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (config.type_id == PLUGIN_ID_CORE) { Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, header, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); } } int is_empty_256b(void *area, int len) { if (len <= SRVBUFLEN) { if (!memcmp(area, empty_mem_area_256b, len)) { return TRUE; } else { return FALSE; } } return ERR; } ssize_t pm_recv(int sockfd, void *buf, size_t len, int flags, unsigned int seconds) { ssize_t ret; if (flags == MSG_WAITALL) { alarm(seconds); } ret = recv(sockfd, buf, len, flags); alarm(0); return ret; } /* flow type to address family */ int ft2af(u_int8_t ft) { if (ft == PM_FTYPE_IPV4 || ft == PM_FTYPE_VLAN_IPV4 || ft == PM_FTYPE_MPLS_IPV4 || ft == PM_FTYPE_VLAN_MPLS_IPV4) { return AF_INET; } else if (ft == PM_FTYPE_IPV6 || ft == PM_FTYPE_VLAN_IPV6 || ft == PM_FTYPE_MPLS_IPV6 || ft == PM_FTYPE_VLAN_MPLS_IPV6) { return AF_INET6; } return ERR; } void distribute_work(struct pm_dump_runner *pdr, u_int64_t seqno, int workers, u_int64_t last_elem) { int id, idx; if (!pdr) return; memset(pdr, 0, (workers * sizeof(struct pm_dump_runner))); for (idx = 0, id = 1; idx < workers; idx++, id++) { struct pm_dump_runner *worker = &pdr[idx]; worker->id = id; worker->seq = seqno; worker->noop = FALSE; if (workers <= last_elem) { int ratio = last_elem / workers; if (idx < (workers - 1)) { worker->first = idx * ratio; worker->last = (((idx * ratio) + ratio) - 1); } else { worker->first = idx * ratio; worker->last = (last_elem - 1); } } else { if (idx < last_elem) { worker->first = idx; worker->last = idx; } else { worker->noop = TRUE; worker->first = FALSE; worker->last = FALSE; } } } } // Dan Bernstein's hash variant 2 (XOR) unsigned long pm_djb2_string_hash(unsigned char *str) { unsigned long hash = 5381; while (*str){ hash = hash * 33 ^ ((int) *str); str++; } return hash; } char *lookup_id_to_string_struct(const struct _id_to_string_struct *table, u_int64_t value) { int index; for (index = 0; table[index].id; index++) { if (table[index].id == value) { return (char * const) table[index].str; } } return NULL; } const char *sampling_direction_print(u_int8_t sd_id) { if (sd_id <= SAMPLING_DIRECTION_MAX) return sampling_direction[sd_id]; else return sampling_direction[SAMPLING_DIRECTION_UNKNOWN]; } u_int8_t sampling_direction_str2id(char *sd_str) { if (!strcmp(sd_str, "u")) return SAMPLING_DIRECTION_UNKNOWN; else if (!strcmp(sd_str, "i")) return SAMPLING_DIRECTION_INGRESS; else if (!strcmp(sd_str, "e")) return SAMPLING_DIRECTION_EGRESS; return SAMPLING_DIRECTION_UNKNOWN; } pmacct-1.7.8/src/amqp_plugin.c0000644000175000017500000007345014354105275015272 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "amqp_common.h" #include "plugin_cmn_json.h" #include "plugin_cmn_avro.h" #include "amqp_plugin.h" #ifndef WITH_JANSSON #error "--enable-rabbitmq requires --enable-jansson" #endif #include "net_aggr.h" /* Functions */ void amqp_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data; struct ports_table pt; struct protos_table prt, tost; unsigned char *pipebuf; struct pollfd pfd; struct insert_data idata; time_t avro_schema_deadline = 0; int timeout, refresh_timeout, avro_schema_timeout = 0; int ret, num, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; pid_t core_pid = ((struct channels_list_entry *)ptr)->core_pid; struct networks_file_data nfd; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; unsigned char *dataptr; #ifdef WITH_AVRO char *avro_acct_data_schema_str = NULL; char *p_avro_acct_init_schema_str = NULL; char *p_avro_acct_close_schema_str = NULL; #endif #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "RabbitMQ/AMQP Plugin", config.name); P_set_signals(); P_init_default_values(); P_config_checks(); pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); timeout = config.sql_refresh_time*1000; if (!config.sql_user) config.sql_user = rabbitmq_user; if (!config.sql_passwd) config.sql_passwd = rabbitmq_pwd; if (!config.message_broker_output) config.message_broker_output = PRINT_OUTPUT_JSON; if (config.message_broker_output & PRINT_OUTPUT_JSON) { compose_json(config.what_to_count, config.what_to_count_2); } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO p_avro_acct_schema = p_avro_schema_build_acct_data(config.what_to_count, config.what_to_count_2); p_avro_schema_add_writer_id(p_avro_acct_schema); p_avro_acct_init_schema = p_avro_schema_build_acct_init(); p_avro_acct_close_schema = p_avro_schema_build_acct_close(); if (config.avro_schema_file) { char avro_schema_file[SRVBUFLEN]; if (strlen(config.avro_schema_file) > (SRVBUFLEN - SUPERSHORTBUFLEN)) { Log(LOG_ERR, "ERROR ( %s/%s ): 'avro_schema_file' too long. Exiting.\n", config.name, config.type); exit_gracefully(1); } write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_data", avro_schema_file, p_avro_acct_schema); write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_init", avro_schema_file, p_avro_acct_init_schema); write_avro_schema_to_file_with_suffix(config.avro_schema_file, "-acct_close", avro_schema_file, p_avro_acct_close_schema); } if (config.amqp_avro_schema_routing_key) { if (!config.amqp_avro_schema_refresh_time) { config.amqp_avro_schema_refresh_time = DEFAULT_AVRO_SCHEMA_REFRESH_TIME; } avro_schema_deadline = time(NULL); P_init_refresh_deadline(&avro_schema_deadline, config.amqp_avro_schema_refresh_time, 0, "m"); avro_acct_data_schema_str = compose_avro_purge_schema(p_avro_acct_schema, config.name); p_avro_acct_init_schema_str = compose_avro_purge_schema(p_avro_acct_init_schema, config.name); p_avro_acct_close_schema_str = compose_avro_purge_schema(p_avro_acct_close_schema, config.name); } else { config.amqp_avro_schema_refresh_time = 0; avro_schema_deadline = 0; avro_schema_timeout = 0; avro_acct_data_schema_str = NULL; p_avro_acct_init_schema_str = NULL; p_avro_acct_close_schema_str = NULL; } #endif } if ((config.sql_table && strchr(config.sql_table, '$')) && config.sql_multi_values) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'amqp_routing_key' is not compatible with 'amqp_multi_values'. Exiting.\n", config.name, config.type); exit_gracefully(1); } if ((config.sql_table && strchr(config.sql_table, '$')) && config.amqp_routing_key_rr) { Log(LOG_ERR, "ERROR ( %s/%s ): dynamic 'amqp_routing_key' is not compatible with 'amqp_routing_key_rr'. Exiting.\n", config.name, config.type); exit_gracefully(1); } p_amqp_init_host(&amqpp_amqp_host); p_amqp_set_user(&amqpp_amqp_host, config.sql_user); p_amqp_set_passwd(&amqpp_amqp_host, config.sql_passwd); /* setting function pointers */ if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET)) insert_func = P_sum_host_insert; else if (config.what_to_count & COUNT_SUM_PORT) insert_func = P_sum_port_insert; else if (config.what_to_count & COUNT_SUM_AS) insert_func = P_sum_as_insert; #if defined (HAVE_L2) else if (config.what_to_count & COUNT_SUM_MAC) insert_func = P_sum_mac_insert; #endif else insert_func = P_cache_insert; purge_func = amqp_cache_purge; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); memset(&idata, 0, sizeof(idata)); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); set_primptrs_funcs(&extras); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); idata.now = time(NULL); /* print_refresh time init: deadline */ refresh_deadline = idata.now; P_init_refresh_deadline(&refresh_deadline, config.sql_refresh_time, config.sql_startup_delay, config.sql_history_roundoff); if (config.sql_history) { basetime_init = P_init_historical_acct; basetime_eval = P_eval_historical_acct; basetime_cmp = P_cmp_historical_acct; (*basetime_init)(idata.now); } /* setting number of entries in _protocols structure */ while (_protocols[protocols_number].number != -1) protocols_number++; #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for(;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; calc_refresh_timeout(refresh_deadline, idata.now, &refresh_timeout); if (config.amqp_avro_schema_routing_key) calc_refresh_timeout(avro_schema_deadline, idata.now, &avro_schema_timeout); pfd.fd = pipe_fd; pfd.events = POLLIN; timeout = MIN(refresh_timeout, (avro_schema_timeout ? avro_schema_timeout : INT_MAX)); ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), timeout); if (ret <= 0) { if (getppid() != core_pid) { Log(LOG_ERR, "ERROR ( %s/%s ): Core process *seems* gone. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (ret < 0) goto poll_again; } poll_ops: P_update_time_reference(&idata); if (idata.now > refresh_deadline) P_cache_handle_flush_event(&pt, &prt, &tost); #ifdef WITH_AVRO if (idata.now > avro_schema_deadline) { amqp_avro_schema_purge(avro_acct_data_schema_str); amqp_avro_schema_purge(p_avro_acct_init_schema_str); amqp_avro_schema_purge(p_avro_acct_close_schema_str); avro_schema_deadline += config.amqp_avro_schema_refresh_time; } #endif recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; (*insert_func)(&prim_ptrs, &idata); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } } } void amqp_cache_purge(struct chained_cache *queue[], int index, int safe_action) { struct pkt_primitives *data = NULL; struct pkt_bgp_primitives *pbgp = NULL; struct pkt_nat_primitives *pnat = NULL; struct pkt_mpls_primitives *pmpls = NULL; struct pkt_tunnel_primitives *ptun = NULL; u_char *pcust = NULL; struct pkt_vlen_hdr_primitives *pvlen = NULL; struct pkt_bgp_primitives empty_pbgp; struct pkt_nat_primitives empty_pnat; struct pkt_mpls_primitives empty_pmpls; struct pkt_tunnel_primitives empty_ptun; u_char *empty_pcust = NULL; char dyn_amqp_routing_key[SRVBUFLEN], *orig_amqp_routing_key = NULL; int j, stop, is_routing_key_dyn = FALSE, qn = 0, ret, saved_index = index; int mv_num = 0, mv_num_save = 0; time_t start, duration; struct primitives_ptrs prim_ptrs; struct pkt_data dummy_data; pid_t writer_pid = getpid(); struct dynname_tokens writer_id_tokens; char *json_buf = NULL; int json_buf_off = 0; //TODO sort out unused variables correctly (void)pvlen; (void)pcust; (void)ptun; (void)pmpls; (void)pnat; (void)pbgp; (void)data; #ifdef WITH_AVRO avro_writer_t p_avro_writer = {0}; char *p_avro_buf = NULL; int p_avro_buffer_full = FALSE; size_t p_avro_len; #endif /* setting some defaults */ if (!config.sql_host) config.sql_host = default_amqp_host; if (!config.sql_db) config.sql_db = default_amqp_exchange; if (!config.amqp_exchange_type) config.amqp_exchange_type = default_amqp_exchange_type; if (!config.amqp_vhost) config.amqp_vhost = default_amqp_vhost; if (!config.sql_table) config.sql_table = default_amqp_routing_key; else { if (strchr(config.sql_table, '$')) { is_routing_key_dyn = TRUE; orig_amqp_routing_key = config.sql_table; config.sql_table = dyn_amqp_routing_key; } } if (config.amqp_routing_key_rr) { orig_amqp_routing_key = config.sql_table; config.sql_table = dyn_amqp_routing_key; } p_amqp_set_exchange(&amqpp_amqp_host, config.sql_db); p_amqp_set_routing_key(&amqpp_amqp_host, config.sql_table); p_amqp_set_exchange_type(&amqpp_amqp_host, config.amqp_exchange_type); p_amqp_set_host(&amqpp_amqp_host, config.sql_host); p_amqp_set_vhost(&amqpp_amqp_host, config.amqp_vhost); p_amqp_set_persistent_msg(&amqpp_amqp_host, config.amqp_persistent_msg); p_amqp_set_frame_max(&amqpp_amqp_host, config.amqp_frame_max); if (config.message_broker_output & PRINT_OUTPUT_JSON) p_amqp_set_content_type_json(&amqpp_amqp_host); else if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) p_amqp_set_content_type_binary(&amqpp_amqp_host); else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) p_amqp_set_content_type_json(&amqpp_amqp_host); else { Log(LOG_ERR, "ERROR ( %s/%s ): Unsupported amqp_output value specified. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (!config.writer_id_string) { config.writer_id_string = DYNNAME_DEFAULT_WRITER_ID; } dynname_tokens_prepare(config.writer_id_string, &writer_id_tokens, DYN_STR_WRITER_ID); p_amqp_init_routing_key_rr(&amqpp_amqp_host); p_amqp_set_routing_key_rr(&amqpp_amqp_host, config.amqp_routing_key_rr); empty_pcust = malloc(config.cpptrs.len); if (!empty_pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() empty_pcust. Exiting.\n", config.name, config.type); exit_gracefully(1); } memset(&empty_pbgp, 0, sizeof(struct pkt_bgp_primitives)); memset(&empty_pnat, 0, sizeof(struct pkt_nat_primitives)); memset(&empty_pmpls, 0, sizeof(struct pkt_mpls_primitives)); memset(&empty_ptun, 0, sizeof(struct pkt_tunnel_primitives)); memset(empty_pcust, 0, config.cpptrs.len); ret = p_amqp_connect_to_publish(&amqpp_amqp_host); if (ret) return; for (j = 0, stop = 0; (!stop) && P_preprocess_funcs[j]; j++) stop = P_preprocess_funcs[j](queue, &index, j); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - START (PID: %u) ***\n", config.name, config.type, writer_pid); start = time(NULL); if (config.message_broker_output & PRINT_OUTPUT_JSON) { if (config.sql_multi_values) { json_buf = malloc(config.sql_multi_values); if (!json_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (json_buf). Exiting ..\n", config.name, config.type); exit_gracefully(1); } else memset(json_buf, 0, config.sql_multi_values); } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (!config.avro_buffer_size) config.avro_buffer_size = LARGEBUFLEN; p_avro_buf = malloc(config.avro_buffer_size); if (!p_avro_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (p_avro_buf). Exiting ..\n", config.name, config.type); exit_gracefully(1); } else { memset(p_avro_buf, 0, config.avro_buffer_size); } if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { p_avro_writer = avro_writer_memory(p_avro_buf, config.avro_buffer_size); } #endif } if (config.print_markers) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { void *json_obj = NULL; char *json_str = NULL; json_obj = compose_purge_init_json(config.name, writer_pid); if (json_obj) json_str = compose_json_str(json_obj); if (json_str) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_amqp_publish_string(&amqpp_amqp_host, json_str); free(json_str); json_str = NULL; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_init_schema); avro_value_t p_avro_value = compose_avro_acct_init(config.name, writer_pid, p_avro_iface); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { p_avro_len = avro_writer_tell(p_avro_writer); ret = p_amqp_publish_binary(&amqpp_amqp_host, p_avro_buf, p_avro_len); avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { ret = p_amqp_publish_string(&amqpp_amqp_host, p_avro_local_buf); free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #endif } } for (j = 0; j < index; j++) { char *json_str = NULL; if (queue[j]->valid != PRINT_CACHE_COMMITTED) continue; data = &queue[j]->primitives; if (queue[j]->pbgp) pbgp = queue[j]->pbgp; else pbgp = &empty_pbgp; if (queue[j]->pnat) pnat = queue[j]->pnat; else pnat = &empty_pnat; if (queue[j]->pmpls) pmpls = queue[j]->pmpls; else pmpls = &empty_pmpls; if (queue[j]->ptun) ptun = queue[j]->ptun; else ptun = &empty_ptun; if (queue[j]->pcust) pcust = queue[j]->pcust; else pcust = empty_pcust; if (queue[j]->pvlen) pvlen = queue[j]->pvlen; else pvlen = NULL; if (queue[j]->valid == PRINT_CACHE_FREE) continue; if (config.message_broker_output & PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON json_t *json_obj = json_object(); int idx; for (idx = 0; idx < N_PRIMITIVES && cjhandler[idx]; idx++) cjhandler[idx](json_obj, queue[j]); add_writer_name_and_pid_json(json_obj, &writer_id_tokens); json_str = compose_json_str(json_obj); #endif } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_schema); avro_value_t p_avro_value = compose_avro_acct_data(config.what_to_count, config.what_to_count_2, queue[j]->flow_type, &queue[j]->primitives, pbgp, pnat, pmpls, ptun, pcust, pvlen, queue[j]->bytes_counter, queue[j]->packet_counter, queue[j]->flow_counter, queue[j]->tcp_flags, queue[j]->tunnel_tcp_flags, &queue[j]->basetime, queue[j]->stitch, p_avro_iface); add_writer_name_and_pid_avro_v2(p_avro_value, &writer_id_tokens); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { size_t p_avro_value_size; avro_value_sizeof(&p_avro_value, &p_avro_value_size); if (p_avro_value_size > config.avro_buffer_size) { Log(LOG_ERR, "ERROR ( %s/%s ): amqp_cache_purge(): avro_buffer_size too small (%u)\n", config.name, config.type, config.avro_buffer_size); exit_gracefully(1); } else if (p_avro_value_size >= (config.avro_buffer_size - avro_writer_tell(p_avro_writer))) { p_avro_buffer_full = TRUE; j--; } else if (avro_value_write(p_avro_writer, &p_avro_value)) { Log(LOG_ERR, "ERROR ( %s/%s ): ARVO: unable to write value: %s\n", config.name, config.type, avro_strerror()); exit_gracefully(1); } else { mv_num++; } } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { size_t p_avro_local_buf_len = strlen(p_avro_local_buf); if (p_avro_local_buf_len > config.avro_buffer_size) { Log(LOG_ERR, "ERROR ( %s/%s ): amqp_cache_purge(): avro_buffer_size too small (%u)\n", config.name, config.type, config.avro_buffer_size); exit_gracefully(1); } else if (p_avro_local_buf_len >= (config.avro_buffer_size - strlen(p_avro_buf))) { p_avro_buffer_full = TRUE; j--; } else { strcat(p_avro_buf, p_avro_local_buf); mv_num++; } free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #else if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_avro_acct_data(): AVRO object not created due to missing --enable-avro\n", config.name, config.type); #endif } if (config.message_broker_output & PRINT_OUTPUT_JSON) { char *tmp_str = NULL; if (json_str && config.sql_multi_values) { int json_strlen = (strlen(json_str) ? (strlen(json_str) + 1) : 0); if (json_strlen >= (config.sql_multi_values - json_buf_off)) { if (json_strlen >= config.sql_multi_values) { Log(LOG_ERR, "ERROR ( %s/%s ): amqp_multi_values not large enough to store JSON elements. Exiting ..\n", config.name, config.type); exit_gracefully(1); } tmp_str = json_str; json_str = json_buf; } else { strcat(json_buf, json_str); mv_num++; string_add_newline(json_buf); json_buf_off = strlen(json_buf); free(json_str); json_str = NULL; } } if (json_str) { if (is_routing_key_dyn) { prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &prim_ptrs, DYN_STR_RABBITMQ_RK); p_amqp_set_routing_key(&amqpp_amqp_host, dyn_amqp_routing_key); } if (config.amqp_routing_key_rr) { P_handle_table_dyn_rr(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &amqpp_amqp_host.rk_rr); p_amqp_set_routing_key(&amqpp_amqp_host, dyn_amqp_routing_key); } Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_amqp_publish_string(&amqpp_amqp_host, json_str); if (config.sql_multi_values) { json_str = tmp_str; strcpy(json_buf, json_str); mv_num_save = mv_num; mv_num = 1; string_add_newline(json_buf); json_buf_off = strlen(json_buf); } free(json_str); json_str = NULL; if (!ret) { if (!config.sql_multi_values) qn++; else qn += mv_num_save; } else break; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (!config.sql_multi_values || (mv_num >= config.sql_multi_values) || p_avro_buffer_full) { if (is_routing_key_dyn) { prim_ptrs.data = &dummy_data; primptrs_set_all_from_chained_cache(&prim_ptrs, queue[j]); handle_dynname_internal_strings(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &prim_ptrs, DYN_STR_RABBITMQ_RK); p_amqp_set_routing_key(&amqpp_amqp_host, dyn_amqp_routing_key); } if (config.amqp_routing_key_rr) { P_handle_table_dyn_rr(dyn_amqp_routing_key, SRVBUFLEN, orig_amqp_routing_key, &amqpp_amqp_host.rk_rr); p_amqp_set_routing_key(&amqpp_amqp_host, dyn_amqp_routing_key); } if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { ret = p_amqp_publish_binary(&amqpp_amqp_host, p_avro_buf, avro_writer_tell(p_avro_writer)); avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { ret = p_amqp_publish_string(&amqpp_amqp_host, p_avro_buf); memset(p_avro_buf, 0, config.avro_buffer_size); } p_avro_buffer_full = FALSE; mv_num_save = mv_num; mv_num = 0; if (!ret) qn += mv_num_save; else break; } #endif } } if (config.sql_multi_values) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { if (json_buf && json_buf_off) { /* no handling of dyn routing keys here: not compatible */ Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_buf); ret = p_amqp_publish_string(&amqpp_amqp_host, json_buf); if (!ret) qn += mv_num; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { if (avro_writer_tell(p_avro_writer)) { ret = p_amqp_publish_binary(&amqpp_amqp_host, p_avro_buf, avro_writer_tell(p_avro_writer)); avro_writer_free(p_avro_writer); if (!ret) qn += mv_num; } } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { if (strlen(p_avro_buf)) { ret = p_amqp_publish_string(&amqpp_amqp_host, p_avro_buf); if (!ret) qn += mv_num; } } #endif } } duration = time(NULL)-start; if (config.print_markers) { if (config.message_broker_output & PRINT_OUTPUT_JSON) { void *json_obj = NULL; char *json_str = NULL; json_obj = compose_purge_close_json(config.name, writer_pid, qn, saved_index, duration); if (json_obj) json_str = compose_json_str(json_obj); if (json_str) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n\n", config.name, config.type, json_str); ret = p_amqp_publish_string(&amqpp_amqp_host, json_str); free(json_str); json_str = NULL; } } else if ((config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) || (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON)) { #ifdef WITH_AVRO avro_value_iface_t *p_avro_iface = avro_generic_class_from_schema(p_avro_acct_close_schema); avro_value_t p_avro_value = compose_avro_acct_close(config.name, writer_pid, qn, saved_index, duration, p_avro_iface); if (config.message_broker_output & PRINT_OUTPUT_AVRO_BIN) { p_avro_len = avro_writer_tell(p_avro_writer); ret = p_amqp_publish_binary(&amqpp_amqp_host, p_avro_buf, p_avro_len); avro_writer_reset(p_avro_writer); } else if (config.message_broker_output & PRINT_OUTPUT_AVRO_JSON) { char *p_avro_local_buf = write_avro_json_record_to_buf(p_avro_value); if (p_avro_local_buf) { ret = p_amqp_publish_string(&amqpp_amqp_host, p_avro_local_buf); free(p_avro_local_buf); } } avro_value_decref(&p_avro_value); avro_value_iface_decref(p_avro_iface); #endif } } p_amqp_close(&amqpp_amqp_host, FALSE); Log(LOG_INFO, "INFO ( %s/%s ): *** Purging cache - END (PID: %u, QN: %u/%u, ET: %lu) ***\n", config.name, config.type, writer_pid, qn, saved_index, duration); if (config.sql_trigger_exec && !safe_action) P_trigger_exec(config.sql_trigger_exec); if (empty_pcust) free(empty_pcust); if (json_buf) free(json_buf); #ifdef WITH_AVRO if (p_avro_buf) free(p_avro_buf); #endif } #ifdef WITH_AVRO void amqp_avro_schema_purge(char *p_avro_schema_str) { struct p_amqp_host amqp_avro_schema_host; int ret; if (!p_avro_schema_str || !config.amqp_avro_schema_routing_key) return; /* setting some defaults */ if (!config.sql_host) config.sql_host = default_amqp_host; if (!config.sql_db) config.sql_db = default_amqp_exchange; if (!config.amqp_exchange_type) config.amqp_exchange_type = default_amqp_exchange_type; if (!config.amqp_vhost) config.amqp_vhost = default_amqp_vhost; p_amqp_init_host(&amqp_avro_schema_host); p_amqp_set_user(&amqp_avro_schema_host, config.sql_user); p_amqp_set_passwd(&amqp_avro_schema_host, config.sql_passwd); p_amqp_set_exchange(&amqp_avro_schema_host, config.sql_db); p_amqp_set_routing_key(&amqp_avro_schema_host, config.amqp_avro_schema_routing_key); p_amqp_set_exchange_type(&amqp_avro_schema_host, config.amqp_exchange_type); p_amqp_set_host(&amqp_avro_schema_host, config.sql_host); p_amqp_set_vhost(&amqp_avro_schema_host, config.amqp_vhost); p_amqp_set_persistent_msg(&amqp_avro_schema_host, config.amqp_persistent_msg); p_amqp_set_frame_max(&amqp_avro_schema_host, config.amqp_frame_max); p_amqp_set_content_type_json(&amqp_avro_schema_host); ret = p_amqp_connect_to_publish(&amqp_avro_schema_host); if (ret) return; ret = p_amqp_publish_string(&amqp_avro_schema_host, p_avro_schema_str); p_amqp_close(&amqp_avro_schema_host, FALSE); } #endif pmacct-1.7.8/src/pmacct.h0000644000175000017500000003051514354105275014225 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PMACCT_H_ #define _PMACCT_H_ /* includes */ #ifdef HAVE_PCAP_PCAP_H #include #endif #ifdef HAVE_PCAP_H #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_GETOPT_H #include #endif #if defined HAVE_MALLOPT #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pmsearch.h" #include "linklist.h" #include "filters/bloom.h" #include #include #if !defined (MAP_ANONYMOUS) #if defined (MAP_ANON) #define MAP_ANONYMOUS MAP_ANON #else #define MAP_ANONYMOUS 0 #define USE_DEVZERO 1 #endif #endif #include "pmacct-version.h" #include "pmacct-build.h" #include "pmacct-defines.h" #if defined (WITH_GEOIP) #include #if defined (WITH_GEOIPV2) #error "--enable-geoip and --enable-geoipv2 are mutually exclusive" #endif #endif #if defined (WITH_GEOIPV2) #include #endif #if defined (WITH_NDPI) #include #endif #if !defined ETHER_ADDRSTRLEN #define ETHER_ADDRSTRLEN 18 #endif #if !defined INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif #if !defined INET6_ADDRSTRLEN #define INET6_ADDRSTRLEN 46 #endif #if defined IM_BIG_ENDIAN #define ntohs(x) (x) #define ntohl(x) (x) #define htons(x) (x) #define htonl(x) (x) #endif #if (!defined HAVE_U_INT8_T) && (defined HAVE_UINT8_T) #define u_int8_t uint8_t #endif #if (!defined HAVE_U_INT16_T) && (defined HAVE_UINT16_T) #define u_int16_t uint16_t #endif #if (!defined HAVE_U_INT32_T) && (defined HAVE_UINT32_T) #define u_int32_t uint32_t #endif #if (!defined HAVE_U_INT64_T) && (defined HAVE_UINT64_T) #define u_int64_t uint64_t #endif #define MOREBUFSZ 32 #ifndef LOCK_UN #define LOCK_UN 8 #endif #ifndef LOCK_EX #define LOCK_EX 2 #endif /* Let work the unaligned copy macros the hard way: byte-per byte copy via u_char pointers. We discard the packed attribute way because it fits just to GNU compiler */ #if !defined NEED_ALIGN #define Assign8(a, b) a = b #else #define Assign8(a, b) \ { \ u_char *ptr = (u_char *)&a; \ *ptr = b; \ } #endif #if !defined NEED_ALIGN #define Assign16(a, b) a = b #else #define Assign16(a, b) \ { \ u_int16_t c = b; \ u_char *dst = (u_char *)&a; \ u_char *src = (u_char *)&c; \ *(dst + 0) = *(src + 0); \ *(dst + 1) = *(src + 1); \ } #endif #if !defined NEED_ALIGN #define Assign32(a, b) a = b #else #define Assign32(a, b) \ { \ u_int32_t c = b; \ u_char *dst = (u_char *)&a; \ u_char *src = (u_char *)&c; \ *(dst + 0) = *(src + 0); \ *(dst + 1) = *(src + 1); \ *(dst + 2) = *(src + 2); \ *(dst + 3) = *(src + 3); \ } #endif /* structure to pass requests: probably plugin_requests name outdated at this point .. */ struct ptm_complex { int load_ptm_plugin; /* load_pre_tag_map(): input plugin type ID */ int load_ptm_res; /* load_pre_tag_map(): result */ int exec_ptm_dissect; /* exec_plugins(): TRUE if at least one plugin returned load_ptm_res == TRUE */ int exec_ptm_res; /* exec_plugins(): input to be matched against list->cfg.ptm_complex */ }; struct plugin_requests { u_int8_t bpf_filter; /* On-request packet copy for BPF purposes */ /* load_id_file() stuff */ void *key_value_table; /* table to be filled in from key-value files */ int line_num; /* line number being processed */ int map_entries; /* number of map entries: wins over global setting */ int map_row_len; /* map row length: wins over global setting */ struct ptm_complex ptm_c; /* flags a map that requires parsing of the records (ie. tee plugin) */ }; typedef struct { u_char *val; u_int16_t len; } pm_hash_key_t; typedef struct { pm_hash_key_t key; u_int16_t off; } pm_hash_serial_t; #if (defined WITH_JANSSON) #include #endif #if (defined WITH_AVRO) #include #endif #if (defined WITH_AVRO) #if (!defined WITH_JANSSON) #error "--enable-avro requires --enable-jansson" #endif #endif #if (defined WITH_SERDES) #if (!defined WITH_AVRO) #error "--enable-serdes requires --enable-avro" #endif #endif #ifdef WITH_REDIS #include "redis_common.h" #endif #ifdef WITH_GNUTLS #include #include #define PM_GNUTLS_KEYFILE "key.pem" #define PM_GNUTLS_CERTFILE "cert.pem" #define PM_GNUTLS_CAFILE "ca-certificates.crt" #endif #include "addr.h" #include "network.h" #include "pretag.h" #include "cfg.h" #include "xflow_status.h" #include "log.h" #include "once.h" #include "mpls.h" /* * htonvl(): host to network (byte ordering) variable length * ntohvl(): network to host (byer ordering) variable length */ #define htonvl(x) pm_htonll(x) #define ntohvl(x) pm_ntohll(x) #define CACHE_THRESHOLD UINT64T_THRESHOLD /* structures */ struct pm_pcap_interface { u_int32_t ifindex; char ifname[IFNAMSIZ]; int direction; }; struct pm_pcap_interfaces { struct pm_pcap_interface *list; int num; }; struct pm_pcap_device { char str[IFNAMSIZ]; u_int32_t id; pcap_t *dev_desc; int link_type; int active; int errors; /* error count when reading from a savefile */ int fd; struct _devices_struct *data; struct pm_pcap_interface *pcap_if; }; struct pm_pcap_devices { struct pm_pcap_device list[PCAP_MAX_INTERFACES]; int num; }; struct pm_pcap_callback_signals { int is_set; sigset_t set; }; struct pm_pcap_callback_data { u_char * f_agent; u_char * bta_table; u_char * bpas_table; u_char * blp_table; u_char * bmed_table; u_char * biss_table; struct pm_pcap_device *device; u_int32_t ifindex_in; u_int32_t ifindex_out; u_int8_t has_tun_prims; struct pm_pcap_callback_signals sig; }; struct pm_dump_runner { u_int16_t id; u_int64_t seq; u_int64_t first; u_int64_t last; int noop; void *extra; /* extra data to pass to the runner thread */ }; struct _protocols_struct { char name[PROTO_LEN]; int number; }; struct _devices_struct { void (*handler)(const struct pcap_pkthdr *, register struct packet_ptrs *); int link_type; }; struct _primitives_matrix_struct { char name[PRIMITIVE_LEN]; u_int8_t pmacctd; u_int8_t uacctd; u_int8_t nfacctd; u_int8_t sfacctd; u_int8_t pmtelemetryd; u_int8_t pmbgpd; u_int8_t pmbmpd; char desc[PRIMITIVE_DESC_LEN]; }; struct _id_to_string_struct { u_int64_t id; char str[PRIMITIVE_DESC_LEN]; }; struct largebuf { u_char base[LARGEBUFLEN]; u_char *end; u_char *ptr; }; struct largebuf_s { char base[LARGEBUFLEN]; char *end; char *ptr; }; struct child_ctl2 { pid_t *list; u_int16_t active; u_int16_t max; u_int32_t flags; }; #define INIT_BUF(x) \ memset(x.base, 0, sizeof(x.base)); \ x.end = x.base+sizeof(x.base); \ x.ptr = x.base; #include "util.h" /* prototypes */ void startup_handle_falling_child(); void handle_falling_child(); void ignore_falling_child(); void PM_sigint_handler(int); void PM_sigalrm_noop_handler(int); void reload(int); void push_stats(int); void reload_maps(int); extern void pm_pcap_device_initialize(struct pm_pcap_devices *); extern void pm_pcap_device_copy_all(struct pm_pcap_devices *, struct pm_pcap_devices *); extern void pm_pcap_device_copy_entry(struct pm_pcap_devices *, struct pm_pcap_devices *, int); extern int pm_pcap_device_getindex_by_ifname_direction(struct pm_pcap_devices *, char *, int); extern pcap_t *pm_pcap_open(const char *, int, int, int, int, int, char *); extern void pm_pcap_add_filter(struct pm_pcap_device *); extern int pm_pcap_add_interface(struct pm_pcap_device *, char *, struct pm_pcap_interface *, int); extern void pm_pcap_check(struct pm_pcap_device *); extern void null_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void eth_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void fddi_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void tr_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern u_int16_t mpls_handler(u_char *, u_int16_t *, u_int16_t *, register struct packet_ptrs *); extern void ppp_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void ieee_802_11_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void sll_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern void raw_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern u_char *llc_handler(const struct pcap_pkthdr *, u_int, register u_char *, register struct packet_ptrs *); extern void chdlc_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); extern int ip_handler(register struct packet_ptrs *); extern int ip6_handler(register struct packet_ptrs *); extern int unknown_etype_handler(register struct packet_ptrs *); extern int gtp_tunnel_func(register struct packet_ptrs *); extern int gtp_tunnel_configurator(struct tunnel_handler *, char *); extern void tunnel_registry_init(); extern void pm_pcap_cb(u_char *, const struct pcap_pkthdr *, const u_char *); extern int PM_find_id(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); extern void PM_print_stats(time_t); extern void compute_once(); extern void reset_index_pkt_ptrs(struct packet_ptrs *); extern void set_index_pkt_ptrs(struct packet_ptrs *); extern void PM_evaluate_flow_type(struct packet_ptrs *); extern ssize_t recvfrom_savefile(struct pm_pcap_device *, void **, struct sockaddr *, struct timeval **, int *, struct packet_ptrs *); extern ssize_t recvfrom_rawip(unsigned char *, size_t, struct sockaddr *, struct packet_ptrs *); #ifndef HAVE_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif void #ifdef __STDC__ pm_setproctitle(const char *fmt, ...); #else /* __STDC__ */ #error pm_setproctitle(fmt, va_alist); #endif /* __STDC__ */ void initsetproctitle(int, char**, char**); /* global variables */ extern char sll_mac[2][ETH_ADDR_LEN]; extern struct host_addr mcast_groups[MAX_MCAST_GROUPS]; extern int reload_map, reload_map_exec_plugins, reload_geoipv2_file; extern int reload_map_bgp_thread, reload_log, reload_log_bgp_thread; extern int reload_map_bmp_thread, reload_log_bmp_thread; extern int reload_map_rpki_thread, reload_log_rpki_thread; extern int reload_map_telemetry_thread, reload_log_telemetry_thread; extern int reload_map_pmacctd; extern int print_stats; extern int reload_log_sf_cnt; extern int data_plugins, tee_plugins; extern int collector_port; extern struct timeval reload_map_tstamp; extern struct child_ctl2 dump_writers; extern int debug; extern struct configuration config; /* global configuration structure */ extern struct plugins_list_entry *plugins_list; /* linked list of each plugin configuration */ extern pid_t failed_plugins[MAX_N_PLUGINS]; /* plugins failed during startup phase */ extern u_char dummy_tlhdr[16], empty_mem_area_256b[SRVBUFLEN]; extern struct pm_pcap_device device; extern struct pm_pcap_devices devices, bkp_devices; extern struct pm_pcap_interfaces pm_pcap_if_map, pm_bkp_pcap_if_map; extern struct pcap_stat ps; extern struct sigaction sighandler_action; extern char pmacctd_globstr[]; extern char nfacctd_globstr[]; extern char sfacctd_globstr[]; extern char uacctd_globstr[]; extern char pmtele_globstr[]; extern char pmbgpd_globstr[]; extern char pmbmpd_globstr[]; #endif /* _PMACCT_H_ */ pmacct-1.7.8/src/kafka_plugin.h0000644000175000017500000000224414354105275015407 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KAFKA_PLUGIN_H #define KAFKA_PLUGIN_H /* includes */ #include #include /* structures */ /* prototypes */ extern void p_kafka_get_version(void); extern void kafka_plugin(int, struct configuration *, void *); extern void kafka_cache_purge(struct chained_cache *[], int, int); #endif //KAFKA_PLUGIN_H pmacct-1.7.8/src/sql_common_m.h0000644000175000017500000000255514354105275015444 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SQL_COMMON_M_H #define SQL_COMMON_M_H #include "pmacct.h" #include "sql_common.h" extern void AddToLRUTail(struct db_cache *Cursor); extern void RetireElem(struct db_cache *Cursor); extern void BuildChain(struct db_cache *Cursor, struct db_cache *newElem); extern void ReBuildChain(struct db_cache *Cursor, struct db_cache *newElem); extern void SwapChainedElems(struct db_cache *Cursor, struct db_cache *staleElem); extern void SQL_SetENV(); extern void SQL_SetENV_child(const struct insert_data *idata); #endif //SQL_COMMON_M_H pmacct-1.7.8/src/xflow_status.c0000644000175000017500000002130114354105275015504 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" /* Global variables */ xflow_status_table_t xflow_status_table; /* functions */ u_int32_t hash_status_table(u_int32_t data, struct sockaddr *sa, u_int32_t size) { int hash = -1; if (sa->sa_family == AF_INET) hash = (data ^ ((struct sockaddr_in *)sa)->sin_addr.s_addr) % size; else if (sa->sa_family == AF_INET6) { u_int32_t tmp; memcpy(&tmp, ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr+12, 4); hash = (data ^ tmp) % size; } return hash; } struct xflow_status_entry *search_status_table(xflow_status_table_t *table, struct sockaddr *sa, u_int32_t aux1, u_int32_t aux2, int hash, int num_entries) { struct xflow_status_entry *entry = table->t[hash], *saved = NULL; u_int16_t port; cycle_again: if (entry) { saved = entry; if (!sa_addr_cmp(sa, &entry->agent_addr) && aux1 == entry->aux1 && aux2 == entry->aux2); /* FOUND IT: we are done */ else { entry = entry->next; goto cycle_again; } } else { if (table->entries < num_entries) { entry = malloc(sizeof(struct xflow_status_entry)); if (!entry) goto error; else { memset(entry, 0, sizeof(struct xflow_status_entry)); sa_to_addr((struct sockaddr *)sa, &entry->agent_addr, &port); entry->aux1 = aux1; entry->aux2 = aux2; entry->seqno = 0; entry->next = FALSE; if (!saved) table->t[hash] = entry; else saved->next = entry; table->memerr = TRUE; table->entries++; } } else { error: if (table->memerr) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate more entries into the xFlow status table.\n", config.name, config.type); table->memerr = FALSE; return NULL; } } } return entry; } void update_status_table(struct xflow_status_entry *entry, u_int32_t seqno, int bytes) { if (!entry) return; entry->counters.total++; entry->counters.bytes += bytes; if (!entry->seqno || config.nfacctd_disable_checks) { entry->counters.good++; } else { if (seqno == entry->seqno + entry->inc) entry->counters.good++; else { char agent_ip_address[INET6_ADDRSTRLEN]; char collector_ip_address[INET6_ADDRSTRLEN]; char null_ip_address[] = "0.0.0.0"; addr_to_str(agent_ip_address, &entry->agent_addr); if (config.nfacctd_ip) memcpy(collector_ip_address, config.nfacctd_ip, MAX(strlen(config.nfacctd_ip), INET6_ADDRSTRLEN)); else strcpy(collector_ip_address, null_ip_address); Log(LOG_INFO, "INFO ( %s/%s ): expecting flow '%u' but received '%u' collector=%s:%u agent=%s:%u\n", config.name, config.type, entry->seqno+entry->inc, seqno, collector_ip_address, collector_port, agent_ip_address, entry->aux1); if (seqno > (entry->seqno + entry->inc)) entry->counters.jumps_f++; else entry->counters.jumps_b++; } } entry->seqno = seqno; } void print_status_table(xflow_status_table_t *table, time_t now, int buckets) { struct xflow_status_entry *entry; int idx; char agent_ip_address[INET6_ADDRSTRLEN]; char collector_ip_address[INET6_ADDRSTRLEN]; char null_ip_address[] = "0.0.0.0"; Log(LOG_NOTICE, "NOTICE ( %s/%s ): +++\n", config.name, config.type); if (config.nfacctd_ip) memcpy(collector_ip_address, config.nfacctd_ip, MAX(strlen(config.nfacctd_ip), INET6_ADDRSTRLEN)); else strcpy(collector_ip_address, null_ip_address); for (idx = 0; idx < buckets; idx++) { entry = table->t[idx]; bucket_cycle: if (entry && entry->counters.total && entry->counters.bytes) { addr_to_str(agent_ip_address, &entry->agent_addr); Log(LOG_NOTICE, "NOTICE ( %s/%s ): stats [%s:%u] agent=%s:%u time=%ld packets=%" PRIu64 " bytes=%" PRIu64 " seq_good=%u seq_jmp_fwd=%u seq_jmp_bck=%u\n", config.name, config.type, collector_ip_address, collector_port, agent_ip_address, entry->aux1, (long)now, entry->counters.total, entry->counters.bytes, entry->counters.good, entry->counters.jumps_f, entry->counters.jumps_b); if (entry->next) { entry = entry->next; goto bucket_cycle; } } } Log(LOG_NOTICE, "NOTICE ( %s/%s ): stats [%s:%u] time=%ld discarded_packets=%u\n", config.name, config.type, collector_ip_address, collector_port, (long)now, table->tot_bad_datagrams); Log(LOG_NOTICE, "NOTICE ( %s/%s ): ---\n", config.name, config.type); } struct xflow_status_entry_sampling * search_smp_if_status_table(struct xflow_status_entry_sampling *sentry, u_int32_t interface) { while (sentry) { if (sentry->interface == interface) return sentry; sentry = sentry->next; } return NULL; } struct xflow_status_entry_sampling * search_smp_id_status_table(struct xflow_status_entry_sampling *sentry, u_int32_t sampler_id, u_int8_t return_unequal) { /* Match a samplerID or, if samplerID within a data record is zero and no match was possible, then return the last samplerID defined -- last part is C7600 workaround */ while (sentry) { if (sentry->sampler_id == sampler_id || (return_unequal && !sampler_id && !sentry->next)) return sentry; sentry = sentry->next; } return NULL; } struct xflow_status_entry_sampling * create_smp_entry_status_table(xflow_status_table_t *table, struct xflow_status_entry *entry) { struct xflow_status_entry_sampling *sentry = entry->sampling, *new = NULL; if (sentry) { while (sentry->next) sentry = sentry->next; } if (table->entries < XFLOW_STATUS_TABLE_MAX_ENTRIES) { new = malloc(sizeof(struct xflow_status_entry_sampling)); if (!new) { if (table->smp_entry_status_table_memerr) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate more entries into the xflow renormalization table.\n", config.name, config.type); table->smp_entry_status_table_memerr = FALSE; } } else { if (!entry->sampling) entry->sampling = new; if (sentry) sentry->next = new; new->next = FALSE; table->smp_entry_status_table_memerr = TRUE; table->entries++; } } return new; } struct xflow_status_entry_class * search_class_id_status_table(struct xflow_status_entry_class *centry, pm_class_t class_id) { pm_class_t needle, haystack; needle = ntohl(class_id); while (centry) { haystack = ntohl(centry->class_id); if (haystack == needle) return centry; centry = centry->next; } return NULL; } struct xflow_status_entry_class * create_class_entry_status_table(xflow_status_table_t *table, struct xflow_status_entry *entry) { struct xflow_status_entry_class *centry = entry->class, *new = NULL; if (centry) { while (centry->next) centry = centry->next; } if (table->entries < XFLOW_STATUS_TABLE_MAX_ENTRIES) { new = malloc(sizeof(struct xflow_status_entry_class)); if (!new) { if (table->class_entry_status_table_memerr) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate more entries into the xflow classification table.\n", config.name, config.type); table->class_entry_status_table_memerr = FALSE; } } else { if (!entry->class) entry->class = new; if (centry) centry->next = new; new->next = FALSE; table->class_entry_status_table_memerr = TRUE; table->entries++; } } return new; } void set_vector_f_status(struct packet_ptrs_vector *pptrsv) { pptrsv->vlan4.f_status = pptrsv->v4.f_status; pptrsv->mpls4.f_status = pptrsv->v4.f_status; pptrsv->vlanmpls4.f_status = pptrsv->v4.f_status; pptrsv->v6.f_status = pptrsv->v4.f_status; pptrsv->vlan6.f_status = pptrsv->v4.f_status; pptrsv->vlanmpls6.f_status = pptrsv->v4.f_status; pptrsv->mpls6.f_status = pptrsv->v4.f_status; } void set_vector_f_status_g(struct packet_ptrs_vector *pptrsv) { pptrsv->vlan4.f_status_g = pptrsv->v4.f_status_g; pptrsv->mpls4.f_status_g = pptrsv->v4.f_status_g; pptrsv->vlanmpls4.f_status_g = pptrsv->v4.f_status_g; pptrsv->v6.f_status_g = pptrsv->v4.f_status_g; pptrsv->vlan6.f_status_g = pptrsv->v4.f_status_g; pptrsv->vlanmpls6.f_status_g = pptrsv->v4.f_status_g; pptrsv->mpls6.f_status_g = pptrsv->v4.f_status_g; } pmacct-1.7.8/src/acct.c0000644000175000017500000004125714354105275013670 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "imt_plugin.h" #include "crc32.h" #include "bgp/bgp.h" /* functions */ struct acc *search_accounting_structure(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; struct pkt_primitives *addr = &data->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_legacy_bgp_primitives *plbgp = prim_ptrs->plbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; //struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct acc *elem_acc; unsigned int hash, pos; unsigned int pp_size = sizeof(struct pkt_primitives); unsigned int pb_size = sizeof(struct pkt_bgp_primitives); unsigned int plb_size = sizeof(struct pkt_legacy_bgp_primitives); unsigned int pn_size = sizeof(struct pkt_nat_primitives); unsigned int pm_size = sizeof(struct pkt_mpls_primitives); unsigned int pt_size = sizeof(struct pkt_tunnel_primitives); unsigned int pc_size = config.cpptrs.len; hash = cache_crc32((unsigned char *)addr, pp_size); if (pbgp) hash ^= cache_crc32((unsigned char *)pbgp, pb_size); if (plbgp) hash ^= cache_crc32((unsigned char *)plbgp, plb_size); if (pnat) hash ^= cache_crc32((unsigned char *)pnat, pn_size); if (pmpls) hash ^= cache_crc32((unsigned char *)pmpls, pm_size); if (ptun) hash ^= cache_crc32((unsigned char *)ptun, pt_size); if (pcust && pc_size) hash ^= cache_crc32((unsigned char *)pcust, pc_size); // if (pvlen) hash ^= cache_crc32((unsigned char *)pvlen, (PvhdrSz + pvlen->tot_len)); pos = hash % config.buckets; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Selecting bucket %u.\n", config.name, config.type, pos); elem_acc = (struct acc *) a; elem_acc += pos; while (elem_acc) { if (elem_acc->signature == hash) { if (compare_accounting_structure(elem_acc, prim_ptrs) == 0) return elem_acc; } elem_acc = elem_acc->next; } return NULL; } int compare_accounting_structure(struct acc *elem, struct primitives_ptrs *prim_ptrs) { struct pkt_data *pdata = prim_ptrs->data; struct pkt_primitives *data = &pdata->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_legacy_bgp_primitives *plbgp = prim_ptrs->plbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE; int res_cust = TRUE, res_vlen = TRUE, res_lbgp = TRUE; res_data = memcmp(&elem->primitives, data, sizeof(struct pkt_primitives)); if (pbgp && elem->pbgp) res_bgp = memcmp(elem->pbgp, pbgp, sizeof(struct pkt_bgp_primitives)); else res_bgp = FALSE; if (plbgp) { if (elem->clbgp) { struct pkt_legacy_bgp_primitives tmp_plbgp; cache_to_pkt_legacy_bgp_primitives(&tmp_plbgp, elem->clbgp); res_lbgp = memcmp(&tmp_plbgp, plbgp, sizeof(struct pkt_legacy_bgp_primitives)); } } else res_lbgp = FALSE; if (pnat && elem->pnat) res_nat = memcmp(elem->pnat, pnat, sizeof(struct pkt_nat_primitives)); else res_nat = FALSE; if (pmpls && elem->pmpls) res_mpls = memcmp(elem->pmpls, pmpls, sizeof(struct pkt_mpls_primitives)); else res_mpls = FALSE; if (ptun && elem->ptun) res_tun = memcmp(elem->ptun, ptun, sizeof(struct pkt_tunnel_primitives)); else res_tun = FALSE; if (pcust && elem->pcust) res_cust = memcmp(elem->pcust, pcust, config.cpptrs.len); else res_cust = FALSE; if (pvlen && elem->pvlen) res_vlen = vlen_prims_cmp(elem->pvlen, pvlen); else res_vlen = FALSE; return res_data | res_bgp | res_lbgp | res_nat | res_mpls | res_tun | res_cust | res_vlen; } void insert_accounting_structure(struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; struct pkt_primitives *addr = &data->primitives; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_legacy_bgp_primitives *plbgp = prim_ptrs->plbgp; struct pkt_nat_primitives *pnat = prim_ptrs->pnat; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct acc *elem_acc; unsigned char *elem, *new_elem; int solved = FALSE; unsigned int hash, pos; unsigned int pp_size = sizeof(struct pkt_primitives); unsigned int pb_size = sizeof(struct pkt_bgp_primitives); unsigned int plb_size = sizeof(struct pkt_legacy_bgp_primitives); unsigned int pn_size = sizeof(struct pkt_nat_primitives); unsigned int pm_size = sizeof(struct pkt_mpls_primitives); unsigned int pt_size = sizeof(struct pkt_tunnel_primitives); unsigned int pc_size = config.cpptrs.len; unsigned int clb_size = sizeof(struct cache_legacy_bgp_primitives); elem = a; hash = cache_crc32((unsigned char *)addr, pp_size); if (pbgp) hash ^= cache_crc32((unsigned char *)pbgp, pb_size); if (plbgp) hash ^= cache_crc32((unsigned char *)plbgp, plb_size); if (pnat) hash ^= cache_crc32((unsigned char *)pnat, pn_size); if (pmpls) hash ^= cache_crc32((unsigned char *)pmpls, pm_size); if (ptun) hash ^= cache_crc32((unsigned char *)ptun, pt_size); if (pcust && pc_size) hash ^= cache_crc32((unsigned char *)pcust, pc_size); // if (pvlen) hash ^= cache_crc32((unsigned char *)pvlen, (PvhdrSz + pvlen->tot_len)); pos = hash % config.buckets; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Selecting bucket %u.\n", config.name, config.type, pos); /* 1st stage: compare data with last used element; 2nd stage: compare data with elements in the table, following chains */ if (lru_elem_ptr[pos]) { elem_acc = lru_elem_ptr[pos]; if (elem_acc->signature == hash) { if (compare_accounting_structure(elem_acc, prim_ptrs) == 0) { if (elem_acc->reset_flag) reset_counters(elem_acc); elem_acc->packet_counter += data->pkt_num; elem_acc->flow_counter += data->flo_num; elem_acc->bytes_counter += data->pkt_len; elem_acc->tcp_flags |= data->tcp_flags; elem_acc->tunnel_tcp_flags |= data->tunnel_tcp_flags; elem_acc->flow_type = data->flow_type; return; } } } elem_acc = (struct acc *) elem; elem_acc += pos; while (solved == FALSE) { if (elem_acc->signature == hash) { if (compare_accounting_structure(elem_acc, prim_ptrs) == 0) { if (elem_acc->reset_flag) reset_counters(elem_acc); elem_acc->packet_counter += data->pkt_num; elem_acc->flow_counter += data->flo_num; elem_acc->bytes_counter += data->pkt_len; elem_acc->tcp_flags |= data->tcp_flags; elem_acc->tunnel_tcp_flags |= data->tunnel_tcp_flags; elem_acc->flow_type = data->flow_type; lru_elem_ptr[pos] = elem_acc; return; } } if (!elem_acc->bytes_counter && !elem_acc->packet_counter) { /* hmmm */ if (elem_acc->reset_flag) elem_acc->reset_flag = FALSE; memcpy(&elem_acc->primitives, addr, sizeof(struct pkt_primitives)); if (pbgp) { if (!elem_acc->pbgp) { elem_acc->pbgp = (struct pkt_bgp_primitives *) malloc(pb_size); if (!elem_acc->pbgp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memcpy(elem_acc->pbgp, pbgp, pb_size); } else { if (elem_acc->pbgp) free(elem_acc->pbgp); elem_acc->pbgp = NULL; } if (plbgp) { if (!elem_acc->clbgp) { elem_acc->clbgp = (struct cache_legacy_bgp_primitives *) malloc(clb_size); if (!elem_acc->clbgp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memset(elem_acc->clbgp, 0, clb_size); pkt_to_cache_legacy_bgp_primitives(elem_acc->clbgp, plbgp, config.what_to_count, config.what_to_count_2); } else free_cache_legacy_bgp_primitives(&elem_acc->clbgp); if (pnat) { if (!elem_acc->pnat) { elem_acc->pnat = (struct pkt_nat_primitives *) malloc(pn_size); if (!elem_acc->pnat) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memcpy(elem_acc->pnat, pnat, pn_size); } else { if (elem_acc->pnat) free(elem_acc->pnat); elem_acc->pnat = NULL; } if (pmpls) { if (!elem_acc->pmpls) { elem_acc->pmpls = (struct pkt_mpls_primitives *) malloc(pm_size); if (!elem_acc->pmpls) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memcpy(elem_acc->pmpls, pmpls, pm_size); } else { if (elem_acc->pmpls) free(elem_acc->pmpls); elem_acc->pmpls = NULL; } if (ptun) { if (!elem_acc->ptun) { elem_acc->ptun = (struct pkt_tunnel_primitives *) malloc(pt_size); if (!elem_acc->ptun) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memcpy(elem_acc->ptun, ptun, pt_size); } else { if (elem_acc->ptun) free(elem_acc->ptun); elem_acc->ptun = NULL; } if (pcust) { if (!elem_acc->pcust) { elem_acc->pcust = malloc(pc_size); if (!elem_acc->pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } memcpy(elem_acc->pcust, pcust, pc_size); } else { if (elem_acc->pcust) free(elem_acc->pcust); elem_acc->pcust = NULL; } /* if we have a pvlen from before let's free it up due to the vlen nature of the memory area */ if (elem_acc->pvlen) { vlen_prims_free(elem_acc->pvlen); elem_acc->pvlen = NULL; } if (pvlen) { if (!elem_acc->pvlen) { elem_acc->pvlen = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen); if (!elem_acc->pvlen) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } } elem_acc->packet_counter += data->pkt_num; elem_acc->flow_counter += data->flo_num; elem_acc->bytes_counter += data->pkt_len; elem_acc->tcp_flags |= data->tcp_flags; elem_acc->tunnel_tcp_flags |= data->tunnel_tcp_flags; elem_acc->flow_type = data->flow_type; elem_acc->signature = hash; lru_elem_ptr[pos] = elem_acc; return; } /* Handling collisions */ else if (elem_acc->next != NULL) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Walking through the collision-chain.\n", config.name, config.type); elem_acc = elem_acc->next; solved = FALSE; } else if (elem_acc->next == NULL) { /* We have to know if there is enough space for a new element; if not we are losing informations; conservative approach */ if (no_more_space) return; /* We have to allocate new space for this address */ Log(LOG_DEBUG, "DEBUG ( %s/%s ): Creating new element.\n", config.name, config.type); if (current_pool->space_left >= sizeof(struct acc)) { new_elem = current_pool->ptr; current_pool->space_left -= sizeof(struct acc); current_pool->ptr += sizeof(struct acc); } else { current_pool = request_memory_pool(config.memory_pool_size); if (current_pool == NULL) { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to allocate more memory pools, clear stats manually!\n", config.name, config.type); no_more_space = TRUE; return; } else { new_elem = current_pool->ptr; current_pool->space_left -= sizeof(struct acc); current_pool->ptr += sizeof(struct acc); } } elem_acc->next = (struct acc *) new_elem; elem_acc = (struct acc *) new_elem; memcpy(&elem_acc->primitives, addr, sizeof(struct pkt_primitives)); if (pbgp) { elem_acc->pbgp = (struct pkt_bgp_primitives *) malloc(pb_size); if (!elem_acc->pbgp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memcpy(elem_acc->pbgp, pbgp, pb_size); } else elem_acc->pbgp = NULL; if (plbgp) { elem_acc->clbgp = (struct cache_legacy_bgp_primitives *) malloc(clb_size); if (!elem_acc->clbgp) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memset(elem_acc->clbgp, 0, clb_size); pkt_to_cache_legacy_bgp_primitives(elem_acc->clbgp, plbgp, config.what_to_count, config.what_to_count_2); } else elem_acc->clbgp = NULL; if (pnat) { elem_acc->pnat = (struct pkt_nat_primitives *) malloc(pn_size); if (!elem_acc->pnat) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memcpy(elem_acc->pnat, pnat, pn_size); } else elem_acc->pnat = NULL; if (pmpls) { elem_acc->pmpls = (struct pkt_mpls_primitives *) malloc(pm_size); if (!elem_acc->pmpls) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memcpy(elem_acc->pmpls, pmpls, pm_size); } else elem_acc->pmpls = NULL; if (ptun) { elem_acc->ptun = (struct pkt_tunnel_primitives *) malloc(pt_size); if (!elem_acc->ptun) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memcpy(elem_acc->ptun, ptun, pt_size); } else elem_acc->ptun = NULL; if (pcust) { elem_acc->pcust = malloc(pc_size); if (!elem_acc->pcust) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } memcpy(elem_acc->pcust, pcust, pc_size); } else elem_acc->pcust = NULL; /* if we have a pvlen from before let's free it up due to the vlen nature of the memory area */ if (elem_acc->pvlen) { vlen_prims_free(elem_acc->pvlen); elem_acc->pvlen = NULL; } if (pvlen) { if (!elem_acc->pvlen) { elem_acc->pvlen = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen); if (!elem_acc->pvlen) { Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (insert_accounting_structure). Exiting ..\n", config.name, config.type); exit_gracefully(1); } } } elem_acc->packet_counter += data->pkt_num; elem_acc->flow_counter += data->flo_num; elem_acc->bytes_counter += data->pkt_len; elem_acc->tcp_flags = data->tcp_flags; elem_acc->tunnel_tcp_flags = data->tunnel_tcp_flags; elem_acc->flow_type = data->flow_type; elem_acc->signature = hash; elem_acc->next = NULL; lru_elem_ptr[pos] = elem_acc; return; } } } void set_reset_flag(struct acc *elem) { elem->reset_flag = TRUE; } void reset_counters(struct acc *elem) { elem->reset_flag = FALSE; elem->packet_counter = 0; elem->bytes_counter = 0; elem->tcp_flags = 0; elem->tunnel_tcp_flags = 0; elem->flow_type = 0; memcpy(&elem->rstamp, &cycle_stamp, sizeof(struct timeval)); } pmacct-1.7.8/src/sfacctd.h0000644000175000017500000002510514354105275014364 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* much of the sflow v2/v4/v5 definitions are based on sFlow toolkit 3.8 and later which is Copyright (C) InMon Corporation 2001 ALL RIGHTS RESERVED */ #ifndef SFACCTD_H #define SFACCTD_H /* defines */ #define DEFAULT_SFACCTD_PORT 6343 #define SFLOW_MIN_MSG_SIZE 200 #define SFLOW_MAX_MSG_SIZE 65536 /* inflated ? */ #define MAX_SF_CNT_LOG_ENTRIES 1024 enum INMPacket_information_type { INMPACKETTYPE_HEADER = 1, /* Packet headers are sampled */ INMPACKETTYPE_IPV4 = 2, /* IP version 4 data */ INMPACKETTYPE_IPV6 = 3 /* IP version 4 data */ }; enum INMExtended_information_type { INMEXTENDED_SWITCH = 1, /* Extended switch information */ INMEXTENDED_ROUTER = 2, /* Extended router information */ INMEXTENDED_GATEWAY = 3, /* Extended gateway router information */ INMEXTENDED_USER = 4, /* Extended TACAS/RADIUS user information */ INMEXTENDED_URL = 5 /* Extended URL information */ }; enum INMCounters_version { INMCOUNTERSVERSION_GENERIC = 1, INMCOUNTERSVERSION_ETHERNET = 2, INMCOUNTERSVERSION_TOKENRING = 3, INMCOUNTERSVERSION_FDDI = 4, INMCOUNTERSVERSION_VG = 5, INMCOUNTERSVERSION_WAN = 6, INMCOUNTERSVERSION_VLAN = 7 }; typedef struct _SFSample { struct timeval *ts; struct in_addr sourceIP; SFLAddress agent_addr; u_int32_t agentSubId; /* the raw pdu */ u_char *rawSample; u_int32_t rawSampleLen; u_char *endp; u_int32_t *datap; u_int32_t datagramVersion; u_int32_t sampleType; u_int32_t ds_class; u_int32_t ds_index; /* generic interface counter sample */ SFLIf_counters ifCounters; /* sample stream info */ u_int32_t sysUpTime; u_int32_t sequenceNo; u_int32_t cntSequenceNo; u_int32_t sampledPacketSize; u_int32_t samplesGenerated; u_int32_t meanSkipCount; u_int32_t samplePool; u_int32_t dropEvents; /* the sampled header */ u_int32_t packet_data_tag; u_int32_t headerProtocol; u_char *header; int headerLen; u_int32_t stripped; /* header decode */ int gotIPV4; int offsetToIPV4; int gotIPV6; int offsetToIPV6; struct in_addr dcd_srcIP; struct in_addr dcd_dstIP; u_int32_t dcd_ipProtocol; u_int32_t dcd_ipTos; u_int32_t dcd_ipTTL; u_int32_t dcd_sport; u_int32_t dcd_dport; u_int32_t dcd_tcpFlags; u_int32_t ip_fragmentOffset; u_int32_t udp_pduLen; /* ports */ u_int32_t inputPortFormat; u_int32_t outputPortFormat; u_int32_t inputPort; u_int32_t outputPort; /* ethernet */ u_int32_t eth_type; u_int32_t eth_len; u_char eth_src[8]; u_char eth_dst[8]; /* vlan */ u_int32_t in_vlan; u_int32_t in_priority; u_int32_t internalPriority; u_int32_t out_vlan; u_int32_t out_priority; u_int32_t cvlan; u_int32_t cvlan_priority; /* MPLS hack */ SFLLabelStack lstk; SFLLabelStack lstk_out; /* extended data fields */ u_int32_t num_extended; u_int32_t extended_data_tag; #define SASAMPLE_EXTENDED_DATA_SWITCH 1 #define SASAMPLE_EXTENDED_DATA_ROUTER 4 #define SASAMPLE_EXTENDED_DATA_GATEWAY 8 #define SASAMPLE_EXTENDED_DATA_USER 16 #define SASAMPLE_EXTENDED_DATA_URL 32 #define SASAMPLE_EXTENDED_DATA_MPLS 64 #define SASAMPLE_EXTENDED_DATA_NAT 128 #define SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL 256 #define SASAMPLE_EXTENDED_DATA_MPLS_VC 512 #define SASAMPLE_EXTENDED_DATA_MPLS_FTN 1024 #define SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC 2048 #define SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL 4096 /* IP forwarding info */ SFLAddress nextHop; u_int32_t srcMask; u_int32_t dstMask; /* BGP info */ SFLAddress bgp_nextHop; u_int32_t my_as; u_int32_t src_as; u_int32_t src_peer_as; u_int32_t dst_as_path_len; char dst_as_path[LARGEBUFLEN]; u_int32_t dst_peer_as; u_int32_t dst_as; u_int32_t communities_len; char comms[LARGEBUFLEN]; u_int32_t localpref; /* user id */ #define SA_MAX_EXTENDED_USER_LEN 200 u_int32_t src_user_charset; u_int32_t src_user_len; char src_user[SA_MAX_EXTENDED_USER_LEN+1]; u_int32_t dst_user_charset; u_int32_t dst_user_len; char dst_user[SA_MAX_EXTENDED_USER_LEN+1]; /* url */ #define SA_MAX_EXTENDED_URL_LEN 200 #define SA_MAX_EXTENDED_HOST_LEN 200 u_int32_t url_direction; u_int32_t url_len; char url[SA_MAX_EXTENDED_URL_LEN+1]; u_int32_t host_len; char host[SA_MAX_EXTENDED_HOST_LEN+1]; /* mpls */ SFLAddress mpls_nextHop; u_int32_t mpls_vll_vc_id; u_int32_t mpls_tunnel_id; /* nat */ SFLAddress nat_src; SFLAddress nat_dst; /* vxlan */ u_int32_t vni; /* counter blocks */ u_int32_t statsSamplingInterval; u_int32_t counterBlockVersion; /* classification */ pm_class_t class; #if defined (WITH_NDPI) pm_class2_t ndpi_class; #endif pm_id_t tag; pm_id_t tag2; SFLAddress ipsrc; SFLAddress ipdst; struct packet_ptrs hdr_ptrs; struct pcap_pkthdr hdr_pcap; void *sppi; } SFSample; /* define my own IP header struct - to ease portability */ struct SF_iphdr { u_int8_t version_and_headerLen; u_int8_t tos; u_int16_t tot_len; u_int16_t id; u_int16_t frag_off; u_int8_t ttl; u_int8_t protocol; u_int16_t check; u_int32_t saddr; u_int32_t daddr; }; /* same for tcp */ struct SF_tcphdr { u_int16_t th_sport; u_int16_t th_dport; u_int32_t th_seq; u_int32_t th_ack; u_int8_t th_off_and_unused; u_int8_t th_flags; u_int16_t th_win; u_int16_t th_sum; u_int16_t th_urp; }; /* and UDP */ struct SF_udphdr { u_int16_t uh_sport; u_int16_t uh_dport; u_int16_t uh_ulen; u_int16_t uh_sum; }; /* and ICMP */ struct SF_icmphdr { u_int8_t type; u_int8_t code; /* ignore the rest */ }; struct SF_dissect { u_char *hdrBasePtr; u_char *hdrEndPtr; u_int32_t hdrLen; u_char *flowBasePtr; u_char *flowEndPtr; u_int32_t flowLen; u_int32_t *samplesInPkt; }; extern u_int8_t SF_evaluate_flow_type(struct packet_ptrs *); extern void set_vector_sample_type(struct packet_ptrs_vector *, u_int32_t); extern void reset_mac(struct packet_ptrs *); extern void reset_mac_vlan(struct packet_ptrs *); extern void reset_ip4(struct packet_ptrs *); extern void reset_ip6(struct packet_ptrs *); extern void SF_notify_malf_packet(short int, char *, char *, struct sockaddr *); extern int SF_find_id(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); extern void SF_compute_once(); extern char *getPointer(SFSample *); extern u_int32_t getData32(SFSample *); extern u_int32_t getData32_nobswap(SFSample *); extern u_int64_t getData64(SFSample *); extern u_int32_t getAddress(SFSample *, SFLAddress *); extern void skipBytes(SFSample *, int); extern int skipBytesAndCheck(SFSample *, int); extern int lengthCheck(SFSample *, u_char *, u_int32_t); extern u_int32_t getString(SFSample *, char *, u_int32_t); extern void process_SFv2v4_packet(SFSample *, struct packet_ptrs_vector *, struct plugin_requests *, struct sockaddr *); extern void process_SFv5_packet(SFSample *, struct packet_ptrs_vector *, struct plugin_requests *, struct sockaddr *); extern void process_SF_raw_packet(SFSample *, struct packet_ptrs_vector *, struct plugin_requests *, struct sockaddr *); extern void readv2v4FlowSample(SFSample *, struct packet_ptrs_vector *, struct plugin_requests *); extern void readv5FlowSample(SFSample *, int, struct packet_ptrs_vector *, struct plugin_requests *, int); extern void readv2v4CountersSample(SFSample *, struct packet_ptrs_vector *); extern void readv5CountersSample(SFSample *, int, struct packet_ptrs_vector *); extern void finalizeSample(SFSample *, struct packet_ptrs_vector *, struct plugin_requests *); extern void InterSampleCleanup(SFSample *); extern void decodeMpls(SFSample *, u_char **); extern void decodePPP(SFSample *); extern void decodeLinkLayer(SFSample *); extern void decodeIPLayer4(SFSample *, u_char *, u_int32_t); extern void decodeIPV4(SFSample *); extern void decodeIPV6(SFSample *); extern void decodeVXLAN(SFSample *, u_char *); extern void readExtendedSwitch(SFSample *); extern void readExtendedRouter(SFSample *); extern void readExtendedGateway_v2(SFSample *); extern void readExtendedGateway(SFSample *); extern void readExtendedUser(SFSample *); extern void readExtendedUrl(SFSample *); extern void mplsLabelStack(SFSample *, u_int8_t); extern void readExtendedMpls(SFSample *); extern void readExtendedNat(SFSample *); extern void readExtendedMplsTunnel(SFSample *); extern void readExtendedMplsVC(SFSample *); extern void readExtendedMplsFTN(SFSample *); extern void readExtendedMplsLDP_FEC(SFSample *); extern void readExtendedVlanTunnel(SFSample *); extern void readExtendedProcess(SFSample *); extern void readFlowSample_header(SFSample *); extern void readFlowSample_ethernet(SFSample *); extern void readFlowSample_IPv4(SFSample *); extern void readFlowSample_IPv6(SFSample *); extern int sf_cnt_log_msg(struct bgp_peer *, SFSample *, int, u_int32_t, char *, int, u_int32_t); extern int readCounters_generic(struct bgp_peer *, SFSample *, char *, int, void *); extern int readCounters_ethernet(struct bgp_peer *, SFSample *, char *, int, void *); extern int readCounters_vlan(struct bgp_peer *, SFSample *, char *, int, void *); extern void sfacctd_counter_init_amqp_host(); extern int sfacctd_counter_init_kafka_host(); extern void sf_cnt_link_misc_structs(struct bgp_misc_structs *); extern void sf_flow_sample_hdr_decode(SFSample *); extern struct xflow_status_entry *sfv245_check_status(SFSample *spp, struct packet_ptrs *, struct sockaddr *); extern void sfv245_check_counter_log_init(struct packet_ptrs *); extern void usage_daemon(char *); extern void compute_once(); #ifdef WITH_KAFKA extern void SF_init_kafka_host(void *); #endif #ifdef WITH_ZMQ extern void SF_init_zmq_host(void *, int *); #endif /* global variables */ extern int sfacctd_counter_backend_methods; extern struct bgp_misc_structs *sf_cnt_misc_db; extern struct host_addr debug_a; extern char debug_agent_addr[50]; extern u_int16_t debug_agent_port; #endif //SFACCTD_H pmacct-1.7.8/src/pmsearch.c0000644000175000017500000005760114354105275014560 0ustar paolopaolo/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is largely based on the GNU C Library and contains: * System V style searching functions - Contributed by Bernd Schmidt , 1997. * Hash table management functions - Contributed by Ulrich Drepper , 1993. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ /* Tree search for red/black trees. The algorithm for adding nodes is taken from one of the many "Algorithms" books by Robert Sedgewick, although the implementation differs. The algorithm for deleting nodes can probably be found in a book named "Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's the book that my professor took most algorithms from during the "Data Structures" course... Totally public domain. */ /* Red/black trees are binary trees in which the edges are colored either red or black. They have the following properties: 1. The number of black edges on every path from the root to a leaf is constant. 2. No two red edges are adjacent. Therefore there is an upper bound on the length of every path, it's O(log n) where n is the number of nodes in the tree. No path can be longer than 1+2*P where P is the length of the shortest path in the tree. Useful for the implementation: 3. If one of the children of a node is NULL, then the other one is red (if it exists). In the implementation, not the edges are colored, but the nodes. The color interpreted as the color of the edge leading to this node. The color is meaningless for the root node, but we color the root node black for convenience. All added nodes are red initially. Adding to a red/black tree is rather easy. The right place is searched with a usual binary tree search. Additionally, whenever a node N is reached that has two red successors, the successors are colored black and the node itself colored red. This moves red edges up the tree where they pose less of a problem once we get to really insert the new node. Changing N's color to red may violate rule 2, however, so rotations may become necessary to restore the invariants. Adding a new red leaf may violate the same rule, so afterwards an additional check is run and the tree possibly rotated. Deleting is hairy. There are mainly two nodes involved: the node to be deleted (n1), and another node that is to be unchained from the tree (n2). If n1 has a successor (the node with a smallest key that is larger than n1), then the successor becomes n2 and its contents are copied into n1, otherwise n1 becomes n2. Unchaining a node may violate rule 1: if n2 is black, one subtree is missing one black edge afterwards. The algorithm must try to move this error upwards towards the root, so that the subtree that does not have enough black edges becomes the whole tree. Once that happens, the error has disappeared. It may not be necessary to go all the way up, since it is possible that rotations and recoloring can fix the error before that. Although the deletion algorithm must walk upwards through the tree, we do not store parent pointers in the nodes. Instead, delete allocates a small array of parent pointers and fills it while descending the tree. Since we know that the length of a path is O(log n), where n is the number of nodes, this is likely to use less memory. */ /* Tree rotations look like this: A C / \ / \ B C A G / \ / \ --> / \ D E F G B F / \ D E In this case, A has been rotated left. This preserves the ordering of the binary tree. */ /* includes */ #include "pmacct.h" #include "crc32.h" /* Possibly "split" a node with two red successors, and/or fix up two red edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the comparison values that determined which way was taken in the tree to reach ROOTP. MODE is 1 if we need not do the split, but must check for two red edges between GPARENTP and ROOTP. */ static void pm_maybe_split_for_insert (pm_node *rootp, pm_node *parentp, pm_node *gparentp, int p_r, int gp_r, int mode) { pm_node root = DEREFNODEPTR(rootp); pm_node *rp, *lp; pm_node rpn, lpn; rp = RIGHTPTR(root); rpn = RIGHT(root); lp = LEFTPTR(root); lpn = LEFT(root); /* See if we have to split this node (both successors red). */ if (mode == 1 || ((rpn) != NULL && (lpn) != NULL && RED(rpn) && RED(lpn))) { /* This node becomes red, its successors black. */ SETRED(root); if (rpn) SETBLACK(rpn); if (lpn) SETBLACK(lpn); /* If the parent of this node is also red, we have to do rotations. */ if (parentp != NULL && RED(DEREFNODEPTR(parentp))) { pm_node gp = DEREFNODEPTR(gparentp); pm_node p = DEREFNODEPTR(parentp); /* There are two main cases: 1. The edge types (left or right) of the two red edges differ. 2. Both red edges are of the same type. There exist two symmetries of each case, so there is a total of 4 cases. */ if ((p_r > 0) != (gp_r > 0)) { /* Put the child at the top of the tree, with its parent and grandparent as successors. */ SETRED(p); SETRED(gp); SETBLACK(root); if (p_r < 0) { /* Child is left of parent. */ SETLEFT(p,rpn); SETNODEPTR(rp,p); SETRIGHT(gp,lpn); SETNODEPTR(lp,gp); } else { /* Child is right of parent. */ SETRIGHT(p,lpn); SETNODEPTR(lp,p); SETLEFT(gp,rpn); SETNODEPTR(rp,gp); } SETNODEPTR(gparentp,root); } else { SETNODEPTR(gparentp,p); /* Parent becomes the top of the tree, grandparent and child are its successors. */ SETBLACK(p); SETRED(gp); if (p_r < 0) { /* Left edges. */ SETLEFT(gp,RIGHT(p)); SETRIGHT(p,gp); } else { /* Right edges. */ SETRIGHT(gp,LEFT(p)); SETLEFT(p,gp); } } } } } /* Find or insert datum into search tree. KEY is the key to be located, ROOTP is the address of tree root, COMPAR the ordering function. */ void * __pm_tsearch (const void *key, void **vrootp, pm_compar_fn_t compar) { pm_node q, root; pm_node *parentp = NULL, *gparentp = NULL; pm_node *rootp = (pm_node *) vrootp; pm_node *nextp; int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */ // static_assert (alignof (max_align_t) > 1, "malloc must return aligned ptrs"); if (rootp == NULL) return NULL; /* This saves some additional tests below. */ root = DEREFNODEPTR(rootp); if (root != NULL) SETBLACK(root); nextp = rootp; while (DEREFNODEPTR(nextp) != NULL) { root = DEREFNODEPTR(rootp); r = (*compar) (key, root->key); if (r == 0) return root; pm_maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0); /* If that did any rotations, parentp and gparentp are now garbage. That doesn't matter, because the values they contain are never used again in that case. */ nextp = r < 0 ? LEFTPTR(root) : RIGHTPTR(root); if (DEREFNODEPTR(nextp) == NULL) break; gparentp = parentp; parentp = rootp; rootp = nextp; gp_r = p_r; p_r = r; } q = (struct pm_node_t *) malloc (sizeof (struct pm_node_t)); if (q != NULL) { /* Make sure the malloc implementation returns naturally aligned memory blocks when expected. Or at least even pointers, so we can use the low bit as red/black flag. Even though we have a static_assert to make sure alignof (max_align_t) > 1 there could be an interposed malloc implementation that might cause havoc by not obeying the malloc contract. */ assert (((uintptr_t) q & (uintptr_t) 0x1) == 0); SETNODEPTR(nextp,q); /* link new node to old */ q->key = key; /* initialize new node */ SETRED(q); SETLEFT(q,NULL); SETRIGHT(q,NULL); if (nextp != rootp) /* There may be two red edges in a row now, which we must avoid by rotating the tree. */ pm_maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1); } return q; } /* Find datum in search tree. KEY is the key to be located, ROOTP is the address of tree root, COMPAR the ordering function. */ void *pm_tfind (const void *key, void **vrootp, pm_compar_fn_t compar) { pm_node root; pm_node *rootp = (pm_node *) vrootp; if (rootp == NULL) return NULL; root = DEREFNODEPTR(rootp); while (DEREFNODEPTR(rootp) != NULL) { root = DEREFNODEPTR(rootp); int r; r = (*compar) (key, root->key); if (r == 0) return root; rootp = r < 0 ? LEFTPTR(root) : RIGHTPTR(root); } return NULL; } /* Delete node with given key. KEY is the key to be deleted, ROOTP is the address of the root of tree, COMPAR the comparison function. */ void *pm_tdelete (const void *key, void **vrootp, pm_compar_fn_t compar) { pm_node p, q, r, retval; int cmp; pm_node *rootp = (pm_node *) vrootp; pm_node root, unchained; /* Stack of nodes so we remember the parents without recursion. It's _very_ unlikely that there are paths longer than 40 nodes. The tree would need to have around 250.000 nodes. */ int stacksize = 40; int sp = 0; pm_node **nodestack = alloca (sizeof (pm_node *) * stacksize); if (rootp == NULL) return NULL; p = DEREFNODEPTR(rootp); if (p == NULL) return NULL; root = DEREFNODEPTR(rootp); while ((cmp = (*compar) (key, root->key)) != 0) { if (sp == stacksize) { pm_node **newstack; stacksize += 20; newstack = alloca (sizeof (pm_node *) * stacksize); nodestack = memcpy (newstack, nodestack, sp * sizeof (pm_node *)); } nodestack[sp++] = rootp; p = DEREFNODEPTR(rootp); if (cmp < 0) { rootp = LEFTPTR(p); root = LEFT(p); } else { rootp = RIGHTPTR(p); root = RIGHT(p); } if (root == NULL) return NULL; } /* This is bogus if the node to be deleted is the root... this routine really should return an integer with 0 for success, -1 for failure */ retval = p; /* We don't unchain the node we want to delete. Instead, we overwrite it with its successor and unchain the successor. If there is no successor, we really unchain the node to be deleted. */ root = DEREFNODEPTR(rootp); r = RIGHT(root); q = LEFT(root); if (q == NULL || r == NULL) unchained = root; else { pm_node *parentp = rootp, *up = RIGHTPTR(root); pm_node upn; for (;;) { if (sp == stacksize) { pm_node **newstack; stacksize += 20; newstack = alloca (sizeof (pm_node *) * stacksize); nodestack = memcpy (newstack, nodestack, sp * sizeof (pm_node *)); } nodestack[sp++] = parentp; parentp = up; upn = DEREFNODEPTR(up); if (LEFT(upn) == NULL) break; up = LEFTPTR(upn); } unchained = DEREFNODEPTR(up); } /* We know that either the left or right successor of UNCHAINED is NULL. R becomes the other one, it is chained into the parent of UNCHAINED. */ r = LEFT(unchained); if (r == NULL) r = RIGHT(unchained); if (sp == 0) SETNODEPTR(rootp,r); else { q = DEREFNODEPTR(nodestack[sp-1]); if (unchained == RIGHT(q)) SETRIGHT(q,r); else SETLEFT(q,r); } if (unchained != root) root->key = unchained->key; if (!RED(unchained)) { /* Now we lost a black edge, which means that the number of black edges on every path is no longer constant. We must balance the tree. */ /* NODESTACK now contains all parents of R. R is likely to be NULL in the first iteration. */ /* NULL nodes are considered black throughout - this is necessary for correctness. */ while (sp > 0 && (r == NULL || !RED(r))) { pm_node *pp = nodestack[sp - 1]; p = DEREFNODEPTR(pp); /* Two symmetric cases. */ if (r == LEFT(p)) { /* Q is R's brother, P is R's parent. The subtree with root R has one black edge less than the subtree with root Q. */ q = RIGHT(p); if (RED(q)) { /* If Q is red, we know that P is black. We rotate P left so that Q becomes the top node in the tree, with P below it. P is colored red, Q is colored black. This action does not change the black edge count for any leaf in the tree, but we will be able to recognize one of the following situations, which all require that Q is black. */ SETBLACK(q); SETRED(p); /* Left rotate p. */ SETRIGHT(p,LEFT(q)); SETLEFT(q,p); SETNODEPTR(pp,q); /* Make sure pp is right if the case below tries to use it. */ nodestack[sp++] = pp = LEFTPTR(q); q = RIGHT(p); } /* We know that Q can't be NULL here. We also know that Q is black. */ if ((LEFT(q) == NULL || !RED(LEFT(q))) && (RIGHT(q) == NULL || !RED(RIGHT(q)))) { /* Q has two black successors. We can simply color Q red. The whole subtree with root P is now missing one black edge. Note that this action can temporarily make the tree invalid (if P is red). But we will exit the loop in that case and set P black, which both makes the tree valid and also makes the black edge count come out right. If P is black, we are at least one step closer to the root and we'll try again the next iteration. */ SETRED(q); r = p; } else { /* Q is black, one of Q's successors is red. We can repair the tree with one operation and will exit the loop afterwards. */ if (RIGHT(q) == NULL || !RED(RIGHT(q))) { /* The left one is red. We perform the same action as in maybe_split_for_insert where two red edges are adjacent but point in different directions: Q's left successor (let's call it Q2) becomes the top of the subtree we are looking at, its parent (Q) and grandparent (P) become its successors. The former successors of Q2 are placed below P and Q. P becomes black, and Q2 gets the color that P had. This changes the black edge count only for node R and its successors. */ pm_node q2 = LEFT(q); if (RED(p)) SETRED(q2); else SETBLACK(q2); SETRIGHT(p,LEFT(q2)); SETLEFT(q,RIGHT(q2)); SETRIGHT(q2,q); SETLEFT(q2,p); SETNODEPTR(pp,q2); SETBLACK(p); } else { /* It's the right one. Rotate P left. P becomes black, and Q gets the color that P had. Q's right successor also becomes black. This changes the black edge count only for node R and its successors. */ if (RED(p)) SETRED(q); else SETBLACK(q); SETBLACK(p); SETBLACK(RIGHT(q)); /* left rotate p */ SETRIGHT(p,LEFT(q)); SETLEFT(q,p); SETNODEPTR(pp,q); } /* We're done. */ sp = 1; r = NULL; } } else { /* Comments: see above. */ q = LEFT(p); if (RED(q)) { SETBLACK(q); SETRED(p); SETLEFT(p,RIGHT(q)); SETRIGHT(q,p); SETNODEPTR(pp,q); nodestack[sp++] = pp = RIGHTPTR(q); q = LEFT(p); } if ((RIGHT(q) == NULL || !RED(RIGHT(q))) && (LEFT(q) == NULL || !RED(LEFT(q)))) { SETRED(q); r = p; } else { if (LEFT(q) == NULL || !RED(LEFT(q))) { pm_node q2 = RIGHT(q); if (RED(p)) SETRED(q2); else SETBLACK(q2); SETLEFT(p,RIGHT(q2)); SETRIGHT(q,LEFT(q2)); SETLEFT(q2,q); SETRIGHT(q2,p); SETNODEPTR(pp,q2); SETBLACK(p); } else { if (RED(p)) SETRED(q); else SETBLACK(q); SETBLACK(p); SETBLACK(LEFT(q)); SETLEFT(p,RIGHT(q)); SETRIGHT(q,p); SETNODEPTR(pp,q); } sp = 1; r = NULL; } } --sp; } if (r != NULL) SETBLACK(r); } free (unchained); return retval; } /* Walk the nodes of a tree. ROOT is the root of the tree to be walked, ACTION the function to be called at each node. LEVEL is the level of ROOT in the whole tree. RET, the return level from ACTION, says if continue (TRUE) or break (FALSE), ie. due to budgeted traversal */ static void pm_trecurse (const void *vroot, pm_action_fn_t action, int level, void *extra) { int ret = TRUE; pm_const_node root = (pm_const_node) vroot; if (LEFT(root) == NULL && RIGHT(root) == NULL) { ret = (*action) (root, leaf, level, extra); } else { ret = (*action) (root, preorder, level, extra); if (!ret) goto exit_lane; if (LEFT(root) != NULL) pm_trecurse (LEFT(root), action, level + 1, extra); ret = (*action) (root, postorder, level, extra); if (!ret) goto exit_lane; if (RIGHT(root) != NULL) pm_trecurse (RIGHT(root), action, level + 1, extra); ret = (*action) (root, endorder, level, extra); if (!ret) goto exit_lane; } exit_lane: return; } /* Walk the nodes of a tree. ROOT is the root of the tree to be walked, ACTION the function to be called at each node. */ void pm_twalk (const void *vroot, pm_action_fn_t action, void *extra) { pm_const_node root = (pm_const_node) vroot; if (root != NULL && action != NULL) pm_trecurse (root, action, 0, extra); } /* The standardized functions miss an important functionality: the tree cannot be removed easily. We provide a function to do this. */ static void pm_tdestroy_recurse (pm_node root, pm_free_fn_t freefct) { if (LEFT(root) != NULL) pm_tdestroy_recurse (LEFT(root), freefct); if (RIGHT(root) != NULL) pm_tdestroy_recurse (RIGHT(root), freefct); (*freefct) ((void *) root->key); /* Free the node itself. */ free (root); } void __pm_tdestroy (void *vroot, pm_free_fn_t freefct) { pm_node root = (pm_node) vroot; if (root != NULL) pm_tdestroy_recurse (root, freefct); } /* For the used double hash method the table size has to be a prime. To correct the user given table size we need a prime test. This trivial algorithm is adequate because a) the code is (most probably) called a few times per program run and b) the number is small because the table must fit in the core */ static int pm_isprime(unsigned int number) { unsigned int div; /* no even number will be passed */ for (div = 3; div <= number / div; div += 2) { if (number % div == 0) return 0; } return 1; } /* Before using the hash table we must allocate memory for it. Test for an existing table are done. We allocate one element more as the found prime number says. This is done for more effective indexing as explained in the comment for the hsearch function. The contents of the table is zeroed, especially the field used becomes zero. */ int pm_hcreate(size_t nel, struct pm_htable *htab) { /* Test for correct arguments. */ if (htab == NULL) return 0; /* There is still another table active. Return with error. */ if (htab->table != NULL) return 0; /* We need a size of at least 3. Otherwise the hash functions we use will not work. */ if (nel < 3) nel = 3; /* Change nel to the first prime number in the range [nel, UINT_MAX - 2], The '- 2' means 'nel += 2' cannot overflow. */ for (nel |= 1; ; nel += 2) { if (UINT_MAX - 2 < nel) return 0; if (pm_isprime (nel)) break; } htab->size = nel; htab->filled = 0; /* allocate memory and zero out */ htab->table = (_pm_HENTRY *) calloc (htab->size + 1, sizeof (_pm_HENTRY)); if (htab->table == NULL) return 0; /* everything went alright */ return 1; } /* After using the hash table it has to be destroyed. The used memory can be freed and the local static variable can be marked as not used. */ void pm_hdestroy(struct pm_htable *htab) { size_t idx; /* Test for correct arguments. */ if (htab == NULL) return; for (idx = 0; idx < htab->size; idx++) __pm_hdelete(&htab->table[idx]); /* Free used memory. */ free (htab->table); /* the sign for an existing table is an value != NULL in htable */ htab->table = NULL; } /* This is the search function. It uses double hashing with open addressing. The argument item.key has to be a pointer to an zero terminated, most probably strings of chars. The function for generating a number of the strings is simple but fast. It can be replaced by a more complex function like ajw (see [Aho,Sethi,Ullman]) if the needs are shown. We use an trick to speed up the lookup. The table is created by hcreate with one more element available. This enables us to use the index zero special. This index will never be used because we store the first hash index in the field used where zero means not used. Every other value means used. The used field can be used as a first fast comparison for equality of the stored and the parameter value. This helps to prevent unnecessary more expensive calls of memcmp. */ int pm_hsearch(pm_HENTRY item, pm_ACTION action, pm_HENTRY **retval, struct pm_htable *htab) { unsigned int hval; unsigned int idx; /* Compute an value for the given string. Perhaps use a better method. */ hval = cache_crc32(item.key, item.keylen); /* First hash function: simply take the modul but prevent zero. */ idx = hval % htab->size + 1; if (htab->table[idx].used) { /* Further action might be required according to the action value. */ if (htab->table[idx].used == hval && item.keylen == htab->table[idx].entry.keylen && (!memcmp(item.key, htab->table[idx].entry.key, item.keylen))) { if (action == DELETE) { __pm_hdelete(&htab->table[idx]); (*retval) = NULL; } else { (*retval) = &htab->table[idx].entry; } return 1; } /* Second hash function, as suggested in [Knuth] */ unsigned int hval2 = 1 + hval % (htab->size - 2); unsigned int first_idx = idx; do { /* Because SIZE is prime this guarantees to step through all available indeces */ if (idx <= hval2) idx = htab->size + idx - hval2; else idx -= hval2; /* If we visited all entries leave the loop unsuccessfully. */ if (idx == first_idx) break; /* If entry is found use it. */ if (htab->table[idx].used == hval && item.keylen == htab->table[idx].entry.keylen && (!memcmp(item.key, htab->table[idx].entry.key, item.keylen))) { if (action == DELETE) { __pm_hdelete(&htab->table[idx]); (*retval) = NULL; } else { (*retval) = &htab->table[idx].entry; } return 1; } } while (htab->table[idx].used); } /* An empty bucket has been found. */ if (action == INSERT) { /* If table is full and another entry should be entered return with error. */ if (htab->filled == htab->size) { *retval = NULL; return ERR; } htab->table[idx].used = hval; htab->table[idx].entry = item; ++htab->filled; *retval = &htab->table[idx].entry; return 1; } *retval = NULL; return 0; } void pm_hmove(struct pm_htable *new_htab, struct pm_htable *old_htab, struct pm_htable *saved_htab) { memcpy(saved_htab, old_htab, sizeof(struct pm_htable)); memcpy(old_htab, new_htab, sizeof(struct pm_htable)); } void __pm_hdelete(_pm_HENTRY *item) { item->used = 0; item->entry.keylen = 0; free(item->entry.key); item->entry.key = NULL; if (item->entry.data) { free(item->entry.data); item->entry.data = NULL; } } pmacct-1.7.8/src/nfv9_template.c0000644000175000017500000015306014354105275015527 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "nfacctd.h" #include "pmacct-data.h" struct template_cache_entry *handle_template(struct template_hdr_v9 *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int16_t len, u_int32_t seq) { struct template_cache_entry *tpl = NULL; u_int8_t version = 0; if (pens) *pens = FALSE; if (tpl_type == 0 || tpl_type == 1) version = 9; else if (tpl_type == 2 || tpl_type == 3) version = 10; /* 0 NetFlow v9, 2 IPFIX */ if (tpl_type == 0 || tpl_type == 2) { if ((tpl = find_template(hdr->template_id, (struct sockaddr *) pptrs->f_agent, tpl_type, sid))) tpl = refresh_template(hdr, tpl, pptrs, tpl_type, sid, pens, version, len, seq); else tpl = insert_template(hdr, pptrs, tpl_type, sid, pens, version, len, seq); } /* 1 NetFlow v9, 3 IPFIX */ else if (tpl_type == 1 || tpl_type == 3) { if ((tpl = find_template(hdr->template_id, (struct sockaddr *) pptrs->f_agent, tpl_type, sid))) tpl = refresh_opt_template(hdr, tpl, pptrs, tpl_type, sid, pens, version, len, seq); else tpl = insert_opt_template(hdr, pptrs, tpl_type, sid, pens, version, len, seq); } return tpl; } u_int16_t modulo_template(u_int16_t template_id, struct sockaddr *agent, u_int16_t buckets) { return hash_status_table(ntohs(template_id), agent, buckets); } struct template_cache_entry *find_template(u_int16_t id, struct sockaddr *agent, u_int16_t tpl_type, u_int32_t sid) { struct template_cache_entry *ptr; u_int16_t modulo = modulo_template(id, agent, tpl_cache.num); ptr = tpl_cache.c[modulo]; while (ptr) { if ((ptr->template_id == id) && (!sa_addr_cmp((struct sockaddr *)agent, &ptr->agent)) && (ptr->source_id == sid)) return ptr; else ptr = ptr->next; } return NULL; } struct template_cache_entry *insert_template(struct template_hdr_v9 *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct template_cache_entry *ptr, *prevptr = NULL; struct template_field_v9 *field; u_int16_t modulo = modulo_template(hdr->template_id, (struct sockaddr *) pptrs->f_agent, tpl_cache.num); u_int16_t num = ntohs(hdr->num), type, port, off, count; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl; ptr = tpl_cache.c[modulo]; while (ptr) { prevptr = ptr; ptr = ptr->next; } ptr = malloc(sizeof(struct template_cache_entry)); if (!ptr) { Log(LOG_ERR, "ERROR ( %s/core ): insert_template(): unable to allocate new Data Template Cache Entry.\n", config.name); return NULL; } memset(ptr, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &ptr->agent, &port); ptr->source_id = sid; ptr->template_id = hdr->template_id; ptr->template_type = 0; ptr->num = num; log_template_header(ptr, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, version); count = off = 0; tpl = (u_char *) hdr; tpl += NfTplHdrV9Sz; off += NfTplHdrV9Sz; field = (struct template_field_v9 *)tpl; while (count < num) { if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "insert_template(): unable to read Data Template (too long)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; free(ptr); return NULL; } if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "insert_template(): unable to read Data Template (malformed)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; free(ptr); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(ptr->vlen, pen, type, ptr->len, ntohs(field->len), version); /* Let's determine if we use legacy template registry or the new template database (ie. if we have a PEN or high field value, >= 384) */ if (type < NF9_MAX_DEFINED_FIELD && !pen) { ptr->tpl[type].off = ptr->len; ptr->tpl[type].tpl_len = ntohs(field->len); if (ptr->vlen) ptr->tpl[type].off = 0; if (ptr->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { ptr->tpl[type].len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ptr->tpl[type].len = ptr->tpl[type].tpl_len; if (!ptr->vlen) ptr->len += ptr->tpl[type].len; } ptr->list[count].ptr = (char *) &ptr->tpl[type]; ptr->list[count].type = TPL_TYPE_LEGACY; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_ptr = ext_db_get_next_ie(ptr, type, &repeat_id); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = ptr->len; ext_db_ptr->tpl_len = ntohs(field->len); ext_db_ptr->repeat_id = repeat_id; if (ptr->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!ptr->vlen) ptr->len += ext_db_ptr->len; } } ptr->list[count].ptr = (char *) ext_db_ptr; ptr->list[count].type = TPL_TYPE_EXT_DB; } count++; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } if (prevptr) prevptr->next = ptr; else tpl_cache.c[modulo] = ptr; log_template_footer(ptr, ptr->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) save_template(ptr, config.nfacctd_templates_file); #endif return ptr; } #ifdef WITH_JANSSON void load_templates_from_file(char *path) { struct template_cache_entry *tpl, *prev_ptr = NULL, *ptr = NULL; FILE *tmp_file = fopen(path, "r"); char errbuf[SRVBUFLEN], tmpbuf[LARGEBUFLEN]; int line = 1; u_int16_t modulo; struct sockaddr_storage agent; if (!tmp_file) { Log(LOG_ERR, "ERROR ( %s/core ): [%s] load_templates_from_file(): unable to fopen(). File skipped.\n", config.name, path); return; } while (fgets(tmpbuf, LARGEBUFLEN, tmp_file)) { tpl = nfacctd_offline_read_json_template(tmpbuf, errbuf, SRVBUFLEN); if (tpl == NULL) { Log(LOG_WARNING, "WARN ( %s/core ): [%s:%u] %s\n", config.name, path, line, errbuf); } else { addr_to_sa((struct sockaddr *) &agent, &tpl->agent, 0); /* We assume the cache is empty when templates are loaded */ if (find_template(tpl->template_id, (struct sockaddr *) &agent, tpl->template_type, tpl->source_id)) { Log(LOG_WARNING, "WARN ( %s/core ): load_templates_from_file(): template %u already cached. Skipping.\n", config.name, tpl->template_id); } else { modulo = modulo_template(tpl->template_id, (struct sockaddr *) &agent, tpl_cache.num); ptr = tpl_cache.c[modulo]; while (ptr) { prev_ptr = ptr; ptr = ptr->next; } if (prev_ptr) prev_ptr->next = tpl; else tpl_cache.c[modulo] = tpl; Log(LOG_DEBUG, "DEBUG ( %s/core ): load_templates_from_file(): loaded template %u into cache.\n", config.name, tpl->template_id); } } prev_ptr = NULL; line++; } fclose(tmp_file); } void update_template_in_file(struct template_cache_entry *tpl, char *path) { FILE *tmp_file = fopen(path, "r"); char tmpbuf[LARGEBUFLEN], tpl_agent_str[INET6_ADDRSTRLEN]; const char *addr; int line = 0, tpl_found = 0; u_int16_t tpl_id, tpl_type; u_int32_t src_id; if (!tmp_file) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): unable to fopen(). File skipped.\n", config.name, path); return; } /* Find line where our template is stored */ while (fgets(tmpbuf, LARGEBUFLEN, tmp_file)) { json_error_t json_err; json_t *json_obj; json_obj = json_loads(tmpbuf, 0, &json_err); if (!json_obj) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): json_loads() error: %s. Line skipped.\n", config.name, path, json_err.text); continue; } else { if (!json_is_object(json_obj)) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): json_is_object() failed. Line skipped.\n", config.name, path); goto next_line; } else { json_t *json_tpl_id = json_object_get(json_obj, "template_id"); if (json_tpl_id == NULL) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): template ID null. Line skipped.\n", config.name, path); goto next_line; } else tpl_id = json_integer_value(json_tpl_id); json_t *json_agent = json_object_get(json_obj, "agent"); if (json_agent == NULL) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): agent null. Line skipped.\n", config.name, path); goto next_line; } else addr = json_string_value(json_agent); json_t *json_src_id = json_object_get(json_obj, "source_id"); if (json_src_id == NULL) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): source ID null. Line skipped.\n", config.name, path); goto next_line; } else src_id = json_integer_value(json_src_id); json_t *json_tpl_type = json_object_get(json_obj, "template_type"); if (json_tpl_type == NULL) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): template type null. Line skipped.\n", config.name, path); goto next_line; } else tpl_type = json_integer_value(json_tpl_type); } addr_to_str(tpl_agent_str, &tpl->agent); if (tpl_id == tpl->template_id && tpl_type == tpl->template_type && src_id == tpl->source_id && !strcmp(addr, tpl_agent_str)) { tpl_found = TRUE; json_decref(json_obj); break; } } next_line: json_decref(json_obj); line++; } if (!tpl_found) Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): Template %u not found.\n", config.name, path, tpl->template_id); else { if (delete_line_from_file(line, path) != 0) { Log(LOG_WARNING, "WARN ( %s/core ): [%s] update_template_in_file(): Error deleting old template. New version not saved.\n", config.name, path); } else { save_template(tpl, path); } } fclose(tmp_file); } void save_template(struct template_cache_entry *tpl, char *file) { FILE *tpl_file = open_output_file(config.nfacctd_templates_file, "a", TRUE); u_int16_t field_idx; char ip_addr[INET6_ADDRSTRLEN]; json_t *root = json_object(); json_t *list_array, *tpl_array; addr_to_str(ip_addr, &tpl->agent); json_object_set_new_nocheck(root, "agent", json_string(ip_addr)); json_object_set_new_nocheck(root, "source_id", json_integer(tpl->source_id)); json_object_set_new_nocheck(root, "template_id", json_integer(tpl->template_id)); json_object_set_new_nocheck(root, "template_type", json_integer(tpl->template_type)); json_object_set_new_nocheck(root, "num", json_integer(tpl->num)); json_object_set_new_nocheck(root, "len", json_integer(tpl->len)); /* Data template */ if (tpl->template_type == 0) { json_object_set_new_nocheck(root, "vlen", json_integer(tpl->vlen)); list_array = json_array(); for (field_idx = 0; field_idx < tpl->num; field_idx++) { json_t *json_tfl_field = json_object(); json_object_set_new_nocheck(json_tfl_field, "type", json_integer(tpl->list[field_idx].type)); /* idea: depending on tpl->list[field_idx].type, serialize either an otpl_field (if TPL_TYPE_LEGACY) or an utpl_field (if TPL_TYPE_EXT_DB) */ if (tpl->list[field_idx].type == TPL_TYPE_LEGACY){ struct otpl_field *otpl_field = (struct otpl_field *) tpl->list[field_idx].ptr; /* Where in tpl->tpl to insert the otpl_field when deserializing */ int tpl_index = (otpl_field - tpl->tpl); json_t *json_otpl_field = json_object(); json_object_set_new_nocheck(json_otpl_field, "off", json_integer(otpl_field->off)); json_object_set_new_nocheck(json_otpl_field, "len", json_integer(otpl_field->len)); json_object_set_new_nocheck(json_otpl_field, "tpl_len", json_integer(otpl_field->tpl_len)); json_object_set_new_nocheck(json_otpl_field, "tpl_index", json_integer(tpl_index)); json_object_set_new(json_tfl_field, "otpl", json_otpl_field); } else if (tpl->list[field_idx].type == TPL_TYPE_EXT_DB) { struct utpl_field *ext_db_ptr = (struct utpl_field *) tpl->list[field_idx].ptr; u_int16_t ext_db_modulo = (ext_db_ptr->type % TPL_EXT_DB_ENTRIES); /* Where in tpl->ext_db[ext_db_modulo].ie to insert the utpl_field when deserializing */ int ie_idx = (ext_db_ptr - tpl->ext_db[ext_db_modulo].ie); json_t *json_utpl_field = json_object(); json_object_set_new_nocheck(json_utpl_field, "pen", json_integer(ext_db_ptr->pen)); json_object_set_new_nocheck(json_utpl_field, "type", json_integer(ext_db_ptr->type)); json_object_set_new_nocheck(json_utpl_field, "off", json_integer(ext_db_ptr->off)); json_object_set_new_nocheck(json_utpl_field, "len", json_integer(ext_db_ptr->len)); json_object_set_new_nocheck(json_utpl_field, "tpl_len", json_integer(ext_db_ptr->tpl_len)); json_object_set_new_nocheck(json_utpl_field, "repeat_id", json_integer(ext_db_ptr->repeat_id)); json_object_set_new_nocheck(json_utpl_field, "ie_idx", json_integer(ie_idx)); json_object_set_new(json_tfl_field, "utpl", json_utpl_field); } json_array_append_new(list_array, json_tfl_field); } json_object_set_new(root, "list", list_array); } /* Options template */ else { tpl_array = json_array(); /* Fields with type >= NF9_MAX_DEFINED_FIELD are not serialized since they don't appear to be taken into account when receiving the template. */ for (field_idx = 0; field_idx < NF9_MAX_DEFINED_FIELD; field_idx++) { if (tpl->tpl[field_idx].off == 0 && tpl->tpl[field_idx].len == 0) continue; json_t *json_tpl_field = json_object(); json_object_set_new_nocheck(json_tpl_field, "type", json_integer(field_idx)); json_object_set_new_nocheck(json_tpl_field, "off", json_integer(tpl->tpl[field_idx].off)); json_object_set_new_nocheck(json_tpl_field, "len", json_integer(tpl->tpl[field_idx].len)); json_array_append_new(tpl_array, json_tpl_field); } json_object_set_new(root, "tpl", tpl_array); } /* NB: member `next` is willingly excluded from serialisation, since it would make more sense for it to be computed when de-serializing, to prevent the template cache from being corrupted. */ if (root) { write_and_free_json(tpl_file, root); Log(LOG_DEBUG, "DEBUG ( %s/core ): save_template(): saved template %u into file.\n", config.name, tpl->template_id); } close_output_file(tpl_file); } struct template_cache_entry *nfacctd_offline_read_json_template(char *buf, char *errbuf, int errlen) { struct template_cache_entry *ret = NULL; json_error_t json_err; json_t *json_obj = NULL, *json_tpl_id = NULL, *json_src_id = NULL, *json_tpl_type = NULL; json_t *json_num = NULL, *json_len = NULL, *json_agent = NULL, *json_list = NULL; const char *agent_str; json_obj = json_loads(buf, 0, &json_err); if (!json_obj) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): json_loads() error: %s. Line skipped.\n", json_err.text); } else { if (!json_is_object(json_obj)) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): json_is_object() failed. Line skipped.\n"); } else { ret = malloc(sizeof(struct template_cache_entry)); if (!ret) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): Unable to allocate enough memory for a new Template Cache Entry.\n"); goto exit_lane; } memset(ret, 0, sizeof(struct template_cache_entry)); json_tpl_id = json_object_get(json_obj, "template_id"); if (json_tpl_id == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): template ID null. Line skipped.\n"); goto exit_lane; } else ret->template_id = json_integer_value(json_tpl_id); json_src_id = json_object_get(json_obj, "source_id"); if (json_src_id == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): source ID null. Line skipped.\n"); goto exit_lane; } else ret->source_id = json_integer_value(json_src_id); json_tpl_type = json_object_get(json_obj, "template_type"); if (json_tpl_type == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): template type null. Line skipped.\n"); goto exit_lane; } else ret->template_type = json_integer_value(json_tpl_type); json_num = json_object_get(json_obj, "num"); if (json_num == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): num null. Line skipped.\n"); goto exit_lane; } else ret->num = json_integer_value(json_num); json_len = json_object_get(json_obj, "len"); if (json_len == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): len null. Line skipped.\n"); goto exit_lane; } else ret->len = json_integer_value(json_len); json_agent = json_object_get(json_obj, "agent"); agent_str = json_string_value(json_agent); if (!str_to_addr(agent_str, &ret->agent)) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): error creating agent.\n"); goto exit_lane; } /* Data template */ if (ret->template_type == 0) { json_t *json_vlen = json_object_get(json_obj, "vlen"); if (json_vlen == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): vlen null. Line skipped.\n"); goto exit_lane; } else ret->vlen = json_integer_value(json_vlen); json_list = json_object_get(json_obj, "list"); if (!json_is_array(json_list)) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): error parsing template fields list.\n"); } else { size_t key; json_t *value; int idx = 0; json_array_foreach(json_list, key, value) { if (json_integer_value(json_object_get(value, "type")) == TPL_TYPE_LEGACY) { json_t *json_otpl = NULL, *json_otpl_member = NULL; struct otpl_field otpl; int tpl_index = 0; ret->list[idx].type = TPL_TYPE_LEGACY; memset(&otpl, 0, sizeof (struct otpl_field)); json_otpl = json_object_get(value, "otpl"); if (json_otpl == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): otpl null. Line skipped.\n"); goto exit_lane; } json_otpl_member = json_object_get(json_otpl, "off"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): off null. Line skipped.\n"); goto exit_lane; } else otpl.off = json_integer_value(json_otpl_member); json_otpl_member = json_object_get(json_otpl, "len"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): len null. Line skipped.\n"); goto exit_lane; } else otpl.len = json_integer_value(json_otpl_member); json_otpl_member = json_object_get(json_otpl, "tpl_len"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): tpl_len null. Line skipped.\n"); goto exit_lane; } else otpl.tpl_len = json_integer_value(json_otpl_member); json_otpl_member = json_object_get(json_otpl, "tpl_index"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): tpl_index null. Line skipped.\n"); goto exit_lane; } else tpl_index = json_integer_value(json_otpl_member); memcpy(&ret->tpl[tpl_index], &otpl, sizeof(struct otpl_field)); ret->list[idx].ptr = (char *) &ret->tpl[tpl_index]; } else if (json_integer_value(json_object_get(value, "type")) == TPL_TYPE_EXT_DB) { json_t *json_utpl = NULL, *json_utpl_member = NULL; struct utpl_field utpl; int ie_idx = 0, modulo = 0; ret->list[idx].type = TPL_TYPE_EXT_DB; memset(&utpl, 0, sizeof(struct utpl_field)); json_utpl = json_object_get(value, "utpl"); if (json_utpl == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): utpl null. Line skipped.\n"); goto exit_lane; } json_utpl_member = json_object_get(json_utpl, "pen"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): pen null. Line skipped.\n"); goto exit_lane; } else utpl.pen = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "type"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): type null. Line skipped.\n"); goto exit_lane; } else utpl.type = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "off"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): off null. Line skipped.\n"); goto exit_lane; } else utpl.off = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "len"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): len null. Line skipped.\n"); goto exit_lane; } else utpl.len = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "tpl_len"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): tpl_len null. Line skipped.\n"); goto exit_lane; } else utpl.tpl_len = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "repeat_id"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): repeat_id null. Line skipped.\n"); goto exit_lane; } else utpl.repeat_id = json_integer_value(json_utpl_member); json_utpl_member = json_object_get(json_utpl, "ie_idx"); if (json_utpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): ie_idx null. Line skipped.\n"); goto exit_lane; } else ie_idx = json_integer_value(json_utpl_member); modulo = (utpl.type % TPL_EXT_DB_ENTRIES); memcpy(&ret->ext_db[modulo].ie[ie_idx], &utpl, sizeof(struct utpl_field)); ret->list[idx].ptr = (char *) &ret->ext_db[modulo].ie[ie_idx]; } else { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): incorrect field type. Line skipped.\n"); goto exit_lane; } idx++; } } } /* Options template */ else { json_t *json_tpl = json_object_get(json_obj, "tpl"); if (!json_is_array(json_tpl)) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): error parsing template fields list.\n"); } else { size_t key; json_t *value; int tpl_idx = 0; json_array_foreach(json_tpl, key, value) { struct otpl_field otpl; memset(&otpl, 0, sizeof (struct otpl_field)); json_t *json_otpl_member = json_object_get(value, "type"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): type null. Line skipped.\n"); goto exit_lane; } else tpl_idx = json_integer_value(json_otpl_member); json_otpl_member = json_object_get(value, "off"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): off null. Line skipped.\n"); goto exit_lane; } else otpl.off = json_integer_value(json_otpl_member); json_otpl_member = json_object_get(value, "len"); if (json_otpl_member == NULL) { snprintf(errbuf, errlen, "nfacctd_offline_read_json_template(): len null. Line skipped.\n"); goto exit_lane; } else otpl.len = json_integer_value(json_otpl_member); memcpy(&ret->tpl[tpl_idx], &otpl, sizeof(struct otpl_field)); } } } } json_decref(json_obj); } return ret; exit_lane: json_decref(json_obj); if (ret) free(ret); return NULL; } #else void load_templates_from_file(char *path) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core ): load_templates_from_file(): JSON object not created due to missing --enable-jansson\n", config.name); } void update_template_in_file(struct template_cache_entry *tpl, char *path) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core ): update_template_in_file(): JSON object not created due to missing --enable-jansson\n", config.name); } void save_template(struct template_cache_entry *tpl, char *file) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core ): save_template(): JSON object not created due to missing --enable-jansson\n", config.name); } struct template_cache_entry *nfacctd_offline_read_json_template(char *buf, char *errbuf, int errlen) { if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/core ): nfacctd_offline_read_json_template(): JSON object not created due to missing --enable-jansson\n", config.name); return NULL; } #endif struct template_cache_entry *refresh_template(struct template_hdr_v9 *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct template_cache_entry backup, *next; struct template_field_v9 *field; u_int16_t count, num = ntohs(hdr->num), type, port, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *ptr; next = tpl->next; memcpy(&backup, tpl, sizeof(struct template_cache_entry)); memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = hdr->template_id; tpl->template_type = 0; tpl->num = num; tpl->next = next; log_template_header(tpl, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, version); count = off = 0; ptr = (u_char *) hdr; ptr += NfTplHdrV9Sz; off += NfTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count < num) { if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "refresh_template(): unable to read Data Template (too long)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; return NULL; } if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "refresh_template(): unable to read Data Template (malformed)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; memcpy(tpl, &backup, sizeof(struct template_cache_entry)); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(tpl->vlen, pen, type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].tpl_len = ntohs(field->len); if (tpl->vlen) tpl->tpl[type].off = 0; if (tpl->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { tpl->tpl[type].len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { tpl->tpl[type].len = tpl->tpl[type].tpl_len; if (!tpl->vlen) tpl->len += tpl->tpl[type].len; } tpl->list[count].ptr = (char *) &tpl->tpl[type]; tpl->list[count].type = TPL_TYPE_LEGACY; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_ptr = ext_db_get_next_ie(tpl, type, &repeat_id); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = tpl->len; ext_db_ptr->tpl_len = ntohs(field->len); ext_db_ptr->repeat_id = repeat_id; if (tpl->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!tpl->vlen) tpl->len += ext_db_ptr->len; } } tpl->list[count].ptr = (char *) ext_db_ptr; tpl->list[count].type = TPL_TYPE_EXT_DB; } count++; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } log_template_footer(tpl, tpl->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) update_template_in_file(tpl, config.nfacctd_templates_file); #endif return tpl; } void log_template_header(struct template_cache_entry *tpl, struct sockaddr *agent, u_int16_t tpl_type, u_int32_t sid, u_int8_t version) { struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr(agent, &a, &agent_port); addr_to_str(agent_addr, &a); Log(LOG_DEBUG, "DEBUG ( %s/core ): NfV%u agent : %s:%u\n", config.name, version, agent_addr, sid); Log(LOG_DEBUG, "DEBUG ( %s/core ): NfV%u template type : %s\n", config.name, version, ( tpl->template_type == 0 || tpl->template_type == 2 ) ? "flow" : "options"); Log(LOG_DEBUG, "DEBUG ( %s/core ): NfV%u template ID : %u\n", config.name, version, ntohs(tpl->template_id)); Log(LOG_DEBUG, "DEBUG ( %s/core ): -------------------------------------------------------------\n", config.name); Log(LOG_DEBUG, "DEBUG ( %s/core ): | pen | field type | offset | size |\n", config.name); } void log_template_field(u_int8_t vlen, u_int32_t *pen, u_int16_t type, u_int16_t off, u_int16_t len, u_int8_t version) { if (!pen) { if (type <= MAX_TPL_DESC_LIST && strlen(tpl_desc_list[type])) { if (!off && vlen) Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18s [%-5u] | %6s | %6u |\n", config.name, 0, tpl_desc_list[type], type, "tbd", len); else Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18s [%-5u] | %6u | %6u |\n", config.name, 0, tpl_desc_list[type], type, off, len); } else { if (!off && vlen) Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6s | %6u |\n", config.name, 0, type, type, "tbd", len); else Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6u | %6u |\n", config.name, 0, type, type, off, len); } } else { if (!off && vlen) Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6s | %6u |\n", config.name, ntohl(*pen), type, type, "tbd", len); else Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6u | %6u |\n", config.name, ntohl(*pen), type, type, off, len); } } void log_opt_template_field(u_int8_t vlen, u_int32_t *pen, u_int16_t type, u_int16_t off, u_int16_t len, u_int8_t version) { if (!pen) { if (type <= MAX_OPT_TPL_DESC_LIST && strlen(opt_tpl_desc_list[type])) Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18s [%-5u] | %6u | %6u |\n", config.name, 0, opt_tpl_desc_list[type], type, off, len); else Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6u | %6u |\n", config.name, 0, type, type, off, len); } else Log(LOG_DEBUG, "DEBUG ( %s/core ): | %-10u | %-18u [%-5u] | %6u | %6u |\n", config.name, ntohl(*pen), type, type, off, len); } void log_template_footer(struct template_cache_entry *tpl, u_int16_t size, u_int8_t version) { Log(LOG_DEBUG, "DEBUG ( %s/core ): -------------------------------------------------------------\n", config.name); if (!size) Log(LOG_DEBUG, "DEBUG ( %s/core ): Netflow V9/IPFIX record size : %s\n", config.name, "tbd"); else Log(LOG_DEBUG, "DEBUG ( %s/core ): Netflow V9/IPFIX record size : %u\n", config.name, size); Log(LOG_DEBUG, "DEBUG ( %s/core ): \n", config.name); } struct template_cache_entry *insert_opt_template(void *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry *ptr, *prevptr = NULL; struct template_field_v9 *field; u_int16_t modulo, count, slen, olen, type, port, tid, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl; /* NetFlow v9 */ if (tpl_type == 1) { modulo = modulo_template(hdr_v9->template_id, (struct sockaddr *) pptrs->f_agent, tpl_cache.num); tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { modulo = modulo_template(hdr_v10->template_id, (struct sockaddr *) pptrs->f_agent, tpl_cache.num); tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } else { Log(LOG_ERR, "ERROR ( %s/core ): Unknown template type (%u).\n", config.name, tpl_type); return NULL; } ptr = tpl_cache.c[modulo]; while (ptr) { prevptr = ptr; ptr = ptr->next; } ptr = malloc(sizeof(struct template_cache_entry)); if (!ptr) { Log(LOG_ERR, "ERROR ( %s/core ): insert_opt_template(): unable to allocate new Options Template Cache Entry.\n", config.name); return NULL; } memset(ptr, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &ptr->agent, &port); ptr->source_id = sid; ptr->template_id = tid; ptr->template_type = 1; ptr->num = olen+slen; log_template_header(ptr, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, version); off = 0; count = ptr->num; tpl = (u_char *) hdr; tpl += NfOptTplHdrV9Sz; off += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)tpl; while (count) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "insert_opt_template(): unable to read Options Template Flowset (malformed)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; free(ptr); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_opt_template_field(FALSE, pen, type, ptr->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { ptr->tpl[type].off = ptr->len; ptr->tpl[type].len = ntohs(field->len); ptr->len += ptr->tpl[type].len; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_ptr = ext_db_get_next_ie(ptr, type, &repeat_id); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = ptr->len; ext_db_ptr->tpl_len = ntohs(field->len); ext_db_ptr->repeat_id = repeat_id; ext_db_ptr->len = ext_db_ptr->tpl_len; } if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "insert_opt_template(): unable to read Options Template (too long)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; free(ptr); return NULL; } ptr->list[count].ptr = (char *) ext_db_ptr; ptr->list[count].type = TPL_TYPE_EXT_DB; ptr->len += ext_db_ptr->len; } count--; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } if (prevptr) prevptr->next = ptr; else tpl_cache.c[modulo] = ptr; log_template_footer(ptr, ptr->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) save_template(ptr, config.nfacctd_templates_file); #endif return ptr; } struct template_cache_entry *refresh_opt_template(void *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry backup, *next; struct template_field_v9 *field; u_int16_t slen, olen, count, type, port, tid, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *ptr; /* NetFlow v9 */ if (tpl_type == 1) { tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } else { Log(LOG_ERR, "ERROR ( %s/core ): Unknown template type (%u).\n", config.name, tpl_type); return NULL; } next = tpl->next; memcpy(&backup, tpl, sizeof(struct template_cache_entry)); memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = tid; tpl->template_type = 1; tpl->num = olen+slen; tpl->next = next; log_template_header(tpl, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, version); off = 0; count = tpl->num; ptr = (u_char *) hdr; ptr += NfOptTplHdrV9Sz; off += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "refresh_opt_template(): unable to read Options Template Flowset (malformed)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; memcpy(tpl, &backup, sizeof(struct template_cache_entry)); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_opt_template_field(FALSE, pen, type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].len = ntohs(field->len); tpl->len += tpl->tpl[type].len; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_ptr = ext_db_get_next_ie(tpl, type, &repeat_id); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = tpl->len; ext_db_ptr->tpl_len = ntohs(field->len); ext_db_ptr->repeat_id = repeat_id; ext_db_ptr->len = ext_db_ptr->tpl_len; } if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "refresh_opt_template: unable to read Options Template (too long)", (struct sockaddr *) pptrs->f_agent, seq); xflow_status_table.tot_bad_datagrams++; return NULL; } tpl->list[count].ptr = (char *) ext_db_ptr; tpl->list[count].type = TPL_TYPE_EXT_DB; tpl->len += ext_db_ptr->len; } count--; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } log_template_footer(tpl, tpl->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) update_template_in_file(tpl, config.nfacctd_templates_file); #endif return tpl; } int resolve_vlen_template(u_char *ptr, u_int16_t remlen, struct template_cache_entry *tpl) { struct otpl_field *otpl_ptr; struct utpl_field *utpl_ptr; u_int16_t idx = 0, len = 0; u_int8_t vlen = 0, add_len; int ret; while (idx < tpl->num) { add_len = 0; if (tpl->list[idx].type == TPL_TYPE_LEGACY) { otpl_ptr = (struct otpl_field *) tpl->list[idx].ptr; if (vlen) otpl_ptr->off = len; if (otpl_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { vlen = TRUE; ret = get_ipfix_vlen(ptr+len, remlen - len, &otpl_ptr->len); if (ret > 0) add_len = ret; else return ERR; otpl_ptr->off = (len + add_len); } len += (otpl_ptr->len + add_len); } else if (tpl->list[idx].type == TPL_TYPE_EXT_DB) { utpl_ptr = (struct utpl_field *) tpl->list[idx].ptr; if (vlen) utpl_ptr->off = len; if (utpl_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { vlen = TRUE; ret = get_ipfix_vlen(ptr+len, remlen - len, &utpl_ptr->len); if (ret > 0) add_len = ret; else return ERR; utpl_ptr->off = (len + add_len); } len += (utpl_ptr->len + add_len); } /* if len is invalid (ie. greater than flowsetlen), we stop here */ if (len > remlen) return ERR; idx++; } tpl->len = len; return SUCCESS; } int get_ipfix_vlen(u_char *base, u_int16_t remlen, u_int16_t *len) { u_char *ptr = base; u_int8_t *len8, ret = 0; u_int16_t *len16; if (ptr && len) { if (remlen >= 1) { len8 = (u_int8_t *) ptr; if ((*len8) < 255) { ret = 1; (*len) = (*len8); } else { if (remlen >= 3) { ptr++; len16 = (u_int16_t *) ptr; ret = 3; (*len) = ntohs(*len16); } else ret = ERR; } } else ret = ERR; } return ret; } struct utpl_field *ext_db_get_ie(struct template_cache_entry *ptr, u_int32_t pen, u_int16_t type, u_int8_t repeat_id) { u_int16_t ie_idx, ext_db_modulo = (type % TPL_EXT_DB_ENTRIES); struct utpl_field *ext_db_ptr = NULL; for (ie_idx = 0; ie_idx < IES_PER_TPL_EXT_DB_ENTRY; ie_idx++) { if (ptr->ext_db[ext_db_modulo].ie[ie_idx].type == type && ptr->ext_db[ext_db_modulo].ie[ie_idx].pen == pen && ptr->ext_db[ext_db_modulo].ie[ie_idx].repeat_id == repeat_id) { ext_db_ptr = &ptr->ext_db[ext_db_modulo].ie[ie_idx]; break; } } return ext_db_ptr; } struct utpl_field *ext_db_get_next_ie(struct template_cache_entry *ptr, u_int16_t type, u_int8_t *repeat_id) { u_int16_t ie_idx, ext_db_modulo = (type % TPL_EXT_DB_ENTRIES); struct utpl_field *ext_db_ptr = NULL; (*repeat_id) = 0; for (ie_idx = 0; ie_idx < IES_PER_TPL_EXT_DB_ENTRY; ie_idx++) { if (ptr->ext_db[ext_db_modulo].ie[ie_idx].type == type) (*repeat_id)++; if (ptr->ext_db[ext_db_modulo].ie[ie_idx].type == 0) { ext_db_ptr = &ptr->ext_db[ext_db_modulo].ie[ie_idx]; break; } } return ext_db_ptr; } u_int16_t calc_template_keylen() { return (sizeof(u_int16_t /* template id */) + sizeof(u_int32_t /* source id */) + sizeof(struct sockaddr_storage /* sender IP */)); } struct template_cache_entry *compose_template(struct template_hdr_v9 *hdr, struct sockaddr *agent, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct template_cache_entry *tpl; struct template_field_v9 *field; u_int16_t num = ntohs(hdr->num), type, port, off, count; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl_ptr; tpl = malloc(sizeof(struct template_cache_entry)); if (!tpl) { Log(LOG_ERR, "ERROR ( %s/core ): compose_template(): unable to allocate new Data Template Cache Entry.\n", config.name); return NULL; } memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr(agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = hdr->template_id; tpl->template_type = 0; tpl->num = num; log_template_header(tpl, agent, tpl_type, sid, version); count = off = 0; tpl_ptr = (u_char *) hdr; tpl_ptr += NfTplHdrV9Sz; off += NfTplHdrV9Sz; field = (struct template_field_v9 *)tpl_ptr; while (count < num) { if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "compose_template(): unable to read Data Template (too long)", agent, seq); xflow_status_table.tot_bad_datagrams++; free(tpl); return NULL; } if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "compose_template(): unable to read Data Template (malformed)", agent, seq); xflow_status_table.tot_bad_datagrams++; free(tpl); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(tpl->vlen, pen, type, tpl->len, ntohs(field->len), version); /* Let's determine if we use legacy template registry or the new template database (ie. if we have a PEN or high field value, >= 384) */ if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].tpl_len = ntohs(field->len); if (tpl->vlen) tpl->tpl[type].off = 0; if (tpl->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { tpl->tpl[type].len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { tpl->tpl[type].len = tpl->tpl[type].tpl_len; if (!tpl->vlen) tpl->len += tpl->tpl[type].len; } tpl->list[count].ptr = (char *) &tpl->tpl[type]; tpl->list[count].type = TPL_TYPE_LEGACY; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_tpl = ext_db_get_next_ie(tpl, type, &repeat_id); if (ext_db_tpl) { if (pen) ext_db_tpl->pen = ntohl(*pen); ext_db_tpl->type = type; ext_db_tpl->off = tpl->len; ext_db_tpl->tpl_len = ntohs(field->len); ext_db_tpl->repeat_id = repeat_id; if (tpl->vlen) ext_db_tpl->off = 0; if (ext_db_tpl->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_tpl->len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { ext_db_tpl->len = ext_db_tpl->tpl_len; if (!tpl->vlen) tpl->len += ext_db_tpl->len; } } tpl->list[count].ptr = (char *) ext_db_tpl; tpl->list[count].type = TPL_TYPE_EXT_DB; } count++; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } log_template_footer(tpl, tpl->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) save_template(tpl, config.nfacctd_templates_file); #endif return tpl; } struct template_cache_entry *compose_opt_template(void *hdr, struct sockaddr *agent, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len, u_int32_t seq) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry *tpl; struct template_field_v9 *field; u_int16_t count, slen, olen, type, port, tid, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl_ptr; /* NetFlow v9 */ if (tpl_type == 1) { tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } else { Log(LOG_ERR, "ERROR ( %s/core ): Unknown template type (%u).\n", config.name, tpl_type); return NULL; } tpl = malloc(sizeof(struct template_cache_entry)); if (!tpl) { Log(LOG_ERR, "ERROR ( %s/core ): insert_opt_template(): unable to allocate new Options Template Cache Entry.\n", config.name); return NULL; } memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr(agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = tid; tpl->template_type = 1; tpl->num = olen+slen; log_template_header(tpl, agent, tpl_type, sid, version); off = 0; count = tpl->num; tpl_ptr = (u_char *) hdr; tpl_ptr += NfOptTplHdrV9Sz; off += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)tpl_ptr; while (count) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO", "insert_opt_template(): unable to read Options Template Flowset (malformed)", agent, seq); xflow_status_table.tot_bad_datagrams++; free(tpl); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_opt_template_field(FALSE, pen, type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].len = ntohs(field->len); tpl->len += tpl->tpl[type].len; } else { u_int8_t repeat_id = 0; struct utpl_field *ext_db_tpl = ext_db_get_next_ie(tpl, type, &repeat_id); if (ext_db_tpl) { if (pen) ext_db_tpl->pen = ntohl(*pen); ext_db_tpl->type = type; ext_db_tpl->off = tpl->len; ext_db_tpl->tpl_len = ntohs(field->len); ext_db_tpl->repeat_id = repeat_id; ext_db_tpl->len = ext_db_tpl->tpl_len; } if (count >= TPL_LIST_ENTRIES) { notify_malf_packet(LOG_INFO, "INFO", "insert_opt_template(): unable to read Options Template (too long)", agent, seq); xflow_status_table.tot_bad_datagrams++; free(tpl); return NULL; } tpl->list[count].ptr = (char *) ext_db_tpl; tpl->list[count].type = TPL_TYPE_EXT_DB; tpl->len += ext_db_tpl->len; } count--; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } log_template_footer(tpl, tpl->len, version); #ifdef WITH_JANSSON if (config.nfacctd_templates_file) save_template(tpl, config.nfacctd_templates_file); #endif return tpl; } u_char *compose_template_key(pm_hash_serial_t *ser, u_int16_t template_id, struct sockaddr *agent, u_int32_t source_id) { pm_hash_key_t *hash_key; u_int16_t hash_keylen; hash_keylen = calc_template_keylen(); hash_init_serial(ser, hash_keylen); hash_serial_append(ser, (char *)&template_id, sizeof(template_id), FALSE); hash_serial_append(ser, (char *)&source_id, sizeof(source_id), TRUE); hash_serial_append(ser, (char *)agent, sizeof(struct sockaddr_storage), TRUE); hash_key = hash_serial_get_key(ser); return hash_key_get_val(hash_key); } struct template_cache_entry *handle_template_v2(struct template_hdr_v9 *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int16_t len, u_int32_t seq) { struct template_cache_entry *tpl = NULL; u_int8_t version = 0; int ret; pm_hash_serial_t hash_serializer; u_char *hash_keyval; if (pens) { *pens = FALSE; } if (tpl_type == 0 || tpl_type == 1) { version = 9; } else if (tpl_type == 2 || tpl_type == 3) { version = 10; } hash_keyval = compose_template_key(&hash_serializer, hdr->template_id, (struct sockaddr *)pptrs->f_agent, sid); /* 0 NetFlow v9, 2 IPFIX */ if (tpl_type == 0 || tpl_type == 2) { tpl = compose_template(hdr, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, pens, version, len, seq); ret = cdada_map_insert_replace(tpl_data_map, hash_keyval, tpl); if (ret != CDADA_SUCCESS) { Log(LOG_WARNING, "WARN ( %s/core ): Unable to insert / refresh template in tpl_data_map\n", config.name); goto exit_lane; } } /* 1 NetFlow v9, 3 IPFIX */ else if (tpl_type == 1 || tpl_type == 3) { tpl = compose_opt_template(hdr, (struct sockaddr *)pptrs->f_agent, tpl_type, sid, pens, version, len, seq); ret = cdada_map_insert_replace(tpl_data_map, hash_keyval, tpl); if (ret != CDADA_SUCCESS) { Log(LOG_WARNING, "WARN ( %s/core ): Unable to insert / refresh template in tpl_opt_map\n", config.name); goto exit_lane; } } exit_lane: /* freeing hash key */ hash_destroy_serial(&hash_serializer); return tpl; } pmacct-1.7.8/src/telemetry/0000755000175000017500000000000014354105416014610 5ustar paolopaolopmacct-1.7.8/src/telemetry/telemetry_logdump.h0000644000175000017500000000451314354105275020530 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TELEMETRY_LOGDUMP_H #define TELEMETRY_LOGDUMP_H /* includes */ /* defines */ /* prototypes */ extern void telemetry_log_seq_init(u_int64_t *); extern void telemetry_log_seq_increment(u_int64_t *); extern u_int64_t telemetry_log_seq_get(u_int64_t *); extern void telemetry_log_seq_set(u_int64_t *, u_int64_t); extern int telemetry_log_seq_has_ro_bit(u_int64_t *); extern int telemetry_peer_log_init(telemetry_peer *, telemetry_tag_t *, int, int); extern void telemetry_peer_log_dynname(char *, int, char *, telemetry_peer *); extern int telemetry_log_msg(telemetry_peer *, struct telemetry_data *, telemetry_tag_t *, void *, u_int32_t, int, u_int64_t, char *, int); extern int telemetry_peer_dump_init(telemetry_peer *, telemetry_tag_t *, int, int); extern int telemetry_peer_dump_close(telemetry_peer *, telemetry_tag_t *, int, int); extern void telemetry_dump_init_peer(telemetry_peer *); extern void telemetry_dump_se_ll_destroy(telemetry_dump_se_ll *); extern void telemetry_dump_se_ll_append(telemetry_peer *, struct telemetry_data *, int); extern void telemetry_handle_dump_event(struct telemetry_data *, int); extern int telemetry_dump_event_runner(struct pm_dump_runner *); extern void telemetry_daemon_msglog_init_amqp_host(); extern void telemetry_dump_init_amqp_host(void *); extern int telemetry_daemon_msglog_init_kafka_host(); extern int telemetry_dump_init_kafka_host(void *); #if defined WITH_JANSSON extern void telemetry_tag_print_json(json_t *, telemetry_tag_t *); #endif #endif //TELEMETRY_LOGDUMP_H pmacct-1.7.8/src/telemetry/telemetry_msg.c0000644000175000017500000002441414354105275017644 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "telemetry.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined WITH_ZMQ #include "zmq_common.h" #endif /* Functions */ void telemetry_process_data(telemetry_peer *peer, struct telemetry_data *t_data, int data_decoder) { telemetry_misc_structs *tms; if (!peer || !t_data) return; tms = bgp_select_misc_db(peer->type); if (!tms) return; if (tms->msglog_backend_methods) { char event_type[] = "log"; if (!telemetry_validate_input_output_decoders(data_decoder, config.telemetry_msglog_output)) { telemetry_log_msg(peer, t_data, &telemetry_logdump_tag, peer->buf.base, peer->msglen, data_decoder, telemetry_log_seq_get(&tms->log_seq), event_type, config.telemetry_msglog_output); } } if (tms->dump_backend_methods) { if (!telemetry_validate_input_output_decoders(data_decoder, config.telemetry_dump_output)) { telemetry_dump_se_ll_append(peer, t_data, data_decoder); } } if (tms->msglog_backend_methods || tms->dump_backend_methods) telemetry_log_seq_increment(&tms->log_seq); } #if defined WITH_ZMQ int telemetry_recv_zmq_generic(telemetry_peer *peer, u_int32_t len) { int ret = 0; ret = p_zmq_recv_bin(&telemetry_zmq_host.sock, peer->buf.base, peer->buf.tot_len); if (ret > 0) { peer->stats.packet_bytes += ret; peer->msglen = ret; } return ret; } #endif #if defined WITH_KAFKA int telemetry_recv_kafka_generic(telemetry_peer *peer, u_int32_t len) { int ret = 0; ret = p_kafka_consume_data(&telemetry_kafka_host, peer->buf.kafka_msg, (u_char *)peer->buf.base, peer->buf.tot_len); if (ret > 0) { peer->stats.packet_bytes += ret; peer->msglen = ret; } peer->buf.kafka_msg = NULL; return ret; } #endif int telemetry_recv_generic(telemetry_peer *peer, u_int32_t len) { int ret = 0; if (!len) { ret = recv(peer->fd, &peer->buf.base[peer->buf.cur_len], (peer->buf.tot_len - peer->buf.cur_len), 0); } else { if (len <= (peer->buf.tot_len - peer->buf.cur_len)) { ret = pm_recv(peer->fd, &peer->buf.base[peer->buf.cur_len], len, MSG_WAITALL, DEFAULT_SLOTH_SLEEP_TIME); } } if (ret > 0) { peer->stats.packet_bytes += ret; peer->msglen = (ret + peer->buf.cur_len); } return ret; } void telemetry_basic_process_json(telemetry_peer *peer) { if (config.telemetry_decoder_id == TELEMETRY_DECODER_CISCO_V0 && config.telemetry_port_udp) { peer->msglen -= TELEMETRY_CISCO_HDR_LEN_V0; memmove(peer->buf.base, &peer->buf.base[TELEMETRY_CISCO_HDR_LEN_V0], peer->msglen); } else if (config.telemetry_decoder_id == TELEMETRY_DECODER_CISCO_V1 && config.telemetry_port_udp) { peer->msglen -= TELEMETRY_CISCO_HDR_LEN_V1; memmove(peer->buf.base, &peer->buf.base[TELEMETRY_CISCO_HDR_LEN_V1], peer->msglen); } peer->buf.base[peer->msglen] = '\0'; } int telemetry_recv_json(telemetry_peer *peer, u_int32_t len, int *flags) { int ret = 0; if (!flags) return ret; (*flags) = FALSE; if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { ret = telemetry_recv_generic(peer, len); } #if defined WITH_ZMQ else if (zmq_input) { ret = telemetry_recv_zmq_generic(peer, len); } #endif #if defined WITH_KAFKA else if (kafka_input) { ret = telemetry_recv_kafka_generic(peer, len); } #endif telemetry_basic_process_json(peer); if (ret) (*flags) = telemetry_basic_validate_json(peer); return ret; } int telemetry_recv_gpb(telemetry_peer *peer, u_int32_t len) { int ret = 0; ret = telemetry_recv_generic(peer, len); return ret; } int telemetry_recv_cisco_v0(telemetry_peer *peer, int *flags, int *data_decoder) { int ret = 0; u_int32_t type, len; if (!flags || !data_decoder) return ret; *flags = FALSE; *data_decoder = TELEMETRY_DATA_DECODER_UNKNOWN; ret = telemetry_recv_generic(peer, TELEMETRY_CISCO_HDR_LEN_V0); if (ret == TELEMETRY_CISCO_HDR_LEN_V0) { type = telemetry_cisco_hdr_v0_get_type(peer); len = telemetry_cisco_hdr_v0_get_len(peer); /* MSG_WAITALL does not apply to UDP */ if (config.telemetry_port_udp) len = 0; ret = telemetry_recv_cisco(peer, flags, data_decoder, type, len); } return ret; } int telemetry_recv_cisco_v1(telemetry_peer *peer, int *flags, int *data_decoder) { int ret = 0; u_int32_t type, len, encap; if (!flags || !data_decoder) return ret; *flags = FALSE; *data_decoder = TELEMETRY_DATA_DECODER_UNKNOWN; ret = telemetry_recv_generic(peer, TELEMETRY_CISCO_HDR_LEN_V1); if (ret == TELEMETRY_CISCO_HDR_LEN_V1) { type = telemetry_cisco_hdr_v1_get_type(peer); len = telemetry_cisco_hdr_v1_get_len(peer); encap = telemetry_cisco_hdr_v1_get_encap(peer); /* MSG_WAITALL does not apply to UDP */ if (config.telemetry_port_udp) len = 0; if (type == TELEMETRY_CISCO_V1_TYPE_DATA) { switch (encap) { case TELEMETRY_CISCO_V1_ENCAP_GPB: case TELEMETRY_CISCO_V1_ENCAP_GPV_CPT: encap = TELEMETRY_CISCO_GPB_COMPACT; break; case TELEMETRY_CISCO_V1_ENCAP_GPB_KV: encap = TELEMETRY_CISCO_GPB_KV; break; case TELEMETRY_CISCO_V1_ENCAP_JSON: encap = TELEMETRY_CISCO_JSON; break; default: return ret; } ret = telemetry_recv_cisco(peer, flags, data_decoder, encap, len); } } return ret; } int telemetry_recv_cisco(telemetry_peer *peer, int *flags, int *data_decoder, u_int32_t type, u_int32_t len) { int ret = 0; switch (type) { case TELEMETRY_CISCO_RESET_COMPRESSOR: ret = telemetry_recv_jump(peer, len, flags); (*data_decoder) = TELEMETRY_DATA_DECODER_UNKNOWN; /* XXX: JSON instead? */ break; case TELEMETRY_CISCO_JSON: ret = telemetry_recv_json(peer, len, flags); if (config.tmp_telemetry_decode_cisco_v1_json_string) { (*data_decoder) = TELEMETRY_DATA_DECODER_JSON_STRING; } else { (*data_decoder) = TELEMETRY_DATA_DECODER_JSON; } break; case TELEMETRY_CISCO_GPB_COMPACT: ret = telemetry_recv_generic(peer, len); (*data_decoder) = TELEMETRY_DATA_DECODER_GPB; break; case TELEMETRY_CISCO_GPB_KV: ret = telemetry_recv_generic(peer, len); (*data_decoder) = TELEMETRY_DATA_DECODER_GPB; break; default: ret = telemetry_recv_jump(peer, len, flags); (*data_decoder) = TELEMETRY_DATA_DECODER_UNKNOWN; break; } return ret; } int telemetry_recv_jump(telemetry_peer *peer, u_int32_t len, int *flags) { int ret = 0; if (!flags) return ret; ret = telemetry_recv_generic(peer, len); (*flags) = ERR; return ret; } int telemetry_basic_validate_json(telemetry_peer *peer) { if (peer->buf.base[peer->buf.cur_len] != '{') { peer->stats.msg_errors++; return ERR; } else return FALSE; } #if defined (WITH_JANSSON) int telemetry_decode_producer_peer(struct telemetry_data *t_data, void *h, u_char *buf, size_t buflen, struct sockaddr *addr, socklen_t *addr_len) { json_t *json_obj = NULL, *telemetry_node_json, *telemetry_node_port_json; json_error_t json_err; struct host_addr telemetry_node; u_int16_t telemetry_node_port = 0; int bytes = 0, ret = SUCCESS; if (!buf || !buflen || !addr || !addr_len) return ERR; #if defined WITH_ZMQ if (zmq_input) { struct p_zmq_host *zmq_host = h; bytes = p_zmq_recv_bin(&zmq_host->sock, buf, buflen); } #endif #if defined WITH_KAFKA else if (kafka_input) { struct p_kafka_host *kafka_host = h; bytes = p_kafka_consume_data(kafka_host, t_data->kafka_msg, buf, buflen); } #endif if (bytes > 0) { buf[bytes] = '\0'; json_obj = json_loads((char *)buf, 0, &json_err); if (json_obj) { if (!json_is_object(json_obj)) { Log(LOG_WARNING, "WARN ( %s/%s ): telemetry_decode_producer_peer(): json_is_object() failed.\n", config.name, t_data->log_str); ret = ERR; goto exit_lane; } else { /* v1 */ telemetry_node_json = json_object_get(json_obj, "telemetry_node"); /* v2, v3 */ if (!telemetry_node_json) { json_t *collector_json = NULL, *grpc_json = NULL; collector_json = json_object_get(json_obj, "collector"); if (collector_json) grpc_json = json_object_get(collector_json, "grpc"); if (grpc_json) telemetry_node_json = json_object_get(grpc_json, "grpcPeer"); } if (!telemetry_node_json) { Log(LOG_WARNING, "WARN ( %s/%s ): telemetry_decode_producer_peer(): no 'telemetry_node' element.\n", config.name, t_data->log_str); ret = ERR; goto exit_lane; } else { const char *telemetry_node_str; telemetry_node_str = json_string_value(telemetry_node_json); str_to_addr(telemetry_node_str, &telemetry_node); } telemetry_node_port_json = json_object_get(json_obj, "telemetry_node_port"); if (telemetry_node_port_json) telemetry_node_port = json_integer_value(telemetry_node_port_json); (*addr_len) = addr_to_sa(addr, &telemetry_node, telemetry_node_port); } exit_lane: json_decref(json_obj); } else { Log(LOG_WARNING, "WARN ( %s/%s ): telemetry_decode_producer_peer(): invalid telemetry node JSON received: %s.\n", config.name, t_data->log_str, json_err.text); if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): %s\n", config.name, t_data->log_str, buf); ret = ERR; } } else { ret = ERR; } return ret; } #else int telemetry_decode_producer_peer(struct telemetry_data *t_data, void *h, u_char *buf, size_t buflen, struct sockaddr *addr, socklen_t *addr_len) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_decode_producer_peer() requires --enable-jansson. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); return 0; } #endif pmacct-1.7.8/src/telemetry/telemetry_util.h0000644000175000017500000000375414354105275020044 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TELEMETRY_UTIL_H #define TELEMETRY_UTIL_H /* includes */ /* defines */ /* prototypes */ extern int telemetry_peer_init(telemetry_peer *, int); extern void telemetry_peer_close(telemetry_peer *, int); extern u_int32_t telemetry_cisco_hdr_v0_get_len(telemetry_peer *); extern u_int32_t telemetry_cisco_hdr_v0_get_type(telemetry_peer *); extern u_int32_t telemetry_cisco_hdr_v1_get_len(telemetry_peer *); extern u_int16_t telemetry_cisco_hdr_v1_get_type(telemetry_peer *); extern u_int16_t telemetry_cisco_hdr_v1_get_encap(telemetry_peer *); extern void telemetry_link_misc_structs(telemetry_misc_structs *); extern int telemetry_tpc_addr_cmp(const void *, const void *); extern int telemetry_validate_input_output_decoders(int, int); extern void telemetry_log_peer_stats(telemetry_peer *, struct telemetry_data *); extern void telemetry_log_global_stats(struct telemetry_data *); #ifdef WITH_ZMQ extern void telemetry_init_zmq_host(void *, int *); #endif #ifdef WITH_KAFKA extern void telemetry_init_kafka_host(void *); #endif #ifdef WITH_UNYTE_UDP_NOTIF extern int create_socket_unyte_udp_notif(struct telemetry_data *, char *, char *); #endif #endif //TELEMETRY_UTIL_H pmacct-1.7.8/src/telemetry/telemetry.c0000644000175000017500000011432114354105275016773 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "thread_pool.h" #include "bgp/bgp.h" #include "telemetry.h" #if defined WITH_EBPF #include "ebpf/ebpf_rp_balancer.h" #endif #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined WITH_ZMQ #include "zmq_common.h" #endif /* Global variables */ thread_pool_t *telemetry_pool; telemetry_misc_structs *telemetry_misc_db; telemetry_peer *telemetry_peers; void *telemetry_peers_cache; telemetry_peer_timeout *telemetry_peers_timeout; int zmq_input = 0, kafka_input = 0, unyte_udp_notif_input = 0; telemetry_tag_t telemetry_logdump_tag; struct sockaddr_storage telemetry_logdump_tag_peer; /* Functions */ void telemetry_wrapper() { struct telemetry_data *t_data; /* initialize threads pool */ telemetry_pool = allocate_thread_pool(1); assert(telemetry_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/TELE ): %d thread(s) initialized\n", config.name, 1); t_data = malloc(sizeof(struct telemetry_data)); if (!t_data) { Log(LOG_ERR, "ERROR ( %s/core/TELE ): malloc() struct telemetry_data failed. Terminating.\n", config.name); exit_gracefully(1); } telemetry_prepare_thread(t_data); /* giving a kick to the telemetry thread */ send_to_pool(telemetry_pool, telemetry_daemon, t_data); } int telemetry_daemon(void *t_data_void) { struct telemetry_data *t_data = t_data_void; telemetry_peer_cache tpc; int ret, rc, peers_idx, allowed, yes=1; int peers_idx_rr = 0, max_peers_idx = 0, peers_num = 0; int data_decoder = 0, recv_flags = 0; int capture_methods = 0; u_int16_t port = 0; char *srv_proto = NULL; time_t last_peers_timeout_check; socklen_t slen = {0}, clen; telemetry_peer *peer = NULL; struct sockaddr_storage server, client; struct hosts_table allow; struct host_addr addr; sigset_t signal_set; /* select() stuff */ fd_set read_descs, bkp_read_descs; int fd, select_fd, bkp_select_fd, recalc_fds, select_num = 0; /* logdump time management */ time_t dump_refresh_deadline = {0}; struct timeval dump_refresh_timeout, *drt_ptr; /* ZeroMQ and Kafka stuff */ char *saved_peer_buf = NULL; u_char consumer_buf[PKT_MSG_SIZE]; /* telemetry_tag_map stuff */ struct plugin_requests req; struct id_table telemetry_logdump_tag_table; int telemetry_logdump_tag_map_allocated; #if defined WITH_UNYTE_UDP_NOTIF unyte_udp_collector_t *uun_collector = NULL; void *seg_ptr = NULL; char udp_notif_port[6]; char udp_notif_null_ip_address[] = "0.0.0.0"; #endif if (!t_data) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon(): missing telemetry data. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } /* initial cleanups */ reload_map_telemetry_thread = FALSE; reload_log_telemetry_thread = FALSE; memset(&server, 0, sizeof(server)); memset(&client, 0, sizeof(client)); memset(&allow, 0, sizeof(struct hosts_table)); clen = sizeof(client); telemetry_peers_cache = NULL; last_peers_timeout_check = FALSE; telemetry_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_TELEMETRY]; memset(telemetry_misc_db, 0, sizeof(telemetry_misc_structs)); /* initialize variables */ if (config.telemetry_ip || config.telemetry_port_tcp || config.telemetry_port_udp) { capture_methods++; } if (config.telemetry_udp_notif_ip || config.telemetry_udp_notif_port) { #if defined WITH_UNYTE_UDP_NOTIF capture_methods++; unyte_udp_notif_input = TRUE; #endif } if (config.telemetry_zmq_address) { #if defined WITH_ZMQ capture_methods++; zmq_input = TRUE; #else Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_zmq_* require --enable-zmq. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); #endif } if (config.telemetry_kafka_broker_host || config.telemetry_kafka_topic) { #if defined WITH_KAFKA capture_methods++; kafka_input = TRUE; if ((config.telemetry_kafka_broker_host && !config.telemetry_kafka_topic) || (config.telemetry_kafka_topic && !config.telemetry_kafka_broker_host)) { Log(LOG_ERR, "ERROR ( %s/%s ): Kafka collection requires both broker host and topic to be specified. Terminating.\n\n", config.name, t_data->log_str); exit_gracefully(1); } #else Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_kafka_* require --enable-kafka. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); #endif } if (capture_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_ip, telemetry_daemon_zmq_* and telemetry_kafka_* are mutually exclusive. Exiting...\n", config.name, t_data->log_str); exit_gracefully(1); } memset(consumer_buf, 0, sizeof(consumer_buf)); if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { if (config.telemetry_port_tcp && config.telemetry_port_udp) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_port_tcp and telemetry_daemon_port_udp are mutually exclusive. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } else if (!config.telemetry_port_tcp && !config.telemetry_port_udp) { /* defaulting to TCP */ port = config.telemetry_port_tcp = TELEMETRY_TCP_PORT; srv_proto = malloc(strlen("tcp") + 1); strcpy(srv_proto, "tcp"); } else { if (config.telemetry_port_tcp) { port = config.telemetry_port_tcp; srv_proto = malloc(strlen("tcp") + 1); strcpy(srv_proto, "tcp"); } if (config.telemetry_port_udp) { port = config.telemetry_port_udp; srv_proto = malloc(strlen("udp") + 1); strcpy(srv_proto, "udp"); } } /* socket creation for telemetry server: IPv4 only */ if (!config.telemetry_ip) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&server; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(port); slen = sizeof(struct sockaddr_in6); } else { trim_spaces(config.telemetry_ip); ret = str_to_addr(config.telemetry_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_ip value is not a valid IPv4/IPv6 address. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } slen = addr_to_sa((struct sockaddr *)&server, &addr, port); } } if (!config.telemetry_decoder) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_decoder is not specified. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } else { if (!strcmp(config.telemetry_decoder, "json")) config.telemetry_decoder_id = TELEMETRY_DECODER_JSON; else if (!strcmp(config.telemetry_decoder, "gpb")) config.telemetry_decoder_id = TELEMETRY_DECODER_GPB; else if (!strcmp(config.telemetry_decoder, "cisco_v0")) config.telemetry_decoder_id = TELEMETRY_DECODER_CISCO_V0; else if (!strcmp(config.telemetry_decoder, "cisco_v1")) config.telemetry_decoder_id = TELEMETRY_DECODER_CISCO_V1; else { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_decoder set to unknown value. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } if (config.telemetry_decoder_id != TELEMETRY_DECODER_JSON) { if (zmq_input) { Log(LOG_ERR, "ERROR ( %s/%s ): ZeroMQ collection supports only 'json' decoder (telemetry_daemon_decoder). Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } if (kafka_input) { Log(LOG_ERR, "ERROR ( %s/%s ): Kafka collection supports only 'json' decoder (telemetry_daemon_decoder). Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } if (unyte_udp_notif_input) { Log(LOG_ERR, "ERROR ( %s/%s ): Unyte UDP Notif collection supports only 'json' decoder (telemetry_daemon_decoder). Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } } } if (!config.telemetry_max_peers) config.telemetry_max_peers = TELEMETRY_MAX_PEERS_DEFAULT; Log(LOG_INFO, "INFO ( %s/%s ): maximum telemetry peers allowed: %d\n", config.name, t_data->log_str, config.telemetry_max_peers); if (config.telemetry_port_udp || zmq_input || kafka_input || unyte_udp_notif_input) { if (!config.telemetry_peer_timeout) config.telemetry_peer_timeout = TELEMETRY_PEER_TIMEOUT_DEFAULT; Log(LOG_INFO, "INFO ( %s/%s ): telemetry peers timeout: %u\n", config.name, t_data->log_str, config.telemetry_peer_timeout); } telemetry_peers = malloc(config.telemetry_max_peers*sizeof(telemetry_peer)); if (!telemetry_peers) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() telemetry_peers structure. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } memset(telemetry_peers, 0, config.telemetry_max_peers*sizeof(telemetry_peer)); if (config.telemetry_port_udp || zmq_input || kafka_input || unyte_udp_notif_input) { telemetry_peers_timeout = malloc(config.telemetry_max_peers*sizeof(telemetry_peer_timeout)); if (!telemetry_peers_timeout) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() telemetry_peers_timeout structure. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } memset(telemetry_peers_timeout, 0, config.telemetry_max_peers*sizeof(telemetry_peer_timeout)); } if (config.telemetry_msglog_file || config.telemetry_msglog_amqp_routing_key || config.telemetry_msglog_kafka_topic) { if (config.telemetry_msglog_file) telemetry_misc_db->msglog_backend_methods++; if (config.telemetry_msglog_amqp_routing_key) telemetry_misc_db->msglog_backend_methods++; if (config.telemetry_msglog_kafka_topic) telemetry_misc_db->msglog_backend_methods++; if (telemetry_misc_db->msglog_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_daemon_msglog_file, telemetry_daemon_msglog_amqp_routing_key and telemetry_daemon_msglog_kafka_topic are mutually exclusive. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } } if (config.telemetry_dump_file || config.telemetry_dump_amqp_routing_key || config.telemetry_dump_kafka_topic) { if (config.telemetry_dump_file) telemetry_misc_db->dump_backend_methods++; if (config.telemetry_dump_amqp_routing_key) telemetry_misc_db->dump_backend_methods++; if (config.telemetry_dump_kafka_topic) telemetry_misc_db->dump_backend_methods++; if (telemetry_misc_db->dump_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/%s ): telemetry_dump_file, telemetry_dump_amqp_routing_key and telemetry_dump_kafka_topic are mutually exclusive. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } } if (telemetry_misc_db->msglog_backend_methods || telemetry_misc_db->dump_backend_methods) telemetry_log_seq_init(&telemetry_misc_db->log_seq); if (telemetry_misc_db->msglog_backend_methods) { telemetry_misc_db->peers_log = malloc(config.telemetry_max_peers*sizeof(telemetry_peer_log)); if (!telemetry_misc_db->peers_log) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() telemetry peers_log structure. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } memset(telemetry_misc_db->peers_log, 0, config.telemetry_max_peers*sizeof(telemetry_peer_log)); if (config.telemetry_msglog_amqp_routing_key) { #ifdef WITH_RABBITMQ telemetry_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&telemetry_daemon_msglog_amqp_host); if (!config.telemetry_msglog_amqp_retry) config.telemetry_msglog_amqp_retry = AMQP_DEFAULT_RETRY; #else Log(LOG_WARNING, "WARN ( %s/%s ): p_amqp_connect_to_publish() not possible due to missing --enable-rabbitmq\n", config.name, t_data->log_str); #endif } if (config.telemetry_msglog_kafka_topic) { #ifdef WITH_KAFKA telemetry_daemon_msglog_init_kafka_host(); #else Log(LOG_WARNING, "WARN ( %s/%s ): p_kafka_connect_to_produce() not possible due to missing --enable-kafka\n", config.name, t_data->log_str); #endif } } if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { if (config.telemetry_port_tcp) config.telemetry_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); else if (config.telemetry_port_udp) config.telemetry_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); if (config.telemetry_sock < 0) { /* retry with IPv4 */ if (!config.telemetry_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(port); slen = sizeof(struct sockaddr_in); if (config.telemetry_port_tcp) config.telemetry_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_STREAM, 0); else if (config.telemetry_port_udp) config.telemetry_sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); } if (config.telemetry_sock < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): socket() failed. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } if (config.telemetry_port_tcp) setsockopt(config.telemetry_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&yes, sizeof(yes)); } if (config.telemetry_ipprec) { int opt = config.telemetry_ipprec << 5; rc = setsockopt(config.telemetry_sock, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IP_TOS (errno: %d).\n", config.name, t_data->log_str, errno); } #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.telemetry_sock, SOL_SOCKET, SO_REUSEPORT, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEPORT (errno: %d).\n", config.name, t_data->log_str, errno); #endif #if (defined HAVE_SO_BINDTODEVICE) if (config.telemetry_interface) { rc = setsockopt(config.telemetry_sock, SOL_SOCKET, SO_BINDTODEVICE, config.telemetry_interface, (socklen_t) strlen(config.telemetry_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, t_data->log_str, errno); } #endif rc = setsockopt(config.telemetry_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_REUSEADDR (errno: %d).\n", config.name, t_data->log_str, errno); if (config.telemetry_ipv6_only) { int yes=1; rc = setsockopt(config.telemetry_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IPV6_V6ONLY (errno: %d).\n", config.name, t_data->log_str, errno); } if (config.telemetry_pipe_size) { socklen_t l = sizeof(config.telemetry_pipe_size); int saved = 0, obtained = 0; getsockopt(config.telemetry_sock, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(config.telemetry_sock, SOL_SOCKET, SO_RCVBUF, &config.telemetry_pipe_size, (socklen_t) sizeof(config.telemetry_pipe_size)); getsockopt(config.telemetry_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Setsocksize(config.telemetry_sock, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(config.telemetry_sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); Log(LOG_INFO, "INFO ( %s/%s ): telemetry_daemon_pipe_size: obtained=%d target=%d.\n", config.name, t_data->log_str, obtained, config.telemetry_pipe_size); } rc = bind(config.telemetry_sock, (struct sockaddr *) &server, slen); if (rc < 0) { char null_ip_address[] = "0.0.0.0"; char *ip_address; ip_address = config.telemetry_ip ? config.telemetry_ip : null_ip_address; Log(LOG_ERR, "ERROR ( %s/%s ): bind() to ip=%s port=%u/%s failed (errno: %d).\n", config.name, t_data->log_str, ip_address, port, srv_proto, errno); exit_gracefully(1); } if (config.telemetry_port_tcp) { rc = listen(config.telemetry_sock, 1); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): listen() failed (errno: %d).\n", config.name, t_data->log_str, errno); exit_gracefully(1); } } } if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { char srv_string[INET6_ADDRSTRLEN]; struct host_addr srv_addr; u_int16_t srv_port; sa_to_addr((struct sockaddr *)&server, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/%s ): waiting for telemetry data on %s:%u/%s\n", config.name, t_data->log_str, srv_string, srv_port, srv_proto); } #if defined WITH_ZMQ else if (zmq_input) { telemetry_init_zmq_host(&telemetry_zmq_host, &config.telemetry_sock); Log(LOG_INFO, "INFO ( %s/%s ): reading telemetry data from ZeroMQ %s\n", config.name, t_data->log_str, p_zmq_get_address(&telemetry_zmq_host)); } #endif #if defined WITH_KAFKA else if (kafka_input) { telemetry_init_kafka_host(&telemetry_kafka_host); Log(LOG_INFO, "INFO ( %s/%s ): reading telemetry data from Kafka %s:%s\n", config.name, t_data->log_str, p_kafka_get_broker(&telemetry_kafka_host), p_kafka_get_topic(&telemetry_kafka_host)); } #endif #if defined WITH_UNYTE_UDP_NOTIF else if (unyte_udp_notif_input) { unyte_udp_options_t options = {0}; int sockfd; memset(udp_notif_port, 0, sizeof(udp_notif_port)); if (!config.telemetry_udp_notif_ip) { config.telemetry_udp_notif_ip = udp_notif_null_ip_address; } if (config.telemetry_udp_notif_port) { sprintf(udp_notif_port, "%d", config.telemetry_udp_notif_port); } else { Log(LOG_ERR, "ERROR ( %s/core/TELE ): Unyte UDP Notif specified but no telemetry_daemon_udp_notif_port supplied. Terminating.\n", config.name); exit_gracefully(1); } sockfd = create_socket_unyte_udp_notif(t_data, config.telemetry_udp_notif_ip, udp_notif_port); #if defined WITH_EBPF && defined HAVE_SO_REUSEPORT if (config.telemetry_udp_notif_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(sockfd, config.telemetry_udp_notif_rp_ebpf_prog, config.cluster_name, "telemetry", config.cluster_id, FALSE); } #endif options.socket_fd = sockfd; if (config.telemetry_udp_notif_nmsgs) { options.recvmmsg_vlen = config.telemetry_udp_notif_nmsgs; } else { options.recvmmsg_vlen = TELEMETRY_DEFAULT_UNYTE_UDP_NOTIF_NMSGS; } if (config.tmp_telemetry_udp_notif_legacy) { options.legacy = TRUE; } uun_collector = unyte_udp_start_collector(&options); Log(LOG_INFO, "INFO ( %s/%s ): reading telemetry data from Unyte UDP Notif on %s:%s\n", config.name, t_data->log_str, config.telemetry_udp_notif_ip, udp_notif_port); } #endif /* Preparing for syncronous I/O multiplexing */ select_fd = 0; FD_ZERO(&bkp_read_descs); FD_SET(config.telemetry_sock, &bkp_read_descs); /* Preparing ACL, if any */ if (config.telemetry_allow_file) load_allow_file(config.telemetry_allow_file, &allow); if (telemetry_misc_db->msglog_backend_methods) { #ifdef WITH_JANSSON if (!config.telemetry_msglog_output) config.telemetry_msglog_output = PRINT_OUTPUT_JSON; #else Log(LOG_WARNING, "WARN ( %s/%s ): telemetry_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", config.name, t_data->log_str); #endif } if (telemetry_misc_db->dump_backend_methods) { if (!config.telemetry_dump_workers) { config.telemetry_dump_workers = 1; } #ifdef WITH_JANSSON if (!config.telemetry_dump_output) { config.telemetry_dump_output = PRINT_OUTPUT_JSON; } #else Log(LOG_WARNING, "WARN ( %s/%s ): telemetry_table_dump_output set to json but will produce no output (missing --enable-jansson).\n", config.name, t_data->log_str); #endif } if (telemetry_misc_db->dump_backend_methods) { char dump_roundoff[] = "m"; time_t tmp_time; if (!config.telemetry_dump_time_slots) { config.telemetry_dump_time_slots = 1; } if (config.telemetry_dump_refresh_time % config.telemetry_dump_time_slots != 0) { Log(LOG_WARNING, "WARN ( %s/%s ): 'telemetry_dump_time_slots' is not a divisor of 'telemetry_dump_refresh_time', please fix.\n", config.name, t_data->log_str); } if (config.telemetry_dump_refresh_time) { gettimeofday(&telemetry_misc_db->log_tstamp, NULL); dump_refresh_deadline = telemetry_misc_db->log_tstamp.tv_sec; tmp_time = roundoff_time(dump_refresh_deadline, dump_roundoff); while ((tmp_time+config.telemetry_dump_refresh_time) < dump_refresh_deadline) { tmp_time += config.telemetry_dump_refresh_time; } dump_refresh_deadline = tmp_time; dump_refresh_deadline += config.telemetry_dump_refresh_time; /* it's a deadline not a basetime */ } else { config.telemetry_dump_file = NULL; telemetry_misc_db->dump_backend_methods = FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): Invalid 'telemetry_dump_refresh_time'.\n", config.name, t_data->log_str); } } if (!config.writer_id_string) { config.writer_id_string = DYNNAME_DEFAULT_WRITER_ID; } dynname_tokens_prepare(config.writer_id_string, &telemetry_misc_db->writer_id_tokens, DYN_STR_WRITER_ID); select_fd = bkp_select_fd = (config.telemetry_sock + 1); recalc_fds = FALSE; telemetry_link_misc_structs(telemetry_misc_db); if (config.telemetry_tag_map) { memset(&telemetry_logdump_tag, 0, sizeof(telemetry_logdump_tag)); memset(&telemetry_logdump_tag_table, 0, sizeof(telemetry_logdump_tag_table)); memset(&req, 0, sizeof(req)); telemetry_logdump_tag_map_allocated = FALSE; load_pre_tag_map(ACCT_PMTELE, config.telemetry_tag_map, &telemetry_logdump_tag_table, &req, &telemetry_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); /* making some bindings */ telemetry_logdump_tag.tag_table = (unsigned char *) &telemetry_logdump_tag_table; } sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } for (;;) { select_again: if (!t_data->is_thread) { sigprocmask(SIG_UNBLOCK, &signal_set, NULL); sigprocmask(SIG_BLOCK, &signal_set, NULL); } if (recalc_fds) { select_fd = config.telemetry_sock; max_peers_idx = -1; /* .. since valid indexes include 0 */ for (peers_idx = 0, peers_num = 0; peers_idx < config.telemetry_max_peers; peers_idx++) { if (select_fd < telemetry_peers[peers_idx].fd) select_fd = telemetry_peers[peers_idx].fd; if (telemetry_peers[peers_idx].fd > 0) { max_peers_idx = peers_idx; peers_num++; } } select_fd++; max_peers_idx++; bkp_select_fd = select_fd; recalc_fds = FALSE; } else select_fd = bkp_select_fd; memcpy(&read_descs, &bkp_read_descs, sizeof(bkp_read_descs)); if (telemetry_misc_db->dump_backend_methods) { int delta; calc_refresh_timeout_sec(dump_refresh_deadline, telemetry_misc_db->log_tstamp.tv_sec, &delta); dump_refresh_timeout.tv_sec = delta; dump_refresh_timeout.tv_usec = 0; drt_ptr = &dump_refresh_timeout; } else drt_ptr = NULL; if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { select_num = select(select_fd, &read_descs, NULL, NULL, drt_ptr); if (select_num < 0) goto select_again; } #if defined WITH_ZMQ else if (zmq_input) { select_num = p_zmq_recv_poll(&telemetry_zmq_host.sock, drt_ptr ? (drt_ptr->tv_sec * 1000) : 1000); if (select_num < 0) goto select_again; } #endif #if defined WITH_KAFKA else if (kafka_input) { t_data->kafka_msg = NULL; select_num = p_kafka_consume_poller(&telemetry_kafka_host, &t_data->kafka_msg, drt_ptr ? (drt_ptr->tv_sec * 1000) : 1000); if (select_num < 0) { /* Close */ p_kafka_manage_consumer(&nfacctd_kafka_host, FALSE); /* Re-open */ telemetry_init_kafka_host(&telemetry_kafka_host); goto select_again; } } #endif #if defined WITH_UNYTE_UDP_NOTIF else if (unyte_udp_notif_input) { seg_ptr = unyte_udp_queue_read(uun_collector->queue); select_num = TRUE; /* anything but zero or negative */ } #endif t_data->now = time(NULL); /* Logging stats */ if (!t_data->global_stats.last_check || ((t_data->global_stats.last_check + TELEMETRY_LOG_STATS_INTERVAL) <= t_data->now)) { if (t_data->global_stats.last_check) { telemetry_peer *stats_peer; int peers_idx; for (stats_peer = NULL, peers_idx = 0; peers_idx < config.telemetry_max_peers; peers_idx++) { if (telemetry_peers[peers_idx].fd) { stats_peer = &telemetry_peers[peers_idx]; telemetry_log_peer_stats(stats_peer, t_data); stats_peer->stats.last_check = t_data->now; } } telemetry_log_global_stats(t_data); } t_data->global_stats.last_check = t_data->now; } /* XXX: ZeroMQ / Kafka cases: timeout handling (to be tested) */ if (config.telemetry_port_udp || zmq_input || kafka_input || unyte_udp_notif_input) { if (t_data->now > (last_peers_timeout_check + TELEMETRY_PEER_TIMEOUT_INTERVAL)) { for (peers_idx = 0; peers_idx < config.telemetry_max_peers; peers_idx++) { telemetry_peer_timeout *peer_timeout; peer = &telemetry_peers[peers_idx]; peer_timeout = &telemetry_peers_timeout[peers_idx]; if (peer->fd) { if (t_data->now > (peer_timeout->last_msg + config.telemetry_peer_timeout)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] telemetry peer removed (timeout).\n", config.name, t_data->log_str, peer->addr_str); telemetry_peer_close(peer, FUNC_TYPE_TELEMETRY); peers_num--; recalc_fds = TRUE; } } } last_peers_timeout_check = t_data->now; } } if (reload_map_telemetry_thread) { if (config.telemetry_allow_file) load_allow_file(config.telemetry_allow_file, &allow); if (config.telemetry_tag_map) { load_pre_tag_map(ACCT_PMTELE, config.telemetry_tag_map, &telemetry_logdump_tag_table, &req, &telemetry_logdump_tag_map_allocated, config.maps_entries, config.maps_row_len); } reload_map_telemetry_thread = FALSE; } if (reload_log_telemetry_thread) { for (peers_idx = 0; peers_idx < config.telemetry_max_peers; peers_idx++) { if (telemetry_misc_db->peers_log[peers_idx].fd) { fclose(telemetry_misc_db->peers_log[peers_idx].fd); telemetry_misc_db->peers_log[peers_idx].fd = open_output_file(telemetry_misc_db->peers_log[peers_idx].filename, "a", FALSE); setlinebuf(telemetry_misc_db->peers_log[peers_idx].fd); } else break; } reload_log_telemetry_thread = FALSE; } if (reload_log && !telemetry_misc_db->is_thread) { reload_logs(PMTELEMETRYD_USAGE_HEADER); reload_log = FALSE; } if (telemetry_misc_db->msglog_backend_methods || telemetry_misc_db->dump_backend_methods) { gettimeofday(&telemetry_misc_db->log_tstamp, NULL); compose_timestamp(telemetry_misc_db->log_tstamp_str, SRVBUFLEN, &telemetry_misc_db->log_tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); /* let's reset log sequence here as we do not sequence dump_init/dump_close events */ if (telemetry_log_seq_has_ro_bit(&telemetry_misc_db->log_seq)) telemetry_log_seq_init(&telemetry_misc_db->log_seq); int refreshTimePerSlot = config.telemetry_dump_refresh_time / config.telemetry_dump_time_slots; if (telemetry_misc_db->dump_backend_methods) { while (telemetry_misc_db->log_tstamp.tv_sec > dump_refresh_deadline) { telemetry_misc_db->dump.tstamp.tv_sec = dump_refresh_deadline; telemetry_misc_db->dump.tstamp.tv_usec = 0; compose_timestamp(telemetry_misc_db->dump.tstamp_str, SRVBUFLEN, &telemetry_misc_db->dump.tstamp, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); telemetry_misc_db->dump.period = refreshTimePerSlot; telemetry_handle_dump_event(t_data, max_peers_idx); dump_refresh_deadline += config.telemetry_dump_refresh_time; } } #ifdef WITH_RABBITMQ if (config.telemetry_msglog_amqp_routing_key) { time_t last_fail = P_broker_timers_get_last_fail(&telemetry_daemon_msglog_amqp_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&telemetry_daemon_msglog_amqp_host.btimers)) <= telemetry_misc_db->log_tstamp.tv_sec)) { telemetry_daemon_msglog_init_amqp_host(); p_amqp_connect_to_publish(&telemetry_daemon_msglog_amqp_host); } } #endif #ifdef WITH_KAFKA if (config.telemetry_msglog_kafka_topic) { time_t last_fail = P_broker_timers_get_last_fail(&telemetry_daemon_msglog_kafka_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&telemetry_daemon_msglog_kafka_host.btimers)) <= telemetry_misc_db->log_tstamp.tv_sec)) telemetry_daemon_msglog_init_kafka_host(); } #endif } /* If select_num == 0 then we got out of polling due to a timeout rather than because we had a message from a peer to handle. By now we did all routine checks and can return to polling again. */ if (!select_num) goto select_again; /* New connection is coming in */ if (FD_ISSET(config.telemetry_sock, &read_descs) || kafka_input || unyte_udp_notif_input) { if (config.telemetry_port_tcp) { fd = accept(config.telemetry_sock, (struct sockaddr *) &client, &clen); if (fd == ERR) goto read_data; } else if (config.telemetry_port_udp) { char dummy_local_buf[TRUE]; ret = recvfrom(config.telemetry_sock, dummy_local_buf, TRUE, MSG_PEEK, (struct sockaddr *) &client, &clen); if (ret <= 0) goto select_again; else fd = config.telemetry_sock; } #if defined WITH_ZMQ else if (zmq_input) { ret = telemetry_decode_producer_peer(t_data, &telemetry_zmq_host, consumer_buf, sizeof(consumer_buf), (struct sockaddr *) &client, &clen); if (ret < 0) goto select_again; else fd = config.telemetry_sock; } #endif #if defined WITH_KAFKA else if (kafka_input) { ret = telemetry_decode_producer_peer(t_data, &telemetry_kafka_host, consumer_buf, sizeof(consumer_buf), (struct sockaddr *) &client, &clen); if (ret < 0) goto select_again; else fd = TELEMETRY_KAFKA_FD; } #endif #if defined WITH_UNYTE_UDP_NOTIF else if (unyte_udp_notif_input) { if (seg_ptr) { unyte_seg_met_t *seg = NULL; int payload_len = 0; seg = (unyte_seg_met_t *)seg_ptr; if (unyte_udp_get_media_type(seg) == UNYTE_MEDIATYPE_YANG_JSON && config.telemetry_decoder_id == TELEMETRY_DECODER_JSON) { struct sockaddr_storage *unsa = NULL; unsa = unyte_udp_get_src(seg); memcpy(&client, unsa, sizeof(struct sockaddr_storage)); payload_len = strlen(seg->payload); if (payload_len < sizeof(consumer_buf)) { strlcpy((char *)consumer_buf, seg->payload, sizeof(consumer_buf)); fd = TELEMETRY_UDP_NOTIF_FD; } else { goto select_again; } } else { goto select_again; } } } #endif ipv4_mapped_to_ipv4(&client); /* If an ACL is defined, here we check against and enforce it */ if (allow.num) allowed = check_allow(&allow, (struct sockaddr *)&client); else allowed = TRUE; if (!allowed) { if (config.telemetry_port_tcp) close(fd); goto read_data; } /* XXX: UDP, ZeroMQ and Kafka cases may be optimized further */ if (config.telemetry_port_udp || zmq_input || kafka_input || unyte_udp_notif_input) { telemetry_peer_cache *tpc_ret; u_int16_t client_port; sa_to_addr((struct sockaddr *)&client, &tpc.addr, &client_port); tpc_ret = pm_tfind(&tpc, &telemetry_peers_cache, telemetry_tpc_addr_cmp); if (tpc_ret) { telemetry_peer_cache *tpc_peer = (*(telemetry_peer_cache **) tpc_ret); peer = &telemetry_peers[tpc_peer->index]; telemetry_peers_timeout[tpc_peer->index].last_msg = t_data->now; goto read_data; } } for (peer = NULL, peers_idx = 0; peers_idx < config.telemetry_max_peers; peers_idx++) { if (!telemetry_peers[peers_idx].fd) { peer = &telemetry_peers[peers_idx]; if (telemetry_peer_init(peer, FUNC_TYPE_TELEMETRY)) peer = NULL; if (peer) { recalc_fds = TRUE; // XXX: do we need this for ZeroMQ / Kafka cases? if (config.telemetry_port_udp || zmq_input || kafka_input || unyte_udp_notif_input) { tpc.index = peers_idx; telemetry_peers_timeout[peers_idx].last_msg = t_data->now; if (!pm_tsearch(&tpc, &telemetry_peers_cache, telemetry_tpc_addr_cmp, sizeof(telemetry_peer_cache))) Log(LOG_WARNING, "WARN ( %s/%s ): tsearch() unable to insert in peers cache.\n", config.name, t_data->log_str); } } break; } } if (!peer) { /* We briefly accept the new connection to be able to drop it */ Log(LOG_WARNING, "WARN ( %s/%s ): Insufficient number of telemetry peers has been configured by telemetry_max_peers (%d).\n", config.name, t_data->log_str, config.telemetry_max_peers); if (config.telemetry_port_tcp) close(fd); goto read_data; } #if defined WITH_KAFKA if (kafka_input) { peer->buf.kafka_msg = t_data->kafka_msg; t_data->kafka_msg = NULL; } #endif peer->fd = fd; if (config.telemetry_port_tcp) FD_SET(peer->fd, &bkp_read_descs); peer->addr.family = ((struct sockaddr *)&client)->sa_family; if (peer->addr.family == AF_INET) { peer->addr.address.ipv4.s_addr = ((struct sockaddr_in *)&client)->sin_addr.s_addr; peer->tcp_port = ntohs(((struct sockaddr_in *)&client)->sin_port); } else if (peer->addr.family == AF_INET6) { memcpy(&peer->addr.address.ipv6, &((struct sockaddr_in6 *)&client)->sin6_addr, 16); peer->tcp_port = ntohs(((struct sockaddr_in6 *)&client)->sin6_port); } addr_to_str(peer->addr_str, &peer->addr); if (config.telemetry_tag_map) { telemetry_tag_init_find(peer, (struct sockaddr *) &telemetry_logdump_tag_peer, &telemetry_logdump_tag); telemetry_tag_find((struct id_table *)telemetry_logdump_tag.tag_table, &telemetry_logdump_tag, &telemetry_logdump_tag.tag, NULL); } if (telemetry_misc_db->msglog_backend_methods) telemetry_peer_log_init(peer, &telemetry_logdump_tag, config.telemetry_msglog_output, FUNC_TYPE_TELEMETRY); if (telemetry_misc_db->dump_backend_methods) telemetry_dump_init_peer(peer); peers_num++; Log(LOG_INFO, "INFO ( %s/%s ): [%s] telemetry peers usage: %u/%u\n", config.name, t_data->log_str, peer->addr_str, peers_num, config.telemetry_max_peers); } read_data: /* We have something coming in: let's lookup which peer is that. FvD: To avoid starvation of the "later established" peers, we offset the start of the search in a round-robin style. */ if (config.telemetry_port_tcp) { for (peer = NULL, peers_idx = 0; peers_idx < max_peers_idx; peers_idx++) { int loc_idx = (peers_idx + peers_idx_rr) % max_peers_idx; if (telemetry_peers[loc_idx].fd && FD_ISSET(telemetry_peers[loc_idx].fd, &read_descs)) { peer = &telemetry_peers[loc_idx]; peers_idx_rr = (peers_idx_rr + 1) % max_peers_idx; break; } } } if (!peer) goto select_again; recv_flags = 0; switch (config.telemetry_decoder_id) { case TELEMETRY_DECODER_JSON: if (!zmq_input && !kafka_input && !unyte_udp_notif_input) { ret = telemetry_recv_json(peer, 0, &recv_flags); } else { ret = (strlen((char *) consumer_buf) + 1); if (ret > 0) { saved_peer_buf = peer->buf.base; peer->buf.base = (char *) consumer_buf; peer->msglen = peer->buf.tot_len = ret; if (unyte_udp_notif_input) { peer->stats.packet_bytes += ret; } } } data_decoder = TELEMETRY_DATA_DECODER_JSON; break; case TELEMETRY_DECODER_GPB: ret = telemetry_recv_gpb(peer, 0); data_decoder = TELEMETRY_DATA_DECODER_GPB; break; case TELEMETRY_DECODER_CISCO_V0: ret = telemetry_recv_cisco_v0(peer, &recv_flags, &data_decoder); break; case TELEMETRY_DECODER_CISCO_V1: ret = telemetry_recv_cisco_v1(peer, &recv_flags, &data_decoder); break; default: ret = TRUE; recv_flags = ERR; data_decoder = TELEMETRY_DATA_DECODER_UNKNOWN; break; } if (ret <= 0) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] connection reset by peer (%d).\n", config.name, t_data->log_str, peer->addr_str, errno); FD_CLR(peer->fd, &bkp_read_descs); telemetry_peer_close(peer, FUNC_TYPE_TELEMETRY); peers_num--; recalc_fds = TRUE; } else { peer->stats.packets++; if (recv_flags != ERR) { if (config.telemetry_tag_map) { telemetry_tag_init_find(peer, (struct sockaddr *) &telemetry_logdump_tag_peer, &telemetry_logdump_tag); telemetry_tag_find((struct id_table *)telemetry_logdump_tag.tag_table, &telemetry_logdump_tag, &telemetry_logdump_tag.tag, NULL); } peer->stats.msg_bytes += ret; telemetry_process_data(peer, t_data, data_decoder); } if (zmq_input || kafka_input || unyte_udp_notif_input) { peer->buf.base = saved_peer_buf; } } } return SUCCESS; } void telemetry_prepare_thread(struct telemetry_data *t_data) { if (!t_data) return; memset(t_data, 0, sizeof(struct telemetry_data)); t_data->is_thread = TRUE; t_data->log_str = malloc(strlen("core/TELE") + 1); strcpy(t_data->log_str, "core/TELE"); } void telemetry_prepare_daemon(struct telemetry_data *t_data) { if (!t_data) return; memset(t_data, 0, sizeof(struct telemetry_data)); t_data->is_thread = FALSE; t_data->log_str = malloc(strlen("core") + 1); strcpy(t_data->log_str, "core"); } void telemetry_tag_init_find(telemetry_peer *peer, struct sockaddr *sa, telemetry_tag_t *pptrs) { bgp_tag_init_find(peer, sa, pptrs); } int telemetry_tag_find(struct id_table *t, telemetry_tag_t *pptrs, pm_id_t *tag, pm_id_t *tag2) { return bgp_tag_find(t, pptrs, tag, tag2); } pmacct-1.7.8/src/telemetry/telemetry_msg.h0000644000175000017500000000367614354105275017660 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TELEMETRY_MSG_H #define TELEMETRY_MSG_H /* includes */ /* defines */ /* prototypes */ extern void telemetry_process_data(telemetry_peer *, struct telemetry_data *, int); extern int telemetry_recv_generic(telemetry_peer *, u_int32_t); extern int telemetry_recv_jump(telemetry_peer *, u_int32_t, int *); extern int telemetry_recv_json(telemetry_peer *, u_int32_t, int *); extern int telemetry_recv_gpb(telemetry_peer *, u_int32_t); extern int telemetry_recv_cisco(telemetry_peer *, int *, int *, u_int32_t, u_int32_t); extern int telemetry_recv_cisco_v0(telemetry_peer *, int *, int *); extern int telemetry_recv_cisco_v1(telemetry_peer *, int *, int *); extern void telemetry_basic_process_json(telemetry_peer *); extern int telemetry_basic_validate_json(telemetry_peer *); extern int telemetry_decode_producer_peer(struct telemetry_data *, void *, u_char *, size_t, struct sockaddr *, socklen_t *); #if defined (WITH_ZMQ) extern int telemetry_recv_zmq_generic(telemetry_peer *, u_int32_t); #endif #if defined (WITH_KAFKA) extern int telemetry_recv_kafka_generic(telemetry_peer *, u_int32_t); #endif #endif//TELEMETRY_MSG_H pmacct-1.7.8/src/telemetry/telemetry.h0000644000175000017500000001174614354105275017007 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TELEMETRY_H #define TELEMETRY_H /* includes */ #include "base64.h" #ifdef WITH_UNYTE_UDP_NOTIF #include #endif /* defines */ #define TELEMETRY_TCP_PORT 1620 #define TELEMETRY_UDP_PORT 1620 #define TELEMETRY_MAX_PEERS_DEFAULT 100 #define TELEMETRY_PEER_TIMEOUT_DEFAULT 300 #define TELEMETRY_PEER_TIMEOUT_INTERVAL 60 #define TELEMETRY_UDP_MAXMSG 65535 #define TELEMETRY_LOG_STATS_INTERVAL 120 #define TELEMETRY_KAFKA_FD INT_MAX #define TELEMETRY_UDP_NOTIF_FD INT_MAX #define TELEMETRY_DECODER_UNKNOWN 0 #define TELEMETRY_DECODER_JSON 1 #define TELEMETRY_DECODER_GPB 2 #define TELEMETRY_DECODER_CISCO_V0 3 #define TELEMETRY_DECODER_CISCO_V1 4 #define TELEMETRY_DATA_DECODER_UNKNOWN 0 #define TELEMETRY_DATA_DECODER_JSON 1 #define TELEMETRY_DATA_DECODER_GPB 2 #define TELEMETRY_DATA_DECODER_JSON_STRING 3 #define TELEMETRY_CISCO_VERSION_0 0 #define TELEMETRY_CISCO_HDR_LEN_V0 12 #define TELEMETRY_CISCO_VERSION_1 1 #define TELEMETRY_CISCO_HDR_LEN_V1 12 #define TELEMETRY_CISCO_RESET_COMPRESSOR 1 #define TELEMETRY_CISCO_JSON 2 #define TELEMETRY_CISCO_GPB_COMPACT 3 #define TELEMETRY_CISCO_GPB_KV 4 #define TELEMETRY_CISCO_V1_TYPE_UNUSED 0 #define TELEMETRY_CISCO_V1_TYPE_DATA 1 #define TELEMETRY_CISCO_V1_TYPE_HBEAT 2 #define TELEMETRY_CISCO_V1_ENCAP_UNUSED 0 #define TELEMETRY_CISCO_V1_ENCAP_GPB 1 #define TELEMETRY_CISCO_V1_ENCAP_JSON 2 #define TELEMETRY_CISCO_V1_ENCAP_GPV_CPT 3 #define TELEMETRY_CISCO_V1_ENCAP_GPB_KV 4 #define TELEMETRY_LOGDUMP_ET_NONE BGP_LOGDUMP_ET_NONE #define TELEMETRY_LOGDUMP_ET_LOG BGP_LOGDUMP_ET_LOG #define TELEMETRY_LOGDUMP_ET_DUMP BGP_LOGDUMP_ET_DUMP #ifdef WITH_UNYTE_UDP_NOTIF #define TELEMETRY_DEFAULT_UNYTE_UDP_NOTIF_NMSGS 1 #define TELEMETRY_UDP_NOTIF_ENC_CBOR 0 #define TELEMETRY_UDP_NOTIF_ENC_JSON 1 #define TELEMETRY_UDP_NOTIF_ENC_XML 2 #endif typedef bgp_tag_t telemetry_tag_t; typedef bgp_tag_cache_t telemetry_tag_cache_t; struct telemetry_cisco_hdr_v0 { u_int32_t type; u_int32_t flags; u_int32_t len; } __attribute__ ((packed)); struct telemetry_cisco_hdr_v1 { u_int16_t type; u_int16_t encap; u_int16_t version; u_int16_t flags; u_int32_t len; } __attribute__ ((packed)); typedef struct bgp_peer_stats telemetry_stats; struct telemetry_data { int is_thread; char *log_str; #if defined WITH_ZMQ void *zmq_host; #endif #if defined WITH_KAFKA void *kafka_msg; #endif telemetry_stats global_stats; time_t now; }; struct _telemetry_peer_cache { struct host_addr addr; int index; }; struct _telemetry_peer_timeout { time_t last_msg; }; struct _telemetry_dump_se { int decoder; u_int32_t len; u_int64_t seq; void *data; }; struct _telemetry_dump_se_ll_elem { struct _telemetry_dump_se rec; struct _telemetry_dump_se_ll_elem *next; }; struct _telemetry_dump_se_ll { struct _telemetry_dump_se_ll_elem *start; struct _telemetry_dump_se_ll_elem *last; }; typedef struct bgp_peer telemetry_peer; typedef struct bgp_peer_log telemetry_peer_log; typedef struct bgp_misc_structs telemetry_misc_structs; typedef struct _telemetry_dump_se_ll telemetry_dump_se_ll; typedef struct _telemetry_dump_se_ll_elem telemetry_dump_se_ll_elem; typedef struct _telemetry_peer_cache telemetry_peer_cache; typedef struct _telemetry_peer_timeout telemetry_peer_timeout; /* more includes */ #include "telemetry_logdump.h" #include "telemetry_msg.h" #include "telemetry_util.h" /* prototypes */ extern void telemetry_wrapper(); extern int telemetry_daemon(void *); extern void telemetry_prepare_thread(struct telemetry_data *); extern void telemetry_prepare_daemon(struct telemetry_data *); extern void telemetry_tag_init_find(telemetry_peer *, struct sockaddr *, telemetry_tag_t *); extern int telemetry_tag_find(struct id_table *, telemetry_tag_t *, pm_id_t *, pm_id_t *); /* global variables */ extern telemetry_misc_structs *telemetry_misc_db; extern telemetry_peer *telemetry_peers; extern void *telemetry_peers_cache; extern telemetry_peer_timeout *telemetry_peers_timeout; extern int zmq_input, kafka_input, unyte_udp_notif_input; extern telemetry_tag_t telemetry_logdump_tag; extern struct sockaddr_storage telemetry_logdump_tag_peer; #endif //TELEMETRY_H pmacct-1.7.8/src/telemetry/telemetry_util.c0000644000175000017500000002474414354105275020041 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "telemetry.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined WITH_ZMQ #include "zmq_common.h" #endif /* Functions */ int telemetry_peer_init(telemetry_peer *peer, int type) { return bgp_peer_init(peer, type); } void telemetry_peer_close(telemetry_peer *peer, int type) { telemetry_dump_se_ll *tdsell; telemetry_misc_structs *tms; if (!peer) return; tms = bgp_select_misc_db(peer->type); if (!tms) return; if (tms->dump_file || tms->dump_amqp_routing_key || tms->dump_kafka_topic) { tdsell = (telemetry_dump_se_ll *) peer->bmp_se; if (tdsell && tdsell->start) telemetry_dump_se_ll_destroy(tdsell); free(peer->bmp_se); peer->bmp_se = NULL; } if (config.telemetry_port_udp || config.telemetry_zmq_address) { telemetry_peer_cache tpc; memcpy(&tpc.addr, &peer->addr, sizeof(struct host_addr)); pm_tdelete(&tpc, &telemetry_peers_cache, telemetry_tpc_addr_cmp); peer->fd = ERR; /* dirty trick to prevent close() a valid fd in bgp_peer_close() */ } bgp_peer_close(peer, type, FALSE, FALSE, FALSE, FALSE, NULL); } u_int32_t telemetry_cisco_hdr_v0_get_len(telemetry_peer *peer) { u_int32_t len; memcpy(&len, (peer->buf.base + 8), 4); len = ntohl(len); return len; } u_int32_t telemetry_cisco_hdr_v0_get_type(telemetry_peer *peer) { u_int32_t type; memcpy(&type, peer->buf.base, 4); type = ntohl(type); return type; } u_int32_t telemetry_cisco_hdr_v1_get_len(telemetry_peer *peer) { u_int32_t len; memcpy(&len, (peer->buf.base + 8), 4); len = ntohl(len); return len; } u_int16_t telemetry_cisco_hdr_v1_get_type(telemetry_peer *peer) { u_int16_t type; memcpy(&type, peer->buf.base, 2); type = ntohs(type); return type; } u_int16_t telemetry_cisco_hdr_v1_get_encap(telemetry_peer *peer) { u_int16_t encap; memcpy(&encap, (peer->buf.base + 2), 2); encap = ntohs(encap); return encap; } int telemetry_tpc_addr_cmp(const void *a, const void *b) { return host_addr_cmp(&((telemetry_peer_cache *)a)->addr, &((telemetry_peer_cache *)b)->addr); } void telemetry_link_misc_structs(telemetry_misc_structs *tms) { #if defined WITH_RABBITMQ tms->msglog_amqp_host = &telemetry_daemon_msglog_amqp_host; #endif #if defined WITH_KAFKA tms->msglog_kafka_host = &telemetry_daemon_msglog_kafka_host; #endif tms->max_peers = config.telemetry_max_peers; tms->peers = telemetry_peers; tms->peers_cache = NULL; tms->peers_port_cache = NULL; tms->xconnects = NULL; tms->dump_file = config.telemetry_dump_file; tms->dump_amqp_routing_key = config.telemetry_dump_amqp_routing_key; tms->dump_amqp_routing_key_rr = config.telemetry_dump_amqp_routing_key_rr; tms->dump_kafka_topic = config.telemetry_dump_kafka_topic; tms->dump_kafka_topic_rr = config.telemetry_dump_kafka_topic_rr; tms->dump_kafka_partition_key = config.telemetry_dump_kafka_partition_key; tms->msglog_file = config.telemetry_msglog_file; tms->msglog_output = config.telemetry_msglog_output; tms->msglog_amqp_routing_key = config.telemetry_msglog_amqp_routing_key; tms->msglog_amqp_routing_key_rr = config.telemetry_msglog_amqp_routing_key_rr; tms->msglog_kafka_topic = config.telemetry_msglog_kafka_topic; tms->msglog_kafka_topic_rr = config.telemetry_msglog_kafka_topic_rr; tms->msglog_kafka_partition_key = config.telemetry_msglog_kafka_partition_key; tms->peer_str = malloc(strlen("telemetry_node") + 1); strcpy(tms->peer_str, "telemetry_node"); tms->peer_port_str = malloc(strlen("telemetry_node_port") + 1); strcpy(tms->peer_port_str, "telemetry_node_port"); tms->tag = &telemetry_logdump_tag; tms->tag_map = config.telemetry_tag_map; } int telemetry_validate_input_output_decoders(int input, int output) { if (input == TELEMETRY_DATA_DECODER_GPB) { if (output == PRINT_OUTPUT_JSON) return FALSE; /* else if (output == PRINT_OUTPUT_GPB) return FALSE; */ } else if (input == TELEMETRY_DATA_DECODER_JSON) { if (output == PRINT_OUTPUT_JSON) return FALSE; /* else if (output == PRINT_OUTPUT_GPB) return ERR; */ } else if (input == TELEMETRY_DATA_DECODER_UNKNOWN) { if (output == PRINT_OUTPUT_JSON) return FALSE; } else if (input == TELEMETRY_DATA_DECODER_JSON_STRING) { if (output == PRINT_OUTPUT_JSON) return FALSE; } return ERR; } void telemetry_log_peer_stats(telemetry_peer *peer, struct telemetry_data *t_data) { Log(LOG_INFO, "INFO ( %s/%s ): [%s:%u] pkts=%llu pktBytes=%llu msgBytes=%llu msgErrors=%llu\n", config.name, t_data->log_str, peer->addr_str, peer->tcp_port, (unsigned long long)peer->stats.packets, (unsigned long long)peer->stats.packet_bytes, (unsigned long long)peer->stats.msg_bytes, (unsigned long long)peer->stats.msg_errors); t_data->global_stats.packets += peer->stats.packets; t_data->global_stats.packet_bytes += peer->stats.packet_bytes; t_data->global_stats.msg_bytes += peer->stats.msg_bytes; t_data->global_stats.msg_errors += peer->stats.msg_errors; peer->stats.packets = 0; peer->stats.packet_bytes = 0; peer->stats.msg_bytes = 0; peer->stats.msg_errors = 0; } void telemetry_log_global_stats(struct telemetry_data *t_data) { Log(LOG_INFO, "INFO ( %s/%s ): [Total] pkts=%llu pktBytes=%llu msgBytes=%llu msgErrors=%llu\n", config.name, t_data->log_str, (unsigned long long)t_data->global_stats.packets, (unsigned long long)t_data->global_stats.packet_bytes, (unsigned long long)t_data->global_stats.msg_bytes, (unsigned long long)t_data->global_stats.msg_errors); t_data->global_stats.packets = 0; t_data->global_stats.packet_bytes = 0; t_data->global_stats.msg_bytes = 0; t_data->global_stats.msg_errors = 0; } #ifdef WITH_ZMQ void telemetry_init_zmq_host(void *zh, int *pipe_fd) { struct p_zmq_host *zmq_host = zh; char log_id[SHORTBUFLEN]; p_zmq_init_pull(zmq_host); snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_zmq_set_log_id(zmq_host, log_id); p_zmq_set_address(zmq_host, config.telemetry_zmq_address); p_zmq_pull_setup(zmq_host); p_zmq_set_retry_timeout(zmq_host, PM_ZMQ_DEFAULT_RETRY); if (pipe_fd) (*pipe_fd) = p_zmq_get_fd(zmq_host); } #endif #ifdef WITH_KAFKA void telemetry_init_kafka_host(void *kh) { struct p_kafka_host *kafka_host = kh; p_kafka_init_host(kafka_host, config.telemetry_kafka_config_file); p_kafka_connect_to_consume(kafka_host); p_kafka_set_broker(kafka_host, config.telemetry_kafka_broker_host, config.telemetry_kafka_broker_port); p_kafka_set_topic(kafka_host, config.telemetry_kafka_topic); p_kafka_set_content_type(kafka_host, PM_KAFKA_CNT_TYPE_STR); p_kafka_manage_consumer(kafka_host, TRUE); } #endif #ifdef WITH_UNYTE_UDP_NOTIF int create_socket_unyte_udp_notif(struct telemetry_data *t_data, char *address, char *port) { uint64_t receive_buf_size; struct addrinfo *addr_info; struct addrinfo hints; int rc; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Using getaddrinfo to support both IPv4 and IPv6 */ rc = getaddrinfo(address, port, &hints, &addr_info); if (rc != 0) { Log(LOG_ERR, "ERROR ( %s/%s ): create_socket_unyte_udp_notif(): getaddrinfo error: %s\n", config.name, t_data->log_str, gai_strerror(rc)); exit_gracefully(1); } Log(LOG_INFO, "INFO ( %s/%s ): create_socket_unyte_udp_notif(): family=%s port=%d\n", config.name, t_data->log_str, (addr_info->ai_family == AF_INET) ? "IPv4" : "IPv6", ntohs(((struct sockaddr_in *)addr_info->ai_addr)->sin_port)); /* create socket on UDP protocol */ int sockfd = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol); /* handle error */ if (sockfd < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): create_socket_unyte_udp_notif(): cannot create socket\n", config.name, t_data->log_str); exit_gracefully(1); } /* Use SO_REUSEPORT to be able to launch multiple collector on the same address */ #if (defined HAVE_SO_REUSEPORT) int optval = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int)) < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): create_socket_unyte_udp_notif(): cannot set SO_REUSEPORT option on socket\n", config.name, t_data->log_str); exit_gracefully(1); } #endif #if (defined HAVE_SO_BINDTODEVICE) if (config.telemetry_udp_notif_interface) { rc = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, config.telemetry_udp_notif_interface, (socklen_t) strlen(config.telemetry_udp_notif_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, t_data->log_str, errno); } #endif if (config.telemetry_udp_notif_ipv6_only) { int yes=1; rc = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/%s ): setsockopt() failed for IPV6_V6ONLY (errno: %d).\n", config.name, t_data->log_str, errno); } /* Setting socket buffer to default 20 MB */ if (!config.telemetry_pipe_size) { receive_buf_size = DEFAULT_SK_BUFF_SIZE; } else { receive_buf_size = config.telemetry_pipe_size; } if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &receive_buf_size, sizeof(receive_buf_size)) < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): create_socket_unyte_udp_notif(): cannot set buffer size\n", config.name, t_data->log_str); exit_gracefully(1); } if (bind(sockfd, addr_info->ai_addr, (int)addr_info->ai_addrlen) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): create_socket_unyte_udp_notif(): bind() failed\n", config.name, t_data->log_str); close(sockfd); exit_gracefully(1); } /* free addr_info after usage */ freeaddrinfo(addr_info); return sockfd; } #endif pmacct-1.7.8/src/telemetry/Makefile.in0000644000175000017500000006203314354105416016661 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/telemetry ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmtelemetry_la_LIBADD = am_libpmtelemetry_la_OBJECTS = libpmtelemetry_la-telemetry.lo \ libpmtelemetry_la-telemetry_logdump.lo \ libpmtelemetry_la-telemetry_msg.lo \ libpmtelemetry_la-telemetry_util.lo libpmtelemetry_la_OBJECTS = $(am_libpmtelemetry_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmtelemetry_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libpmtelemetry_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmtelemetry_la-telemetry.Plo \ ./$(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Plo \ ./$(DEPDIR)/libpmtelemetry_la-telemetry_msg.Plo \ ./$(DEPDIR)/libpmtelemetry_la-telemetry_util.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmtelemetry_la_SOURCES) DIST_SOURCES = $(libpmtelemetry_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmtelemetry.la libpmtelemetry_la_SOURCES = telemetry.c telemetry_logdump.c telemetry_msg.c \ telemetry_util.c telemetry.h telemetry_logdump.h telemetry_msg.h \ telemetry_util.h libpmtelemetry_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/telemetry/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/telemetry/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmtelemetry.la: $(libpmtelemetry_la_OBJECTS) $(libpmtelemetry_la_DEPENDENCIES) $(EXTRA_libpmtelemetry_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmtelemetry_la_LINK) $(libpmtelemetry_la_OBJECTS) $(libpmtelemetry_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmtelemetry_la-telemetry.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmtelemetry_la-telemetry_msg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmtelemetry_la-telemetry_util.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmtelemetry_la-telemetry.lo: telemetry.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -MT libpmtelemetry_la-telemetry.lo -MD -MP -MF $(DEPDIR)/libpmtelemetry_la-telemetry.Tpo -c -o libpmtelemetry_la-telemetry.lo `test -f 'telemetry.c' || echo '$(srcdir)/'`telemetry.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmtelemetry_la-telemetry.Tpo $(DEPDIR)/libpmtelemetry_la-telemetry.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telemetry.c' object='libpmtelemetry_la-telemetry.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -c -o libpmtelemetry_la-telemetry.lo `test -f 'telemetry.c' || echo '$(srcdir)/'`telemetry.c libpmtelemetry_la-telemetry_logdump.lo: telemetry_logdump.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -MT libpmtelemetry_la-telemetry_logdump.lo -MD -MP -MF $(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Tpo -c -o libpmtelemetry_la-telemetry_logdump.lo `test -f 'telemetry_logdump.c' || echo '$(srcdir)/'`telemetry_logdump.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Tpo $(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telemetry_logdump.c' object='libpmtelemetry_la-telemetry_logdump.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -c -o libpmtelemetry_la-telemetry_logdump.lo `test -f 'telemetry_logdump.c' || echo '$(srcdir)/'`telemetry_logdump.c libpmtelemetry_la-telemetry_msg.lo: telemetry_msg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -MT libpmtelemetry_la-telemetry_msg.lo -MD -MP -MF $(DEPDIR)/libpmtelemetry_la-telemetry_msg.Tpo -c -o libpmtelemetry_la-telemetry_msg.lo `test -f 'telemetry_msg.c' || echo '$(srcdir)/'`telemetry_msg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmtelemetry_la-telemetry_msg.Tpo $(DEPDIR)/libpmtelemetry_la-telemetry_msg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telemetry_msg.c' object='libpmtelemetry_la-telemetry_msg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -c -o libpmtelemetry_la-telemetry_msg.lo `test -f 'telemetry_msg.c' || echo '$(srcdir)/'`telemetry_msg.c libpmtelemetry_la-telemetry_util.lo: telemetry_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -MT libpmtelemetry_la-telemetry_util.lo -MD -MP -MF $(DEPDIR)/libpmtelemetry_la-telemetry_util.Tpo -c -o libpmtelemetry_la-telemetry_util.lo `test -f 'telemetry_util.c' || echo '$(srcdir)/'`telemetry_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmtelemetry_la-telemetry_util.Tpo $(DEPDIR)/libpmtelemetry_la-telemetry_util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telemetry_util.c' object='libpmtelemetry_la-telemetry_util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmtelemetry_la_CFLAGS) $(CFLAGS) -c -o libpmtelemetry_la-telemetry_util.lo `test -f 'telemetry_util.c' || echo '$(srcdir)/'`telemetry_util.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_msg.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_util.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_logdump.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_msg.Plo -rm -f ./$(DEPDIR)/libpmtelemetry_la-telemetry_util.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/telemetry/telemetry_logdump.c0000644000175000017500000005772414354105275020537 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "bgp/bgp.h" #include "bmp/bmp.h" #include "telemetry.h" #include "thread_pool.h" #include "util.h" #if defined WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif /* Functions */ int telemetry_log_msg(telemetry_peer *peer, struct telemetry_data *t_data, telemetry_tag_t *tag, void *log_data, u_int32_t log_data_len, int data_decoder, u_int64_t log_seq, char *event_type, int output) { telemetry_misc_structs *tms; int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = TELEMETRY_LOGDUMP_ET_NONE; if (!peer || !peer->log || !log_data || !log_data_len || !t_data || !event_type) return ERR; tms = bgp_select_misc_db(FUNC_TYPE_TELEMETRY); if (!tms) return ERR; if (!strcmp(event_type, "dump")) etype = TELEMETRY_LOGDUMP_ET_DUMP; else if (!strcmp(event_type, "log")) etype = TELEMETRY_LOGDUMP_ET_LOG; if ((config.telemetry_msglog_amqp_routing_key && etype == TELEMETRY_LOGDUMP_ET_LOG) || (config.telemetry_dump_amqp_routing_key && etype == TELEMETRY_LOGDUMP_ET_DUMP)) { #ifdef WITH_RABBITMQ p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif } if ((config.telemetry_msglog_kafka_topic && etype == TELEMETRY_LOGDUMP_ET_LOG) || (config.telemetry_dump_kafka_topic && etype == TELEMETRY_LOGDUMP_ET_DUMP)) { #ifdef WITH_KAFKA p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); if (config.telemetry_msglog_kafka_partition_key && etype == BGP_LOGDUMP_ET_LOG) { p_kafka_set_key(peer->log->kafka_host, peer->log->partition_key, strlen(peer->log->partition_key)); } #endif } if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON u_char *base64_tdata = NULL; size_t base64_tdata_len = 0; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)log_seq)); json_object_set_new_nocheck(obj, "timestamp", json_string(tms->log_tstamp_str)); } else if (etype == BGP_LOGDUMP_ET_DUMP) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) telemetry_log_seq_get(&tms->log_seq))); json_object_set_new_nocheck(obj, "timestamp", json_string(tms->dump.tstamp_str)); } json_object_set_new_nocheck(obj, "telemetry_node", json_string(peer->addr_str)); json_object_set_new_nocheck(obj, "telemetry_port", json_integer((json_int_t)peer->tcp_port)); if (config.telemetry_tag_map && tag) { telemetry_tag_print_json(obj, tag); } if (data_decoder == TELEMETRY_DATA_DECODER_JSON) { json_error_t json_err; json_t *log_data_obj = json_loads(log_data, 0, &json_err); json_object_set_new_nocheck(obj, "telemetry_data", log_data_obj); json_object_set_new_nocheck(obj, "serialization", json_string("json")); } else if (data_decoder == TELEMETRY_DATA_DECODER_GPB) { base64_tdata = base64_encode(log_data, log_data_len, &base64_tdata_len); if (base64_tdata) { json_object_set_new_nocheck(obj, "telemetry_data", json_string((char *)base64_tdata)); base64_freebuf(base64_tdata); base64_tdata_len = 0; } else json_object_set_new_nocheck(obj, "telemetry_data", json_null()); // XXX: kv = json_pack("{sn}", "telemetry_data"); json_object_set_new_nocheck(obj, "serialization", json_string("gpb")); } else if (data_decoder == TELEMETRY_DATA_DECODER_JSON_STRING) { json_object_set_new_nocheck(obj, "telemetry_data", json_string((char *) log_data)); json_object_set_new_nocheck(obj, "serialization", json_string("json_string")); } else if (data_decoder == TELEMETRY_DATA_DECODER_UNKNOWN) { json_object_set_new_nocheck(obj, "serialization", json_string("unknown")); } if ((config.telemetry_msglog_file && etype == TELEMETRY_LOGDUMP_ET_LOG) || (config.telemetry_dump_file && etype == TELEMETRY_LOGDUMP_ET_DUMP)) write_and_free_json(peer->log->fd, obj); if ((config.telemetry_msglog_amqp_routing_key && etype == TELEMETRY_LOGDUMP_ET_LOG) || (config.telemetry_dump_amqp_routing_key && etype == TELEMETRY_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &tms->writer_id_tokens); #ifdef WITH_RABBITMQ amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); #endif } if ((config.telemetry_msglog_kafka_topic && etype == TELEMETRY_LOGDUMP_ET_LOG) || (config.telemetry_dump_kafka_topic && etype == TELEMETRY_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, &tms->writer_id_tokens); #ifdef WITH_KAFKA kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); #endif } #endif } return (ret | amqp_ret | kafka_ret); } void telemetry_dump_se_ll_append(telemetry_peer *peer, struct telemetry_data *t_data, int data_decoder) { telemetry_misc_structs *tms; telemetry_dump_se_ll *se_ll; telemetry_dump_se_ll_elem *se_ll_elem; if (!peer) return; tms = bgp_select_misc_db(FUNC_TYPE_TELEMETRY); if (!tms) return; assert(peer->bmp_se); se_ll_elem = malloc(sizeof(telemetry_dump_se_ll_elem)); if (!se_ll_elem) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() se_ll_elem structure. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } memset(se_ll_elem, 0, sizeof(telemetry_dump_se_ll_elem)); se_ll_elem->rec.data = malloc(peer->msglen); if (!se_ll_elem->rec.data) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to malloc() se_ll_elem->rec.data structure. Terminating.\n", config.name, t_data->log_str); exit_gracefully(1); } memcpy(se_ll_elem->rec.data, peer->buf.base, peer->msglen); se_ll_elem->rec.len = peer->msglen; se_ll_elem->rec.decoder = data_decoder; se_ll_elem->rec.seq = telemetry_log_seq_get(&tms->log_seq); se_ll = (telemetry_dump_se_ll *) peer->bmp_se; /* append to an empty ll */ if (!se_ll->start) { assert(!se_ll->last); se_ll->start = se_ll_elem; se_ll->last = se_ll_elem; } /* append to an existing ll */ else { assert(se_ll->last); se_ll->last->next = se_ll_elem; se_ll->last = se_ll_elem; } } void telemetry_log_seq_init(u_int64_t *seq) { bgp_peer_log_seq_init(seq); } void telemetry_log_seq_increment(u_int64_t *seq) { bgp_peer_log_seq_increment(seq); } u_int64_t telemetry_log_seq_get(u_int64_t *seq) { return bgp_peer_log_seq_get(seq); } void telemetry_log_seq_set(u_int64_t *seq, u_int64_t value) { bgp_peer_log_seq_set(seq, value); } int telemetry_log_seq_has_ro_bit(u_int64_t *seq) { return bgp_peer_log_seq_has_ro_bit(seq); } int telemetry_peer_log_init(telemetry_peer *peer, telemetry_tag_t *tag, int output, int type) { return bgp_peer_log_init(peer, tag, output, type); } void telemetry_peer_log_dynname(char *new, int newlen, char *old, telemetry_peer *peer) { bgp_peer_log_dynname(new, newlen, old, peer); } int telemetry_peer_dump_init(telemetry_peer *peer, telemetry_tag_t *tag, int output, int type) { return bgp_peer_dump_init(peer, tag, output, type); } int telemetry_peer_dump_close(telemetry_peer *peer, telemetry_tag_t *tag, int output, int type) { return bgp_peer_dump_close(peer, tag, NULL, output, type); } void telemetry_dump_init_peer(telemetry_peer *peer) { bmp_dump_init_peer(peer); } void telemetry_dump_se_ll_destroy(telemetry_dump_se_ll *tdsell) { telemetry_dump_se_ll_elem *se_ll_elem, *se_ll_elem_next; if (!tdsell) return; if (!tdsell->start) return; assert(tdsell->last); for (se_ll_elem = tdsell->start; se_ll_elem; se_ll_elem = se_ll_elem_next) { se_ll_elem_next = se_ll_elem->next; free(se_ll_elem->rec.data); free(se_ll_elem); } tdsell->start = NULL; tdsell->last = NULL; } void telemetry_handle_dump_event(struct telemetry_data *t_data, int max_peers_idx) { telemetry_misc_structs *tms = bgp_select_misc_db(FUNC_TYPE_TELEMETRY); thread_pool_t *telemetry_dump_workers_pool; struct pm_dump_runner pdr[config.telemetry_dump_workers]; u_int64_t dump_seqno; int idx, ret; telemetry_peer *peer; telemetry_dump_se_ll *tdsell; if (!tms) return; /* pre-flight check */ if (!tms->dump_backend_methods || !config.telemetry_dump_refresh_time) { return; } /* Sequencing the dump event */ dump_seqno = telemetry_log_seq_get(&tms->log_seq); telemetry_log_seq_increment(&tms->log_seq); switch (ret = fork()) { case 0: /* Child */ /* we have to ignore signals to avoid loops: because we are already forked */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); pm_setproctitle("%s %s [%s]", config.type, "Core Process -- Telemetry Dump Writer", config.name); config.is_forked = TRUE; /* setting ourselves as read-only */ tms->is_readonly = TRUE; /* Arranging workers data */ distribute_work(pdr, dump_seqno, config.telemetry_dump_workers, max_peers_idx); /* creating the thread pool */ telemetry_dump_workers_pool = allocate_thread_pool(config.telemetry_dump_workers); assert(telemetry_dump_workers_pool); for (idx = 0; idx < config.telemetry_dump_workers; idx++) { if (!pdr[idx].noop) { pdr[idx].extra = t_data; send_to_pool(telemetry_dump_workers_pool, telemetry_dump_event_runner, &pdr[idx]); } } deallocate_thread_pool(&telemetry_dump_workers_pool); exit_gracefully(0); default: /* Parent */ if (ret == -1) { /* Something went wrong */ Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork telemetry dump writer: %s\n", config.name, t_data->log_str, strerror(errno)); } /* destroy bmp_se linked-list content after dump event */ for (peer = NULL, idx = 0; idx < max_peers_idx; idx++) { if (telemetry_peers[idx].fd) { peer = &telemetry_peers[idx]; tdsell = peer->bmp_se; if (tdsell && tdsell->start && abs((int) pm_djb2_string_hash((unsigned char *) peer->addr_str)) % config.telemetry_dump_time_slots == tms->current_slot) { telemetry_dump_se_ll_destroy(tdsell); } } } break; } tms->current_slot = (tms->current_slot + 1) % config.telemetry_dump_time_slots; } int telemetry_dump_event_runner(struct pm_dump_runner *pdr) { telemetry_misc_structs *tms = bgp_select_misc_db(FUNC_TYPE_TELEMETRY); struct telemetry_data *t_data; char current_filename[SRVBUFLEN], last_filename[SRVBUFLEN], tmpbuf[SRVBUFLEN]; char latest_filename[SRVBUFLEN], dump_partition_key[SRVBUFLEN], *fd_buf = NULL; int peers_idx, duration, tables_num; pid_t dumper_pid; time_t start; u_int64_t dump_elems = 0, dump_seqno = pdr->seq; telemetry_peer *peer, *saved_peer; telemetry_dump_se_ll *tdsell; telemetry_peer_log peer_log; assert(pdr); assert(pdr->extra); t_data = pdr->extra; #ifdef WITH_RABBITMQ struct p_amqp_host telemetry_dump_amqp_host; #endif #ifdef WITH_KAFKA struct p_kafka_host telemetry_dump_kafka_host; #endif memset(last_filename, 0, sizeof(last_filename)); memset(current_filename, 0, sizeof(current_filename)); fd_buf = malloc(OUTPUT_FILE_BUFSZ); telemetry_log_seq_set(&tms->log_seq, dump_seqno); #ifdef WITH_RABBITMQ if (config.telemetry_dump_amqp_routing_key) { int ret; telemetry_dump_init_amqp_host(&telemetry_dump_amqp_host); ret = p_amqp_connect_to_publish(&telemetry_dump_amqp_host); if (ret) exit_gracefully(ret); } #endif #ifdef WITH_KAFKA if (config.telemetry_dump_kafka_topic) { int ret; ret = telemetry_dump_init_kafka_host(&telemetry_dump_kafka_host); if (ret) exit_gracefully(ret); } #endif dumper_pid = getpid(); Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping telemetry data - START (PID: %u RID: %u) ***\n", config.name, t_data->log_str, dumper_pid, pdr->id); start = time(NULL); tables_num = 0; if (config.telemetry_dump_time_slots > 1) { Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping telemetry data - SLOT %d / %d ***\n", config.name, tms->log_str, tms->current_slot + 1, config.telemetry_dump_time_slots); } for (peer = NULL, saved_peer = NULL, peers_idx = pdr->first; peers_idx <= pdr->last; peers_idx++) { if (telemetry_peers[peers_idx].fd) { char peer_addr[INET6_ADDRSTRLEN]; peer = &telemetry_peers[peers_idx]; addr_to_str(peer_addr, &(peer->addr)); int telemetry_slot = abs((int) pm_djb2_string_hash((unsigned char *) peer_addr)) % config.telemetry_dump_time_slots; if (telemetry_slot == tms->current_slot) { peer->log = &peer_log; /* abusing telemetry_peer a bit, but we are in a child */ tdsell = peer->bmp_se; if (config.telemetry_dump_file) telemetry_peer_log_dynname(current_filename, SRVBUFLEN, config.telemetry_dump_file, peer); if (config.telemetry_dump_amqp_routing_key) telemetry_peer_log_dynname(current_filename, SRVBUFLEN, config.telemetry_dump_amqp_routing_key, peer); if (config.telemetry_dump_kafka_topic) telemetry_peer_log_dynname(current_filename, SRVBUFLEN, config.telemetry_dump_kafka_topic, peer); if (config.telemetry_dump_kafka_partition_key) telemetry_peer_log_dynname(dump_partition_key, SRVBUFLEN, config.telemetry_dump_kafka_partition_key, peer); pm_strftime_same(current_filename, SRVBUFLEN, tmpbuf, &tms->dump.tstamp.tv_sec, config.timestamps_utc); /* we close last_filename and open current_filename in case they differ; we are safe with this approach until time and Streaming Telemetry node (IP, port) are the only variables supported as part of telemetry_dump_file. */ if (config.telemetry_dump_file) { if (strcmp(last_filename, current_filename)) { if (saved_peer && saved_peer->log && strlen(last_filename)) { close_output_file(saved_peer->log->fd); if (config.telemetry_dump_latest_file) { telemetry_peer_log_dynname(latest_filename, SRVBUFLEN, config.telemetry_dump_latest_file, saved_peer); link_latest_output_file(latest_filename, last_filename); } } peer->log->fd = open_output_file(current_filename, "w", TRUE); if (fd_buf) { if (setvbuf(peer->log->fd, fd_buf, _IOFBF, OUTPUT_FILE_BUFSZ)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] setvbuf() failed: %s\n", config.name, t_data->log_str, current_filename, strerror(errno)); } else memset(fd_buf, 0, OUTPUT_FILE_BUFSZ); } } } /* a bit pedantic maybe but should come at little cost and emulating telemetry_dump_file behaviour will work */ #ifdef WITH_RABBITMQ if (config.telemetry_dump_amqp_routing_key) { peer->log->amqp_host = &telemetry_dump_amqp_host; strcpy(peer->log->filename, current_filename); } #endif #ifdef WITH_KAFKA if (config.telemetry_dump_kafka_topic) { peer->log->kafka_host = &telemetry_dump_kafka_host; strcpy(peer->log->filename, current_filename); if (config.telemetry_dump_kafka_partition_key) { p_kafka_set_key(peer->log->kafka_host, dump_partition_key, strlen(dump_partition_key)); } } #endif /* Being telemetry_tag_map limited to 'ip' key lookups, this is finely placed here. Should further lookups be possible, this may be very possibly moved inside the loop */ if (config.telemetry_tag_map) { telemetry_tag_init_find(peer, (struct sockaddr *) &telemetry_logdump_tag_peer, &telemetry_logdump_tag); telemetry_tag_find((struct id_table *)telemetry_logdump_tag.tag_table, &telemetry_logdump_tag, &telemetry_logdump_tag.tag, NULL); } telemetry_peer_dump_init(peer, &telemetry_logdump_tag, config.telemetry_dump_output, FUNC_TYPE_TELEMETRY); if (tdsell && tdsell->start) { telemetry_dump_se_ll_elem *se_ll_elem; char event_type[] = "dump"; for (se_ll_elem = tdsell->start; se_ll_elem; se_ll_elem = se_ll_elem->next) { telemetry_log_msg(peer, t_data, &telemetry_logdump_tag, se_ll_elem->rec.data, se_ll_elem->rec.len, se_ll_elem->rec.decoder, se_ll_elem->rec.seq, event_type, config.telemetry_dump_output); dump_elems++; } } saved_peer = peer; strlcpy(last_filename, current_filename, SRVBUFLEN); telemetry_peer_dump_close(peer, &telemetry_logdump_tag, config.telemetry_dump_output, FUNC_TYPE_TELEMETRY); tables_num++; } } } #ifdef WITH_RABBITMQ if (config.telemetry_dump_amqp_routing_key) { p_amqp_close(&telemetry_dump_amqp_host, FALSE); } #endif #ifdef WITH_KAFKA if (config.telemetry_dump_kafka_topic) { p_kafka_close(&telemetry_dump_kafka_host, FALSE); } #endif if (config.telemetry_dump_file && peer) { close_output_file(peer->log->fd); } if (config.telemetry_dump_latest_file && peer) { telemetry_peer_log_dynname(latest_filename, SRVBUFLEN, config.telemetry_dump_latest_file, peer); link_latest_output_file(latest_filename, last_filename); } duration = time(NULL)-start; Log(LOG_INFO, "INFO ( %s/%s ): *** Dumping telemetry data - END (PID: %u RID: %u PEERS: %u ENTRIES: %" PRIu64 " ET: %u) ***\n", config.name, t_data->log_str, dumper_pid, pdr->id, tables_num, dump_elems, duration); return FALSE; } #if defined WITH_RABBITMQ void telemetry_daemon_msglog_init_amqp_host() { p_amqp_init_host(&telemetry_daemon_msglog_amqp_host); if (!config.telemetry_msglog_amqp_user) config.telemetry_msglog_amqp_user = rabbitmq_user; if (!config.telemetry_msglog_amqp_passwd) config.telemetry_msglog_amqp_passwd = rabbitmq_pwd; if (!config.telemetry_msglog_amqp_exchange) config.telemetry_msglog_amqp_exchange = default_amqp_exchange; if (!config.telemetry_msglog_amqp_exchange_type) config.telemetry_msglog_amqp_exchange_type = default_amqp_exchange_type; if (!config.telemetry_msglog_amqp_host) config.telemetry_msglog_amqp_host = default_amqp_host; if (!config.telemetry_msglog_amqp_vhost) config.telemetry_msglog_amqp_vhost = default_amqp_vhost; if (!config.telemetry_msglog_amqp_retry) config.telemetry_msglog_amqp_retry = AMQP_DEFAULT_RETRY; p_amqp_set_user(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_user); p_amqp_set_passwd(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_passwd); p_amqp_set_exchange(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_exchange); p_amqp_set_exchange_type(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_exchange_type); p_amqp_set_host(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_host); p_amqp_set_vhost(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_vhost); p_amqp_set_persistent_msg(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_persistent_msg); p_amqp_set_frame_max(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_frame_max); p_amqp_set_content_type_json(&telemetry_daemon_msglog_amqp_host); p_amqp_set_heartbeat_interval(&telemetry_daemon_msglog_amqp_host, config.telemetry_msglog_amqp_heartbeat_interval); P_broker_timers_set_retry_interval(&telemetry_daemon_msglog_amqp_host.btimers, config.telemetry_msglog_amqp_retry); } #else void telemetry_daemon_msglog_init_amqp_host() { } #endif #if defined WITH_RABBITMQ void telemetry_dump_init_amqp_host(void *tdah) { struct p_amqp_host *telemetry_dump_amqp_host = tdah; p_amqp_init_host(telemetry_dump_amqp_host); if (!config.telemetry_dump_amqp_user) config.telemetry_dump_amqp_user = rabbitmq_user; if (!config.telemetry_dump_amqp_passwd) config.telemetry_dump_amqp_passwd = rabbitmq_pwd; if (!config.telemetry_dump_amqp_exchange) config.telemetry_dump_amqp_exchange = default_amqp_exchange; if (!config.telemetry_dump_amqp_exchange_type) config.telemetry_dump_amqp_exchange_type = default_amqp_exchange_type; if (!config.telemetry_dump_amqp_host) config.telemetry_dump_amqp_host = default_amqp_host; if (!config.telemetry_dump_amqp_vhost) config.telemetry_dump_amqp_vhost = default_amqp_vhost; p_amqp_set_user(telemetry_dump_amqp_host, config.telemetry_dump_amqp_user); p_amqp_set_passwd(telemetry_dump_amqp_host, config.telemetry_dump_amqp_passwd); p_amqp_set_exchange(telemetry_dump_amqp_host, config.telemetry_dump_amqp_exchange); p_amqp_set_exchange_type(telemetry_dump_amqp_host, config.telemetry_dump_amqp_exchange_type); p_amqp_set_host(telemetry_dump_amqp_host, config.telemetry_dump_amqp_host); p_amqp_set_vhost(telemetry_dump_amqp_host, config.telemetry_dump_amqp_vhost); p_amqp_set_persistent_msg(telemetry_dump_amqp_host, config.telemetry_dump_amqp_persistent_msg); p_amqp_set_frame_max(telemetry_dump_amqp_host, config.telemetry_dump_amqp_frame_max); p_amqp_set_content_type_json(telemetry_dump_amqp_host); p_amqp_set_heartbeat_interval(telemetry_dump_amqp_host, config.telemetry_dump_amqp_heartbeat_interval); } #else void telemetry_dump_init_amqp_host(void *tdkh) { } #endif #if defined WITH_KAFKA int telemetry_daemon_msglog_init_kafka_host() { int ret; p_kafka_init_host(&telemetry_daemon_msglog_kafka_host, config.telemetry_msglog_kafka_config_file); ret = p_kafka_connect_to_produce(&telemetry_daemon_msglog_kafka_host); if (!config.telemetry_msglog_kafka_broker_host) config.telemetry_msglog_kafka_broker_host = default_kafka_broker_host; if (!config.telemetry_msglog_kafka_broker_port) config.telemetry_msglog_kafka_broker_port = default_kafka_broker_port; if (!config.telemetry_msglog_kafka_retry) config.telemetry_msglog_kafka_retry = PM_KAFKA_DEFAULT_RETRY; p_kafka_set_broker(&telemetry_daemon_msglog_kafka_host, config.telemetry_msglog_kafka_broker_host, config.telemetry_msglog_kafka_broker_port); p_kafka_set_topic(&telemetry_daemon_msglog_kafka_host, config.telemetry_msglog_kafka_topic); p_kafka_set_partition(&telemetry_daemon_msglog_kafka_host, config.telemetry_msglog_kafka_partition); p_kafka_set_key(&telemetry_daemon_msglog_kafka_host, config.telemetry_msglog_kafka_partition_key, config.telemetry_msglog_kafka_partition_keylen); p_kafka_set_content_type(&telemetry_daemon_msglog_kafka_host, PM_KAFKA_CNT_TYPE_STR); P_broker_timers_set_retry_interval(&telemetry_daemon_msglog_kafka_host.btimers, config.telemetry_msglog_kafka_retry); return ret; } #else int telemetry_daemon_msglog_init_kafka_host() { return ERR; } #endif #if defined WITH_KAFKA int telemetry_dump_init_kafka_host(void *tdkh) { struct p_kafka_host *telemetry_dump_kafka_host = tdkh; int ret; p_kafka_init_host(telemetry_dump_kafka_host, config.telemetry_dump_kafka_config_file); ret = p_kafka_connect_to_produce(telemetry_dump_kafka_host); if (!config.telemetry_dump_kafka_broker_host) config.telemetry_dump_kafka_broker_host = default_kafka_broker_host; if (!config.telemetry_dump_kafka_broker_port) config.telemetry_dump_kafka_broker_port = default_kafka_broker_port; p_kafka_set_broker(telemetry_dump_kafka_host, config.telemetry_dump_kafka_broker_host, config.telemetry_dump_kafka_broker_port); p_kafka_set_topic(telemetry_dump_kafka_host, config.telemetry_dump_kafka_topic); p_kafka_set_partition(telemetry_dump_kafka_host, config.telemetry_dump_kafka_partition); p_kafka_set_key(telemetry_dump_kafka_host, config.telemetry_dump_kafka_partition_key, config.telemetry_dump_kafka_partition_keylen); p_kafka_set_content_type(telemetry_dump_kafka_host, PM_KAFKA_CNT_TYPE_STR); return ret; } #else int telemetry_dump_init_kafka_host(void *tdkh) { return ERR; } #endif #ifdef WITH_JANSSON void telemetry_tag_print_json(json_t *obj, telemetry_tag_t *tag) { bgp_tag_print_json(obj, tag); } #endif pmacct-1.7.8/src/telemetry/Makefile.am0000644000175000017500000000044014354105275016645 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmtelemetry.la libpmtelemetry_la_SOURCES = telemetry.c telemetry_logdump.c telemetry_msg.c \ telemetry_util.c telemetry.h telemetry_logdump.h telemetry_msg.h \ telemetry_util.h libpmtelemetry_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/signals.c0000644000175000017500000001612714354105275014414 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "bgp/bgp.h" /* extern */ extern struct plugins_list_entry *plugin_list; /* functions */ void startup_handle_falling_child() { int i, j; j = waitpid(-1, 0, WNOHANG); for (i = 0; i < MAX_N_PLUGINS; i++) { if (!failed_plugins[i]) { failed_plugins[i] = j; break; } } } void handle_falling_child() { struct plugins_list_entry *list = NULL; int j, ret; /* we first scan failed_plugins[] array for plugins failed during the startup phase: when we are building plugins_list, we cannot arbitrarily delete nodes (plugins) from it */ for (j = 0; j < MAX_N_PLUGINS; j++) { if (failed_plugins[j]) { list = search_plugin_by_pid(failed_plugins[j]); if (list) { Log(LOG_WARNING, "WARN ( %s/%s ): connection lost to '%s-%s'; closing connection.\n", config.name, config.type, list->name, list->type.string); close(list->pipe[1]); delete_pipe_channel(list->pipe[1]); ret = delete_plugin_by_id(list->id); if (!ret) { Log(LOG_WARNING, "WARN ( %s/%s ): no more plugins active. Shutting down.\n", config.name, config.type); if (config.pidfile) remove_pid_file(config.pidfile); exit(1); } else { if (config.plugin_exit_any) { Log(LOG_WARNING, "WARN ( %s/%s ): one or more plugins did exit (plugin_exit_any). Shutting down.\n", config.name, config.type); if (config.pidfile) remove_pid_file(config.pidfile); exit_all(1); } } } failed_plugins[j] = 0; } else break; } j = waitpid(-1, 0, WNOHANG); list = search_plugin_by_pid(j); if (list) { Log(LOG_WARNING, "WARN ( %s/%s ): connection lost to '%s-%s'; closing connection.\n", config.name, config.type, list->name, list->type.string); close(list->pipe[1]); delete_pipe_channel(list->pipe[1]); ret = delete_plugin_by_id(list->id); if (!ret) { Log(LOG_WARNING, "WARN ( %s/%s ): no more plugins active. Shutting down.\n", config.name, config.type); if (config.pidfile) remove_pid_file(config.pidfile); exit(1); } else { if (config.plugin_exit_any) { Log(LOG_WARNING, "WARN ( %s/%s ): one or more plugins did exit (plugin_exit_any). Shutting down.\n", config.name, config.type); if (config.pidfile) remove_pid_file(config.pidfile); exit_all(1); } } } } void ignore_falling_child() { pid_t cpid; int status; while ((cpid = waitpid(-1, &status, WNOHANG)) > 0) { if (!WIFEXITED(status)) { Log(LOG_WARNING, "WARN ( %s/%s ): Abnormal exit status detected for child PID %u\n", config.name, config.type, cpid); } } } void PM_sigint_handler(int signum) { struct plugins_list_entry *list = plugins_list; char shutdown_msg[] = "pmacct received SIGINT - shutting down"; if (config.acct_type == ACCT_PMBGP || config.bgp_daemon == BGP_DAEMON_ONLINE) { int idx; for (idx = 0; idx < config.bgp_daemon_max_peers; idx++) { if (peers[idx].fd) bgp_peer_close(&peers[idx], FUNC_TYPE_BGP, TRUE, TRUE, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, shutdown_msg); } } if (config.syslog) closelog(); /* We are about to exit, but it may take a while - because of the wait() call. Let's release collector's socket to improve turn- around times when restarting the daemon */ if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { close(config.sock); if (config.nfacctd_templates_sock) { close(config.nfacctd_templates_sock); } #ifdef WITH_GNUTLS if (config.nfacctd_dtls_sock) { pm_dtls_server_bye(NULL); close(config.nfacctd_dtls_sock); } #endif } fill_pipe_buffer(); sleep(2); /* XXX: we should really choose an adaptive value here. It should be closely bound to, say, biggest plugin_buffer_size value */ while (list) { if (memcmp(list->type.string, "core", sizeof("core"))) kill(list->pid, SIGINT); list = list->next; } wait(NULL); Log(LOG_INFO, "INFO ( %s/%s ): OK, Exiting ...\n", config.name, config.type); if (config.acct_type == ACCT_PM && !config.uacctd_group /* XXX */) { int device_idx; if (config.pcap_if) { printf("NOTICE ( %s/%s ): +++\n", config.name, config.type); for (device_idx = 0; device_idx < devices.num; device_idx++) { if (pcap_stats(devices.list[device_idx].dev_desc, &ps) < 0) { printf("INFO ( %s/%s ): [%s,%u] error='pcap_stats(): %s'\n", config.name, config.type, devices.list[device_idx].str, devices.list[device_idx].id, pcap_geterr(devices.list[device_idx].dev_desc)); } printf("NOTICE ( %s/%s ): [%s,%u] received_packets=%u dropped_packets=%u\n", config.name, config.type, devices.list[device_idx].str, devices.list[device_idx].id, ps.ps_recv, ps.ps_drop); } printf("NOTICE ( %s/%s ): ---\n", config.name, config.type); } } if (config.pidfile) remove_pid_file(config.pidfile); if (config.propagate_signals) signal_kittens(signum, TRUE); exit(0); } void PM_sigalrm_noop_handler(int signum) { /* noop */ } void reload(int signum) { reload_log = TRUE; if (config.bgp_daemon_msglog_file) reload_log_bgp_thread = TRUE; if (config.bmp_daemon_msglog_file) reload_log_bmp_thread = TRUE; if (config.sfacctd_counter_file) reload_log_sf_cnt = TRUE; if (config.telemetry_msglog_file) reload_log_telemetry_thread = TRUE; if (config.propagate_signals) signal_kittens(signum, TRUE); } void push_stats(int signum) { if (config.acct_type == ACCT_PM) { time_t now = time(NULL); PM_print_stats(now); } else if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { print_stats = TRUE; } if (config.propagate_signals) signal_kittens(signum, TRUE); } void reload_maps(int signum) { reload_map = FALSE; reload_map_bgp_thread = FALSE; reload_map_bmp_thread = FALSE; reload_map_rpki_thread = FALSE; reload_map_exec_plugins = FALSE; reload_geoipv2_file = FALSE; if (config.maps_refresh) { reload_map = TRUE; reload_map_bgp_thread = TRUE; reload_map_bmp_thread = TRUE; reload_map_rpki_thread = TRUE; reload_map_exec_plugins = TRUE; reload_geoipv2_file = TRUE; if (config.acct_type == ACCT_PM) reload_map_pmacctd = TRUE; } if (config.propagate_signals) { signal_kittens(signum, TRUE); } } pmacct-1.7.8/src/tee_plugin/0000755000175000017500000000000014354105416014731 5ustar paolopaolopmacct-1.7.8/src/tee_plugin/tee_recvs-data.h0000644000175000017500000000250214354105275017772 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2018 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ const struct _map_dictionary_line tee_recvs_map_dictionary[] = { {"id", tee_recvs_map_id_handler}, {"ip", tee_recvs_map_ip_handler}, {"tag", tee_recvs_map_tag_handler}, {"balance-alg", tee_recvs_map_balance_alg_handler}, {"src_port", tee_recvs_map_src_port_handler}, #ifdef WITH_KAFKA {"kafka_broker", tee_recvs_map_kafka_broker_handler}, {"kafka_topic", tee_recvs_map_kafka_topic_handler}, #endif #ifdef WITH_ZMQ {"zmq_address", tee_recvs_map_zmq_address_handler}, #endif {"", NULL} }; pmacct-1.7.8/src/tee_plugin/tee_plugin.h0000644000175000017500000000730514354105275017245 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TEE_PLUGIN_H #define TEE_PLUGIN_H /* includes */ #include #include #include /* defines */ #define DEFAULT_TEE_REFRESH_TIME 10 #define MAX_TEE_POOLS 128 #define MAX_TEE_RECEIVERS 32 #define TEE_BALANCE_NONE 0 #define TEE_BALANCE_RR 1 #define TEE_BALANCE_HASH_AGENT 2 #define TEE_BALANCE_HASH_TAG 3 typedef struct tee_receiver *(*tee_balance_algorithm) (void *, struct pkt_msg *); /* structures */ struct tee_receiver { struct sockaddr_storage dest; socklen_t dest_len; int fd; }; struct tee_balance { int type; /* Balancing algorithm: id */ tee_balance_algorithm func; /* Balancing algorithm: handler */ int next; /* RR algorithm: next receiver */ }; struct tee_receivers_pool { struct tee_receiver *receivers; u_int32_t id; /* Pool ID */ struct pretag_filter tag_filter; /* filter datagrams basing on a pre_tag_map */ struct tee_balance balance; /* balance datagrams basing on supported algorithm */ u_int16_t src_port; /* Non transparent mode: source UDP port to use for replication */ char kafka_broker[SRVBUFLEN]; /* Emitting to Kafka: broker string */ char kafka_topic[SRVBUFLEN]; /* Emitting to Kafka: topic */ #ifdef WITH_KAFKA struct p_kafka_host kafka_host; /* Emitting to Kafka: librdkafka structs */ #endif char zmq_address[SHORTBUFLEN]; /* Emitting via ZeroMQ: server address */ #ifdef WITH_ZMQ struct p_zmq_host zmq_host; /* Emitting via ZeroMQ: libzmq structs */ #endif int num; /* Number of receivers in the pool */ }; struct tee_receivers { struct tee_receivers_pool *pools; int num; }; /* prototypes */ extern void Tee_exit_now(int); extern void Tee_init_socks(); extern void Tee_destroy_recvs(); extern size_t Tee_craft_transparent_msg(struct pkt_msg *, struct sockaddr *); extern void Tee_send(struct pkt_msg *, struct sockaddr *, int, int); extern int Tee_prepare_sock(struct sockaddr *, socklen_t, char *, u_int16_t, int, int); extern int Tee_parse_hostport(const char *, struct sockaddr *, socklen_t *, int); extern struct tee_receiver *Tee_rr_balance(void *, struct pkt_msg *); extern struct tee_receiver *Tee_hash_agent_balance(void *, struct pkt_msg *); extern struct tee_receiver *Tee_hash_agent_crc32(void *, struct pkt_msg *); extern struct tee_receiver *Tee_hash_tag_balance(void *, struct pkt_msg *); extern void Tee_select_templates(unsigned char *, int, int, unsigned char *, int *); #ifdef WITH_KAFKA extern void Tee_kafka_send(struct pkt_msg *, struct tee_receivers_pool *); extern void Tee_init_kafka_host(struct p_kafka_host *, char *, char *, u_int32_t); #endif #ifdef WITH_ZMQ extern void Tee_zmq_send(struct pkt_msg *, struct tee_receivers_pool *); extern void Tee_init_zmq_host(struct p_zmq_host *, char *, u_int32_t); #endif /* global variables */ extern char tee_send_buf[65535]; extern struct tee_receivers receivers; extern int err_cant_bridge_af; #endif //TEE_PLUGIN_H pmacct-1.7.8/src/tee_plugin/tee_plugin.c0000644000175000017500000007226214354105275017244 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #ifdef WITH_KAFKA #include "kafka_common.h" #endif #include "pmacct-data.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "tee_plugin.h" #include "nfacctd.h" #include "crc32.h" /* Global variables */ char tee_send_buf[65535]; struct tee_receivers receivers; void tee_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_msg *msg; unsigned char *pipebuf; struct pollfd pfd; int refresh_timeout, ret, pool_idx, recv_idx, recv_budget, poll_bypass; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; unsigned char *dataptr; struct tee_receiver *target = NULL; struct plugin_requests req; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "Tee Plugin", config.name); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } /* signal handling */ signal(SIGINT, Tee_exit_now); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); /* sets to true the reload_maps flag */ signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); if (config.tee_transparent && getuid() != 0 && !config.pmacctd_nonroot) { Log(LOG_ERR, "ERROR ( %s/%s ): Transparent mode requires super-user permissions. Exiting ...\n", config.name, config.type); exit_gracefully(1); } if (!config.tee_receivers) { Log(LOG_ERR, "ERROR ( %s/%s ): No receivers specified: tee_receivers is required. Exiting ...\n", config.name, config.type); exit_gracefully(1); } memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); memset(&receivers, 0, sizeof(receivers)); memset(&req, 0, sizeof(req)); reload_map = FALSE; /* Setting up pools */ if (!config.tee_max_receiver_pools) config.tee_max_receiver_pools = MAX_TEE_POOLS; receivers.pools = malloc((config.tee_max_receiver_pools+1)*sizeof(struct tee_receivers_pool)); if (!receivers.pools) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate receiver pools. Exiting ...\n", config.name, config.type); exit_gracefully(1); } else memset(receivers.pools, 0, (config.tee_max_receiver_pools+1)*sizeof(struct tee_receivers_pool)); /* Setting up receivers per pool */ if (!config.tee_max_receivers) config.tee_max_receivers = MAX_TEE_RECEIVERS; for (pool_idx = 0; pool_idx < config.tee_max_receiver_pools; pool_idx++) { receivers.pools[pool_idx].receivers = malloc(config.tee_max_receivers*sizeof(struct tee_receiver)); if (!receivers.pools[pool_idx].receivers) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate receivers for pool #%u. Exiting ...\n", config.name, config.type, pool_idx); exit_gracefully(1); } else memset(receivers.pools[pool_idx].receivers, 0, config.tee_max_receivers*sizeof(struct tee_receiver)); } if (config.tee_receivers) { int recvs_allocated = FALSE; req.key_value_table = (void *) &receivers; load_id_file(MAP_TEE_RECVS, config.tee_receivers, NULL, &req, &recvs_allocated); } config.sql_refresh_time = DEFAULT_TEE_REFRESH_TIME; refresh_timeout = config.sql_refresh_time*1000; pipebuf = (unsigned char *) pm_malloc(config.buffer_size); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); memset(pipebuf, 0, config.buffer_size); /* Arrange send socket */ Tee_init_socks(); #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif /* plugin main loop */ for (;;) { poll_again: status->wakeup = TRUE; poll_bypass = FALSE; pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); if (ret < 0) goto poll_again; poll_ops: if (reload_map) { if (config.tee_receivers) { int recvs_allocated = FALSE; Tee_destroy_recvs(); load_id_file(MAP_TEE_RECVS, config.tee_receivers, NULL, &req, &recvs_allocated); Tee_init_socks(); } reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } switch (ret) { case 0: /* timeout */ /* reserved for future since we don't currently cache/batch/etc */ break; default: /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto poll_again; } #endif msg = (struct pkt_msg *) (pipebuf+sizeof(struct ch_buf_hdr)); msg->payload = (pipebuf+sizeof(struct ch_buf_hdr)+PmsgSz); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (pool_idx = 0; pool_idx < receivers.num; pool_idx++) { if (msg->bcast || !evaluate_tags(&receivers.pools[pool_idx].tag_filter, msg->tag)) { if (!receivers.pools[pool_idx].balance.func) { for (recv_idx = 0; recv_idx < receivers.pools[pool_idx].num; recv_idx++) { target = &receivers.pools[pool_idx].receivers[recv_idx]; Tee_send(msg, (struct sockaddr *) &target->dest, target->fd, config.tee_transparent); } #ifdef WITH_KAFKA /* Checking the handler is the most light weight op we can perform in order to ensure we are in business with the Kafka broker */ if (p_kafka_get_handler(&receivers.pools[pool_idx].kafka_host)) { Tee_kafka_send(msg, &receivers.pools[pool_idx]); } #endif #ifdef WITH_ZMQ if (p_zmq_get_sock(&receivers.pools[pool_idx].zmq_host)) { Tee_zmq_send(msg, &receivers.pools[pool_idx]); } #endif } else { target = receivers.pools[pool_idx].balance.func(&receivers.pools[pool_idx], msg); Tee_send(msg, (struct sockaddr *) &target->dest, target->fd, config.tee_transparent); } } } ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) msg; dataptr += (PmsgSz + msg->len); msg = (struct pkt_msg *) dataptr; msg->payload = (dataptr + PmsgSz); } } recv_budget++; goto read_data; } } } void Tee_exit_now(int signum) { wait(NULL); exit_gracefully(0); } size_t Tee_craft_transparent_msg(struct pkt_msg *msg, struct sockaddr *target) { char *buf_ptr = tee_send_buf; struct sockaddr *sa = (struct sockaddr *) &msg->agent; struct sockaddr_in *sa4 = (struct sockaddr_in *) &msg->agent; struct pm_iphdr *i4h = (struct pm_iphdr *) buf_ptr; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &msg->agent; struct ip6_hdr *i6h = (struct ip6_hdr *) buf_ptr; struct pm_udphdr *uh; size_t msglen = 0; if (sa->sa_family == target->sa_family) { /* UDP header first */ if (target->sa_family == AF_INET) { buf_ptr += IP4HdrSz; uh = (struct pm_udphdr *) buf_ptr; uh->uh_sport = sa4->sin_port; uh->uh_dport = ((struct sockaddr_in *)target)->sin_port; } else if (target->sa_family == AF_INET6) { buf_ptr += IP6HdrSz; uh = (struct pm_udphdr *) buf_ptr; uh->uh_sport = sa6->sin6_port; uh->uh_dport = ((struct sockaddr_in6 *)target)->sin6_port; } else { assert(0); return msglen; } uh->uh_ulen = htons(msg->len+UDPHdrSz); uh->uh_sum = 0; /* IP header then */ if (target->sa_family == AF_INET) { i4h->ip_vhl = 4; i4h->ip_vhl <<= 4; i4h->ip_vhl |= (IP4HdrSz/4); if (config.nfprobe_ipprec) { int opt = config.nfprobe_ipprec << 5; i4h->ip_tos = opt; } else i4h->ip_tos = 0; #if !defined BSD i4h->ip_len = htons(IP4HdrSz+UDPHdrSz+msg->len); #else i4h->ip_len = IP4HdrSz+UDPHdrSz+msg->len; #endif i4h->ip_id = 0; i4h->ip_off = 0; i4h->ip_ttl = 255; i4h->ip_p = IPPROTO_UDP; i4h->ip_sum = 0; i4h->ip_src.s_addr = sa4->sin_addr.s_addr; i4h->ip_dst.s_addr = ((struct sockaddr_in *)target)->sin_addr.s_addr; msglen = (IP4HdrSz + UDPHdrSz + msg->len); } else if (target->sa_family == AF_INET6) { i6h->ip6_vfc = 6; i6h->ip6_vfc <<= 4; i6h->ip6_plen = htons(UDPHdrSz+msg->len); i6h->ip6_nxt = IPPROTO_UDP; i6h->ip6_hlim = 255; memcpy(&i6h->ip6_src, &sa6->sin6_addr, IP6AddrSz); memcpy(&i6h->ip6_dst, &((struct sockaddr_in6 *)target)->sin6_addr, IP6AddrSz); msglen = (IP6HdrSz + UDPHdrSz + msg->len); } /* Put everything together and send */ buf_ptr += UDPHdrSz; memcpy(buf_ptr, msg->payload, msg->len); /* If IPv6: last thing last compute the checksum */ if (target->sa_family == AF_INET6) { uh->uh_sum = pm_udp6_checksum(i6h, uh, msg->payload, msg->len); } } else { time_t now = time(NULL); if (!log_notification_isset(&log_notifications.tee_plugin_cant_bridge_af, now)) { Log(LOG_ERR, "ERROR ( %s/%s ): Can't bridge Address Families when in transparent mode\n", config.name, config.type); log_notification_set(&log_notifications.tee_plugin_cant_bridge_af, now, 60); } } return msglen; } void Tee_send(struct pkt_msg *msg, struct sockaddr *target, int fd, int transparent) { struct host_addr r; char recv_addr[50]; u_int16_t recv_port; if (config.debug) { char *flow = NULL, netflow[] = "NetFlow/IPFIX", sflow[] = "sFlow"; struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)msg, &a, &agent_port); addr_to_str(agent_addr, &a); sa_to_addr((struct sockaddr *)target, &r, &recv_port); addr_to_str(recv_addr, &r); if (config.acct_type == ACCT_NF) flow = netflow; else if (config.acct_type == ACCT_SF) flow = sflow; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending %s packet from [%s:%u] seqno [%u] to [%s:%u]\n", config.name, config.type, flow, agent_addr, agent_port, msg->seqno, recv_addr, recv_port); } if (!transparent) { if (send(fd, msg->payload, msg->len, 0) == -1) { struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)msg, &a, &agent_port); addr_to_str(agent_addr, &a); sa_to_addr((struct sockaddr *)target, &r, &recv_port); addr_to_str(recv_addr, &r); Log(LOG_ERR, "ERROR ( %s/%s ): send() from [%s:%u] seqno [%u] to [%s:%u] failed (%s)\n", config.name, config.type, agent_addr, agent_port, msg->seqno, recv_addr, recv_port, strerror(errno)); } } else { size_t msglen; msglen = Tee_craft_transparent_msg(msg, target); if (msglen && send(fd, tee_send_buf, msglen, 0) == -1) { struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)msg, &a, &agent_port); addr_to_str(agent_addr, &a); sa_to_addr((struct sockaddr *)target, &r, &recv_port); addr_to_str(recv_addr, &r); Log(LOG_ERR, "ERROR ( %s/%s ): raw send() from [%s:%u] seqno [%u] to [%s:%u] failed (%s)\n", config.name, config.type, agent_addr, agent_port, msg->seqno, recv_addr, recv_port, strerror(errno)); } } } #ifdef WITH_KAFKA void Tee_kafka_send(struct pkt_msg *msg, struct tee_receivers_pool *pool) { struct p_kafka_host *kafka_host = &pool->kafka_host; struct sockaddr *sa, target; time_t last_fail, now; size_t msglen = 0; memset(&target, 0, sizeof(target)); sa = (struct sockaddr *) &msg->agent; target.sa_family = sa->sa_family; if (config.debug) { char *flow = NULL, netflow[] = "NetFlow/IPFIX", sflow[] = "sFlow"; char *broker, *topic; struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)msg, &a, &agent_port); addr_to_str(agent_addr, &a); broker = p_kafka_get_broker(kafka_host); topic = p_kafka_get_topic(kafka_host); if (config.acct_type == ACCT_NF) flow = netflow; else if (config.acct_type == ACCT_SF) flow = sflow; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending %s packet from [%s:%u] seqno [%u] to Kafka [%s-%s]\n", config.name, config.type, flow, agent_addr, agent_port, msg->seqno, broker, topic); } last_fail = P_broker_timers_get_last_fail(&kafka_host->btimers); if (last_fail) { now = time(NULL); if ((last_fail + P_broker_timers_get_retry_interval(&kafka_host->btimers)) <= now) { Tee_init_kafka_host(kafka_host, pool->kafka_broker, pool->kafka_topic, pool->id); } } if (config.tee_transparent) { msglen = Tee_craft_transparent_msg(msg, &target); if (msglen) p_kafka_produce_data(kafka_host, tee_send_buf, msglen); } } #endif #ifdef WITH_ZMQ void Tee_zmq_send(struct pkt_msg *msg, struct tee_receivers_pool *pool) { struct p_zmq_host *zmq_host = &pool->zmq_host; struct sockaddr *sa, target; size_t msglen = 0; int ret; memset(&target, 0, sizeof(target)); sa = (struct sockaddr *) &msg->agent; target.sa_family = sa->sa_family; if (config.debug) { char *flow = NULL, netflow[] = "NetFlow/IPFIX", sflow[] = "sFlow"; char *address; struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)msg, &a, &agent_port); addr_to_str(agent_addr, &a); address = p_zmq_get_address(zmq_host); if (config.acct_type == ACCT_NF) flow = netflow; else if (config.acct_type == ACCT_SF) flow = sflow; Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending %s packet from [%s:%u] seqno [%u] via ZeroMQ [%s]\n", config.name, config.type, flow, agent_addr, agent_port, msg->seqno, address); } if (config.tee_transparent) { msglen = Tee_craft_transparent_msg(msg, &target); if (msglen) { ret = p_zmq_send_bin(&zmq_host->sock, tee_send_buf, msglen, TRUE); if (ret == ERR && errno == EAGAIN) { char *address; address = p_zmq_get_address(zmq_host); Log(LOG_WARNING, "WARN ( %s/%s ): Queue full: ZeroMQ [%s]\n", config.name, config.type, address); } } } } #endif void Tee_destroy_recvs() { struct tee_receiver *target = NULL; int pool_idx, recv_idx; for (pool_idx = 0; pool_idx < receivers.num; pool_idx++) { for (recv_idx = 0; recv_idx < receivers.pools[pool_idx].num; recv_idx++) { target = &receivers.pools[pool_idx].receivers[recv_idx]; if (target->fd) close(target->fd); } memset(receivers.pools[pool_idx].receivers, 0, config.tee_max_receivers*sizeof(struct tee_receiver)); memset(&receivers.pools[pool_idx].tag_filter, 0, sizeof(struct pretag_filter)); memset(&receivers.pools[pool_idx].balance, 0, sizeof(struct tee_balance)); receivers.pools[pool_idx].id = 0; receivers.pools[pool_idx].num = 0; #ifdef WITH_KAFKA if (strlen(receivers.pools[pool_idx].kafka_broker)) { p_kafka_close(&receivers.pools[pool_idx].kafka_host, FALSE); memset(receivers.pools[pool_idx].kafka_broker, 0, sizeof(receivers.pools[pool_idx].kafka_broker)); memset(receivers.pools[pool_idx].kafka_topic, 0, sizeof(receivers.pools[pool_idx].kafka_topic)); } #endif #ifdef WITH_ZMQ if (strlen(receivers.pools[pool_idx].zmq_address)) { p_zmq_close(&receivers.pools[pool_idx].zmq_host); memset(receivers.pools[pool_idx].zmq_address, 0, sizeof(receivers.pools[pool_idx].zmq_address)); } #endif } receivers.num = 0; } void Tee_init_socks() { struct tee_receiver *target = NULL; struct sockaddr *sa; int pool_idx, recv_idx, err; char dest_addr[256], dest_serv[256]; for (pool_idx = 0; pool_idx < receivers.num; pool_idx++) { for (recv_idx = 0; recv_idx < receivers.pools[pool_idx].num; recv_idx++) { target = &receivers.pools[pool_idx].receivers[recv_idx]; sa = (struct sockaddr *) &target->dest; if (sa->sa_family != 0) { if ((err = getnameinfo(sa, target->dest_len, dest_addr, sizeof(dest_addr), dest_serv, sizeof(dest_serv), NI_NUMERICHOST)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): getnameinfo: %d\n", config.name, config.type, err); exit_gracefully(1); } } target->fd = Tee_prepare_sock((struct sockaddr *) &target->dest, target->dest_len, config.nfprobe_source_ip, receivers.pools[pool_idx].src_port, config.tee_transparent, config.tee_pipe_size); if (config.debug) { struct host_addr recv_addr; char recv_addr_str[INET6_ADDRSTRLEN]; u_int16_t recv_port; sa_to_addr((struct sockaddr *)&target->dest, &recv_addr, &recv_port); addr_to_str(recv_addr_str, &recv_addr); Log(LOG_DEBUG, "DEBUG ( %s/%s ): PoolID=%u receiver=%s fd=%d\n", config.name, config.type, receivers.pools[pool_idx].id, recv_addr_str, target->fd); } } #ifdef WITH_KAFKA if (strlen(receivers.pools[pool_idx].kafka_broker)) { Tee_init_kafka_host(&receivers.pools[pool_idx].kafka_host, receivers.pools[pool_idx].kafka_broker, receivers.pools[pool_idx].kafka_topic, receivers.pools[pool_idx].id); } #endif #ifdef WITH_ZMQ if (strlen(receivers.pools[pool_idx].zmq_address)) { Tee_init_zmq_host(&receivers.pools[pool_idx].zmq_host, receivers.pools[pool_idx].zmq_address, receivers.pools[pool_idx].id); } #endif } } #ifdef WITH_KAFKA void Tee_init_kafka_host(struct p_kafka_host *kafka_host, char *kafka_broker, char *kafka_topic, u_int32_t pool_id) { p_kafka_init_host(kafka_host, config.tee_kafka_config_file); p_kafka_connect_to_produce(kafka_host); p_kafka_set_broker(kafka_host, kafka_broker, FALSE); p_kafka_set_topic(kafka_host, kafka_topic); p_kafka_set_content_type(kafka_host, PM_KAFKA_CNT_TYPE_BIN); P_broker_timers_set_retry_interval(&kafka_host->btimers, PM_KAFKA_DEFAULT_RETRY); if (config.debug) { char *broker, *topic; broker = p_kafka_get_broker(kafka_host); topic = p_kafka_get_topic(kafka_host); Log(LOG_DEBUG, "DEBUG ( %s/%s ): PoolID=%u KafkaBroker=%s KafkaTopic=%s\n", config.name, config.type, pool_id, broker, topic); } } #endif #ifdef WITH_ZMQ void Tee_init_zmq_host(struct p_zmq_host *zmq_host, char *zmq_address, u_int32_t pool_id) { char log_id[SHORTBUFLEN]; p_zmq_init_push(zmq_host, zmq_address); snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_zmq_set_log_id(zmq_host, log_id); p_zmq_set_hwm(zmq_host, PM_ZMQ_DEFAULT_FLOW_HWM); p_zmq_push_setup(zmq_host); if (config.debug) { char *broker; broker = p_zmq_get_address(zmq_host); Log(LOG_DEBUG, "DEBUG ( %s/%s ): PoolID=%u ZmqAddress=%s\n", config.name, config.type, pool_id, broker); } } #endif int Tee_prepare_sock(struct sockaddr *addr, socklen_t len, char *src_ip, u_int16_t src_port, int transparent, int pipe_size) { int s, ret = 0; #if defined BSD int hincl = TRUE; #endif if (!transparent) { struct host_addr source_ip; struct sockaddr_storage ssource_ip; memset(&source_ip, 0, sizeof(source_ip)); memset(&ssource_ip, 0, sizeof(ssource_ip)); if (src_ip || src_port) { if (src_ip) { str_to_addr(src_ip, &source_ip); } else { source_ip.family = addr->sa_family; } ret = addr_to_sa((struct sockaddr *) &ssource_ip, &source_ip, src_port); } if ((s = socket(addr->sa_family, SOCK_DGRAM, 0)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): socket() error: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } if (ret && bind(s, (struct sockaddr *) &ssource_ip, sizeof(ssource_ip)) == -1) { Log(LOG_WARNING, "WARN ( %s/%s ): bind() error: %s\n", config.name, config.type, strerror(errno)); } } else { if ((s = socket(addr->sa_family, SOCK_RAW, IPPROTO_RAW)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): socket() error: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } #if defined BSD setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, (socklen_t) sizeof(hincl)); #endif } if (pipe_size) { socklen_t l = sizeof(pipe_size); int saved = 0, obtained = 0; getsockopt(s, SOL_SOCKET, SO_SNDBUF, &saved, &l); Setsocksize(s, SOL_SOCKET, SO_SNDBUF, &pipe_size, (socklen_t) sizeof(pipe_size)); getsockopt(s, SOL_SOCKET, SO_SNDBUF, &obtained, &l); if (obtained < saved) { Setsocksize(s, SOL_SOCKET, SO_SNDBUF, &saved, l); getsockopt(s, SOL_SOCKET, SO_SNDBUF, &obtained, &l); } Log(LOG_INFO, "INFO ( %s/%s ): tee_pipe_size: obtained=%d target=%d.\n", config.name, config.type, obtained, pipe_size); } if (connect(s, (struct sockaddr *)addr, len) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): connect() error: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } return(s); } int Tee_parse_hostport(const char *s, struct sockaddr *addr, socklen_t *len, int dont_check_port) { char *orig, *host, *port, zero_port[] = "]:0"; struct addrinfo hints, *res; int herr; memset(&hints, '\0', sizeof(hints)); if ((host = orig = strdup(s)) == NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): Tee_parse_hostport() out of memory. Exiting ..\n", config.name, config.type); exit_gracefully(1); } trim_spaces(host); trim_spaces(orig); if ((port = strrchr(host, ':')) == NULL || *(++port) == '\0') { if (dont_check_port) { port = zero_port; ++port; ++port; } else return TRUE; } if (*host == '\0') return TRUE; *(port - 1) = '\0'; /* Accept [host]:port for numeric IPv6 addresses; XXX: if dont_check_port is set to true, check for ']' will be inaccurate */ if (*host == '[' && *(port - 2) == ']') { host++; *(port - 2) = '\0'; hints.ai_family = AF_INET6; } hints.ai_socktype = SOCK_DGRAM; /* Validations */ if ((herr = getaddrinfo(host, port, &hints, &res)) == -1) return TRUE; if (res == NULL || res->ai_addr == NULL) return TRUE; if (res->ai_addrlen > *len) return TRUE; memcpy(addr, res->ai_addr, res->ai_addrlen); free(orig); *len = res->ai_addrlen; return FALSE; } struct tee_receiver *Tee_rr_balance(void *pool, struct pkt_msg *msg) { struct tee_receivers_pool *p = pool; struct tee_receiver *target = NULL; if (p) { target = &p->receivers[p->balance.next % p->num]; p->balance.next++; p->balance.next %= p->num; } return target; } struct tee_receiver *Tee_hash_agent_crc32(void *pool, struct pkt_msg *msg) { struct tee_receivers_pool *p = pool; struct tee_receiver *target = NULL; struct sockaddr *sa = (struct sockaddr *) &msg->agent; struct sockaddr_in *sa4 = (struct sockaddr_in *) &msg->agent; unsigned int bucket = 0; if (p) { if (sa->sa_family == AF_INET) { bucket = cache_crc32((const unsigned char*)&sa4->sin_addr.s_addr, 4); bucket %= p->num; target = &p->receivers[bucket]; } else if (sa->sa_family == AF_INET6) { bucket = sa_hash(sa, p->num); target = &p->receivers[bucket]; } } return target; } struct tee_receiver *Tee_hash_agent_balance(void *pool, struct pkt_msg *msg) { struct tee_receivers_pool *p = pool; struct tee_receiver *target = NULL; struct sockaddr *sa = (struct sockaddr *) &msg->agent; struct sockaddr_in *sa4 = (struct sockaddr_in *) &msg->agent; if (p) { if (sa->sa_family == AF_INET) target = &p->receivers[sa4->sin_addr.s_addr & p->num]; /* XXX: hashing against IPv6 agents is not supported (yet) */ } return target; } struct tee_receiver *Tee_hash_tag_balance(void *pool, struct pkt_msg *msg) { struct tee_receivers_pool *p = pool; struct tee_receiver *target = NULL; if (p) target = &p->receivers[msg->tag % p->num]; return target; } void Tee_select_templates(unsigned char *pkt, int pkt_len, int nfv, unsigned char *tpl_pkt, int *tpl_pkt_len) { struct struct_header_v9 *hdr_v9 = NULL; struct struct_header_ipfix *hdr_v10 = NULL; struct data_hdr_v9 *hdr_flowset = NULL; unsigned char *src_ptr = pkt, *dst_ptr = tpl_pkt; u_int16_t flowsetNo = 0, flowsetCount = 0, flowsetTplCount = 0; int tmp_len = 0, hdr_len = 0, term1 = 0, term2 = 0; if (!pkt || !pkt_len || !tpl_pkt || !tpl_pkt_len) return; if (nfv != 9 && nfv != 10) return; if (pkt_len > NETFLOW_MSG_SIZE) return; (*tpl_pkt_len) = 0; /* NetFlow v9 */ if (nfv == 9) { hdr_v9 = (struct struct_header_v9 *) tpl_pkt; hdr_len = sizeof(struct struct_header_v9); } else if (nfv == 10) { hdr_v10 = (struct struct_header_ipfix *) tpl_pkt; hdr_len = sizeof(struct struct_header_ipfix); } if (pkt_len < hdr_len) return; memcpy(dst_ptr, src_ptr, hdr_len); src_ptr += hdr_len; dst_ptr += hdr_len; pkt_len -= hdr_len; tmp_len += hdr_len; if (nfv == 9) { flowsetNo = htons(hdr_v9->count); term1 = (flowsetNo + 1); /* trick to use > operator */ term2 = flowsetCount; } else if (nfv == 10) { term1 = pkt_len; term2 = 0; } hdr_flowset = (struct data_hdr_v9 *) src_ptr; while (term1 > term2) { int fset_id = ntohs(hdr_flowset->flow_id); int fset_len = ntohs(hdr_flowset->flow_len); if (!fset_len || fset_len > pkt_len) break; /* if template, copy over */ if (((nfv == 9) && (fset_id == 0 || fset_id == 1)) || ((nfv == 10) && (fset_id == 2 || fset_id == 3))) { memcpy(dst_ptr, src_ptr, fset_len); src_ptr += fset_len; dst_ptr += fset_len; pkt_len -= fset_len; tmp_len += fset_len; flowsetTplCount++; } /* if data, skip */ else { src_ptr += fset_len; pkt_len -= fset_len; } if (nfv == 9) { flowsetCount++; term2 = flowsetCount; } else if (nfv == 10) { term1 = pkt_len; } hdr_flowset = (struct data_hdr_v9 *) src_ptr; } /* if we have at least one template, let's update the template packet */ if (flowsetTplCount) { if (nfv == 9) { hdr_v9->count = htons(flowsetTplCount); } else if (nfv == 10) { hdr_v10->len = htons(tmp_len); } (*tpl_pkt_len) = tmp_len; } } pmacct-1.7.8/src/tee_plugin/tee_recvs.h0000644000175000017500000000406214354105275017066 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TEE_RECVS_H #define TEE_RECVS_H /* includes */ /* defines */ /* structures */ /* prototypes */ extern int tee_recvs_map_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_ip_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_tag_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_balance_alg_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_src_port_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); #ifdef WITH_KAFKA extern int tee_recvs_map_kafka_broker_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_kafka_topic_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); #endif #ifdef WITH_ZMQ extern int tee_recvs_map_zmq_address_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int tee_recvs_map_zmq_topic_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); #endif extern void tee_recvs_map_validate(char *, int, struct plugin_requests *); /* global variables */ #endif //TEE_RECVS_H pmacct-1.7.8/src/tee_plugin/tee_recvs.c0000644000175000017500000003021714354105275017062 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #ifdef WITH_KAFKA #include "kafka_common.h" #endif #ifdef WITH_ZMQ #include "zmq_common.h" #endif #include "tee_plugin.h" #include "tee_recvs.h" int tee_recvs_map_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; int pool_idx; u_int32_t pool_id; char *endptr = NULL; if (table && table->pools) { if (table->num < config.tee_max_receiver_pools) { pool_id = strtoull(value, &endptr, 10); if (!pool_id || pool_id > UINT32_MAX) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Invalid Pool ID specified.\n", config.name, config.type, filename); return TRUE; } /* Ensure no pool ID duplicates */ for (pool_idx = 0; pool_idx < table->num; pool_idx++) { if (pool_id == table->pools[table->num].id) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Duplicate Pool ID specified: %u.\n", config.name, config.type, filename, pool_id); return TRUE; } } table->pools[table->num].id = pool_id; } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Maximum amount of receivers pool reached: %u.\n", config.name, config.type, filename, config.tee_max_receiver_pools); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int tee_recvs_map_ip_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; struct tee_receiver *target = NULL; int recv_idx; char *str_ptr, *token; if (table && table->pools && table->pools[table->num].receivers) { str_ptr = value; recv_idx = 0; while ((token = extract_token(&str_ptr, ','))) { if (recv_idx < config.tee_max_receivers) { target = &table->pools[table->num].receivers[recv_idx]; target->dest_len = sizeof(target->dest); if (!Tee_parse_hostport(token, (struct sockaddr *)&target->dest, &target->dest_len, FALSE)) recv_idx++; else Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid receiver %s.\n", config.name, config.type, filename, token); } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Maximum amount of receivers pool reached %u.\n", config.name, config.type, filename, config.tee_max_receiver_pools); break; } } if (!recv_idx) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] No valid receivers.\n", config.name, config.type, filename); return TRUE; } else table->pools[table->num].num = recv_idx; } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int tee_recvs_map_tag_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; int ret; if (table && table->pools) ret = load_tags(filename, &table->pools[table->num].tag_filter, value); else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } if (!ret) return TRUE; else return FALSE; } int tee_recvs_map_balance_alg_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; if (table && table->pools) { if (!strncmp(value, "rr", 2)) { table->pools[table->num].balance.type = TEE_BALANCE_RR; table->pools[table->num].balance.func = Tee_rr_balance; } else if (!strncmp(value, "hash-agent", 10)) { table->pools[table->num].balance.type = TEE_BALANCE_HASH_AGENT; table->pools[table->num].balance.func = Tee_hash_agent_balance; } else if (!strncmp(value, "hash-crc32", 10)) { table->pools[table->num].balance.type = TEE_BALANCE_HASH_AGENT; table->pools[table->num].balance.func = Tee_hash_agent_crc32; } else if (!strncmp(value, "hash-tag", 8)) { table->pools[table->num].balance.type = TEE_BALANCE_HASH_TAG; table->pools[table->num].balance.func = Tee_hash_tag_balance; } else { table->pools[table->num].balance.func = NULL; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unknown balance algorithm '%s'. Ignoring.\n", config.name, config.type, filename, value); } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int tee_recvs_map_src_port_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; int port; if (table && table->pools) { port = atoi(value); if (port <= UINT16_MAX) table->pools[table->num].src_port = port; else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid source port specified '%s'. Ignoring.\n", config.name, config.type, filename, value); } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } #ifdef WITH_KAFKA int tee_recvs_map_kafka_broker_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; if (table && table->pools) { int len = sizeof(table->pools[table->num].kafka_broker); memset(table->pools[table->num].kafka_broker, 0, len); strlcpy(table->pools[table->num].kafka_broker, value, len); table->pools[table->num].kafka_broker[len] = '\0'; } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int tee_recvs_map_kafka_topic_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; if (table && table->pools) { int len = sizeof(table->pools[table->num].kafka_topic); memset(table->pools[table->num].kafka_topic, 0, len); strlcpy(table->pools[table->num].kafka_topic, value, len); table->pools[table->num].kafka_topic[len] = '\0'; } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } #endif #ifdef WITH_ZMQ int tee_recvs_map_zmq_address_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; if (table && table->pools) { int len = sizeof(table->pools[table->num].zmq_address); memset(table->pools[table->num].zmq_address, 0, len); strlcpy(table->pools[table->num].zmq_address, value, len); table->pools[table->num].zmq_address[len] = '\0'; } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Receivers table not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } #endif void tee_recvs_map_validate(char *filename, int lineno, struct plugin_requests *req) { struct tee_receivers *table = (struct tee_receivers *) req->key_value_table; int valid = FALSE, emit_methods = 0; if (table && table->pools && table->pools[table->num].receivers) { /* Check: emit to either IP address(es) or Kafka broker(s) or ZeroMQ queue */ if (table->pools[table->num].num > 0) emit_methods++; if (strlen(table->pools[table->num].kafka_broker)) emit_methods++; if (strlen(table->pools[table->num].zmq_address)) emit_methods++; if (emit_methods > 1) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] 'ip', 'kafka_broker' and 'zmq_address' are mutual exclusive. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } if (!emit_methods) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] 'ip' or 'kafka_broker' or 'zmq_address' must be specified. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } /* Check: valid pool ID */ if (table->pools[table->num].id > 0) valid = TRUE; else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Invalid pool 'id' specified. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } if (table->pools[table->num].num > 0) valid = TRUE; /* Check: if emitting to Kafka: a) make sure we have both broker string and topic, b) balance-alg is not set, tee_transparent is set to true */ #ifdef WITH_KAFKA if (strlen(table->pools[table->num].kafka_broker)) { if (!config.tee_transparent) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] tee_transparent must be set to 'true' when emitting to Kafka. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } if (table->pools[table->num].balance.func) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] 'balance-alg' is not compatible with emitting to Kafka. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } if (!strlen(table->pools[table->num].kafka_topic)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] 'kafka_topic' missing. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } valid = TRUE; } #endif /* Check: if emitting via ZeroMQ: a) make sure we have an address string, b) balance-alg is not set, tee_transparent is set to true */ #ifdef WITH_ZMQ if (strlen(table->pools[table->num].zmq_address)) { if (!config.tee_transparent) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] tee_transparent must be set to 'true' when emitting via ZeroMQ. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } if (table->pools[table->num].balance.func) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] 'balance-alg' is not compatible with emitting via ZeroMQ. Line ignored.\n", config.name, config.type, filename, lineno); valid = FALSE; goto zero_entry; } valid = TRUE; } #endif if (valid) table->num++; else { zero_entry: table->pools[table->num].id = 0; table->pools[table->num].num = 0; table->pools[table->num].src_port = 0; memset(table->pools[table->num].receivers, 0, config.tee_max_receivers*sizeof(struct tee_receiver)); memset(&table->pools[table->num].tag_filter, 0, sizeof(struct pretag_filter)); memset(&table->pools[table->num].balance, 0, sizeof(struct tee_balance)); #ifdef WITH_KAFKA memset(&table->pools[table->num].kafka_host, 0, sizeof(struct p_kafka_host)); memset(&table->pools[table->num].kafka_broker, 0, sizeof(table->pools[table->num].kafka_broker)); memset(&table->pools[table->num].kafka_topic, 0, sizeof(table->pools[table->num].kafka_topic)); #endif #ifdef WITH_ZMQ memset(&table->pools[table->num].zmq_host, 0, sizeof(struct p_zmq_host)); memset(&table->pools[table->num].zmq_address, 0, sizeof(table->pools[table->num].zmq_address)); #endif } } } pmacct-1.7.8/src/tee_plugin/Makefile.in0000644000175000017500000005352614354105416017011 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/tee_plugin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtee_plugin_la_LIBADD = am_libtee_plugin_la_OBJECTS = libtee_plugin_la-tee_plugin.lo \ libtee_plugin_la-tee_recvs.lo libtee_plugin_la_OBJECTS = $(am_libtee_plugin_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libtee_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libtee_plugin_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libtee_plugin_la-tee_plugin.Plo \ ./$(DEPDIR)/libtee_plugin_la-tee_recvs.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libtee_plugin_la_SOURCES) DIST_SOURCES = $(libtee_plugin_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libtee_plugin.la libtee_plugin_la_SOURCES = tee_plugin.c tee_recvs.c tee_plugin.h \ tee_recvs-data.h tee_recvs.h libtee_plugin_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tee_plugin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/tee_plugin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libtee_plugin.la: $(libtee_plugin_la_OBJECTS) $(libtee_plugin_la_DEPENDENCIES) $(EXTRA_libtee_plugin_la_DEPENDENCIES) $(AM_V_CCLD)$(libtee_plugin_la_LINK) $(libtee_plugin_la_OBJECTS) $(libtee_plugin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtee_plugin_la-tee_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtee_plugin_la-tee_recvs.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libtee_plugin_la-tee_plugin.lo: tee_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtee_plugin_la_CFLAGS) $(CFLAGS) -MT libtee_plugin_la-tee_plugin.lo -MD -MP -MF $(DEPDIR)/libtee_plugin_la-tee_plugin.Tpo -c -o libtee_plugin_la-tee_plugin.lo `test -f 'tee_plugin.c' || echo '$(srcdir)/'`tee_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtee_plugin_la-tee_plugin.Tpo $(DEPDIR)/libtee_plugin_la-tee_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tee_plugin.c' object='libtee_plugin_la-tee_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtee_plugin_la_CFLAGS) $(CFLAGS) -c -o libtee_plugin_la-tee_plugin.lo `test -f 'tee_plugin.c' || echo '$(srcdir)/'`tee_plugin.c libtee_plugin_la-tee_recvs.lo: tee_recvs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtee_plugin_la_CFLAGS) $(CFLAGS) -MT libtee_plugin_la-tee_recvs.lo -MD -MP -MF $(DEPDIR)/libtee_plugin_la-tee_recvs.Tpo -c -o libtee_plugin_la-tee_recvs.lo `test -f 'tee_recvs.c' || echo '$(srcdir)/'`tee_recvs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtee_plugin_la-tee_recvs.Tpo $(DEPDIR)/libtee_plugin_la-tee_recvs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tee_recvs.c' object='libtee_plugin_la-tee_recvs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtee_plugin_la_CFLAGS) $(CFLAGS) -c -o libtee_plugin_la-tee_recvs.lo `test -f 'tee_recvs.c' || echo '$(srcdir)/'`tee_recvs.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libtee_plugin_la-tee_plugin.Plo -rm -f ./$(DEPDIR)/libtee_plugin_la-tee_recvs.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libtee_plugin_la-tee_plugin.Plo -rm -f ./$(DEPDIR)/libtee_plugin_la-tee_recvs.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/tee_plugin/Makefile.am0000644000175000017500000000033314354105275016767 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libtee_plugin.la libtee_plugin_la_SOURCES = tee_plugin.c tee_recvs.c tee_plugin.h \ tee_recvs-data.h tee_recvs.h libtee_plugin_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/pmacct-defines.h0000644000175000017500000006155614354105275015651 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* defines */ #define ARGS_NFACCTD "n:dDhP:b:f:F:c:m:p:r:s:S:L:l:o:t:O:MuRVaAE:I:WZ:Y:" #define ARGS_SFACCTD "n:dDhP:b:f:F:c:m:p:r:s:S:L:l:o:t:O:MuRVaAE:I:WZ:Y:" #define ARGS_PMACCTD "n:NdDhP:b:f:F:c:i:I:m:p:r:s:S:o:t:O:MuwWZ:Y:L:RVazAE:" #define ARGS_UACCTD "n:NdDhP:b:f:F:c:m:p:r:s:S:o:t:O:MuRg:L:VaAE:" #define ARGS_PMTELEMETRYD "hVL:u:t:Z:f:dDS:F:o:O:i:" #define ARGS_PMBGPD "hVL:l:f:dDS:F:o:O:i:gm:" #define ARGS_PMBMPD "hVL:l:f:dDS:F:o:O:i:I:Z:Y:T:" #define ARGS_PMACCT "hSsc:Cetm:p:P:M:arN:n:lT:O:E:uVUiI0" #define N_PRIMITIVES 128 #define N_FUNCS 10 #define MAX_N_PLUGINS 32 #define PROTO_LEN 12 #define PROTO_NUM_STRLEN 4 #define MAX_MAP_ENTRIES 2048 /* allow maps */ #define BGP_MD5_MAP_ENTRIES 8192 #define AGG_FILTER_ENTRIES 128 #define FOLLOW_BGP_NH_ENTRIES 32 #define MAX_PROTOCOL_LEN 32 #define DEFAULT_AVRO_SCHEMA_REFRESH_TIME 60 #define MAX_AVRO_SCHEMA 65535 #define MIN_REFRESH_TIME 60 #define MAX_REFRESH_TIME 86400 #define DEFAULT_IMT_PLUGIN_POLL_TIMEOUT 5 #define DEFAULT_SLOTH_SLEEP_TIME 5 #define DEFAULT_SEP "," #define DEFAULT_SEP_INT ',' #define UINT32T_THRESHOLD 4290000000UL #define UINT64T_THRESHOLD 18446744073709551360ULL #define INT64T_THRESHOLD 9223372036854775807ULL #define PM_VARIABLE_LENGTH 65535 #define PM_COUNTRY_T_STRLEN 4 #define PM_POCODE_T_STRLEN 12 #define PCAP_SAVEFILE_MAX_ERRORS 10 #define PCAP_MAX_INTERFACES 1000 #define PCAP_MAX_ATTEMPTS 3 #define PCAP_RETRY_PERIOD 5 #define PCAP_IFINDEX_NONE 0 #define PCAP_IFINDEX_SYS 1 #define PCAP_IFINDEX_HASH 2 #define PCAP_IFINDEX_MAP 3 #define PORT_STRLEN 6 #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #ifndef UINT64_MAX #define UINT64_MAX (18446744073709551615ULL) #endif #ifndef INT_MAX #define INT_MAX (2147483647U) #endif #ifndef INT_MIN #define INT_MIN (-2147483647 - 1) #endif #define LONGLONG_RETRY INT_MAX #define DEFAULT_SNAPLEN 128 #define SNAPLEN_ISIS_MIN 512 #define SNAPLEN_ISIS_DEFAULT 1476 #define SUPERSHORTBUFLEN (16+MOREBUFSZ) #define VERYSHORTBUFLEN (32+MOREBUFSZ) #define SHORTSHORTBUFLEN (64+MOREBUFSZ) #define SHORTBUFLEN (128+MOREBUFSZ) #define SRVBUFLEN (256+MOREBUFSZ) #define LONGSRVBUFLEN (384+MOREBUFSZ) #define LONGLONGSRVBUFLEN (1024+MOREBUFSZ) #define LARGEBUFLEN (8192+MOREBUFSZ) #define OUTPUT_FILE_BUFSZ (100 * LARGEBUFLEN) #define PRIMITIVE_LEN 32 #define PRIMITIVE_DESC_LEN 64 #define MANTAINER "Paolo Lucente " #define GET_IN_TOUCH_MSG "If you see this message, please get in touch" #define PMACCTD_USAGE_HEADER "Promiscuous Mode Accounting Daemon, pmacctd" #define UACCTD_USAGE_HEADER "Linux NetFilter NFLOG Accounting Daemon, uacctd" #define PMACCT_USAGE_HEADER "pmacct IMT plugin client, pmacct" #define NFACCTD_USAGE_HEADER "NetFlow Accounting Daemon, nfacctd" #define SFACCTD_USAGE_HEADER "sFlow Accounting Daemon, sfacctd" #define PMTELEMETRYD_USAGE_HEADER "Streaming Network Telemetry Daemon, pmtelemetryd" #define PMBGPD_USAGE_HEADER "pmacct BGP Collector Daemon, pmbgpd" #define PMBMPD_USAGE_HEADER "pmacct BMP Collector Daemon, pmbmpd" #define PMACCT_COMPILE_ARGS COMPILE_ARGS #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef FALSE_NONZERO #define FALSE_NONZERO INT_MIN #endif #ifndef ERR #define ERR -1 #endif #ifndef SUCCESS #define SUCCESS 0 #endif #define E_NOTFOUND 2 #ifndef MIN #define MIN(x, y) (x <= y ? x : y) #endif #ifndef MAX #define MAX(x, y) (x <= y ? y : x) #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif /* Daemon identificator */ #define ACCT_UNKNOWN 0 /* Undefined / unknown daemon */ #define ACCT_PM 1 /* promiscuous mode */ #define ACCT_NF 2 /* NetFlow */ #define ACCT_SF 3 /* sFlow */ #define ACCT_UL 4 /* Linux NetFilter NFLOG */ #define ACCT_FWDPLANE_MAX 100 /* Max ID for forwarding-plane daemons */ #define ACCT_PMBGP 101 /* standalone BGP daemon */ #define ACCT_PMBMP 102 /* standalone BMP daemon */ #define ACCT_CTLPLANE_MAX 200 /* Max ID for control-plane daemons */ #define ACCT_PMTELE 201 /* Streaming Network Telemetry */ #define ACCT_INFRA_MAX 300 /* Max ID for infrastructure daemons */ /* map type */ #define MAP_TAG 0 /* pre_tag_map */ #define MAP_BGP_PEER_AS_SRC 1000 /* bgp_peer_src_as_map */ #define MAP_BGP_TO_XFLOW_AGENT 1001 /* bgp_to_agent_map */ #define MAP_BGP_SRC_LOCAL_PREF 1002 /* bgp_src_local_pref_map */ #define MAP_BGP_SRC_MED 1003 /* bgp_src_med_map */ #define MAP_FLOW_TO_RD 1004 /* flow_to_rd_map */ #define MAP_SAMPLING 1005 /* sampling_map */ #define MAP_TEE_RECVS 1006 /* tee_receivers */ #define MAP_IGP 1007 /* igp_daemon_map */ #define MAP_CUSTOM_PRIMITIVES 1008 /* aggregate_primitives */ #define MAP_BGP_XCS 1009 /* bgp_xconnect_map */ #define MAP_PCAP_INTERFACES 1010 /* pcap_interfaces_map */ /* PRIMITIVES DEFINITION: START */ /* internal: first registry, ie. what_to_count, aggregation, etc. */ #define COUNT_INT_SRC_HOST 0x0001000000000001ULL #define COUNT_INT_DST_HOST 0x0001000000000002ULL #define COUNT_INT_SUM_HOST 0x0001000000000004ULL #define COUNT_INT_SRC_PORT 0x0001000000000008ULL #define COUNT_INT_DST_PORT 0x0001000000000010ULL #define COUNT_INT_IP_PROTO 0x0001000000000020ULL #define COUNT_INT_SRC_MAC 0x0001000000000040ULL #define COUNT_INT_DST_MAC 0x0001000000000080ULL #define COUNT_INT_SRC_NET 0x0001000000000100ULL #define COUNT_INT_DST_NET 0x0001000000000200ULL #define COUNT_INT_TAG 0x0001000000000400ULL #define COUNT_INT_VLAN 0x0001000000000800ULL #define COUNT_INT_IP_TOS 0x0001000000001000ULL #define COUNT_INT_NONE 0x0001000000002000ULL #define COUNT_INT_SRC_AS 0x0001000000004000ULL #define COUNT_INT_DST_AS 0x0001000000008000ULL #define COUNT_INT_SUM_NET 0x0001000000010000ULL #define COUNT_INT_SUM_AS 0x0001000000020000ULL #define COUNT_INT_SUM_PORT 0x0001000000040000ULL #define INT_TIMESTAMP 0x0001000000080000ULL /* USE_TIMESTAMPS */ #define COUNT_INT_FLOWS 0x0001000000100000ULL #define COUNT_INT_SUM_MAC 0x0001000000200000ULL #define COUNT_INT_CLASS 0x0001000000400000ULL #define COUNT_INT_COUNTERS 0x0001000000800000ULL #define COUNT_INT_PAYLOAD 0x0001000001000000ULL #define COUNT_INT_TCPFLAGS 0x0001000002000000ULL #define COUNT_INT_STD_COMM 0x0001000004000000ULL #define COUNT_INT_EXT_COMM 0x0001000008000000ULL #define COUNT_INT_AS_PATH 0x0001000010000000ULL #define COUNT_INT_LOCAL_PREF 0x0001000020000000ULL #define COUNT_INT_MED 0x0001000040000000ULL #define COUNT_INT_PEER_SRC_AS 0x0001000080000000ULL #define COUNT_INT_PEER_DST_AS 0x0001000100000000ULL #define COUNT_INT_PEER_SRC_IP 0x0001000200000000ULL #define COUNT_INT_PEER_DST_IP 0x0001000400000000ULL #define COUNT_INT_TAG2 0x0001000800000000ULL #define COUNT_INT_SRC_AS_PATH 0x0001001000000000ULL #define COUNT_INT_SRC_STD_COMM 0x0001002000000000ULL #define COUNT_INT_SRC_EXT_COMM 0x0001004000000000ULL #define COUNT_INT_SRC_LOCAL_PREF 0x0001008000000000ULL #define COUNT_INT_SRC_MED 0x0001010000000000ULL #define COUNT_INT_MPLS_VPN_RD 0x0001020000000000ULL #define COUNT_INT_IN_IFACE 0x0001040000000000ULL #define COUNT_INT_OUT_IFACE 0x0001080000000000ULL #define COUNT_INT_SRC_NMASK 0x0001100000000000ULL #define COUNT_INT_DST_NMASK 0x0001200000000000ULL #define COUNT_INT_COS 0x0001400000000000ULL #define COUNT_INT_ETHERTYPE 0x0001800000000000ULL /* internal: second registry, ie. what_to_count_2, aggregation_2, etc. */ #define COUNT_INT_SAMPLING_RATE 0x0002000000000001ULL #define COUNT_INT_SRC_HOST_COUNTRY 0x0002000000000002ULL #define COUNT_INT_DST_HOST_COUNTRY 0x0002000000000004ULL #define COUNT_INT_EXPORT_PROTO_SYSID 0x0002000000000008ULL #define COUNT_INT_POST_NAT_SRC_HOST 0x0002000000000010ULL #define COUNT_INT_POST_NAT_DST_HOST 0x0002000000000020ULL #define COUNT_INT_POST_NAT_SRC_PORT 0x0002000000000040ULL #define COUNT_INT_POST_NAT_DST_PORT 0x0002000000000080ULL #define COUNT_INT_NAT_EVENT 0x0002000000000100ULL #define COUNT_INT_TIMESTAMP_START 0x0002000000000200ULL #define COUNT_INT_TIMESTAMP_END 0x0002000000000400ULL #define COUNT_INT_TIMESTAMP_ARRIVAL 0x0002000000000800ULL #define COUNT_INT_MPLS_LABEL_TOP 0x0002000000001000ULL #define COUNT_INT_MPLS_LABEL_BOTTOM 0x0002000000002000ULL /* #define XXX: available 0x0002000000004000ULL */ #define COUNT_INT_LABEL 0x0002000000008000ULL #define COUNT_INT_EXPORT_PROTO_SEQNO 0x0002000000010000ULL #define COUNT_INT_EXPORT_PROTO_VERSION 0x0002000000020000ULL #define COUNT_INT_LRG_COMM 0x0002000000040000ULL #define COUNT_INT_SRC_LRG_COMM 0x0002000000080000ULL #define COUNT_INT_SRC_HOST_POCODE 0x0002000000100000ULL #define COUNT_INT_DST_HOST_POCODE 0x0002000000200000ULL #define COUNT_INT_TUNNEL_SRC_HOST 0x0002000000400000ULL #define COUNT_INT_TUNNEL_DST_HOST 0x0002000000800000ULL #define COUNT_INT_TUNNEL_IP_PROTO 0x0002000001000000ULL #define COUNT_INT_TUNNEL_IP_TOS 0x0002000002000000ULL #define COUNT_INT_NDPI_CLASS 0x0002000004000000ULL #define COUNT_INT_SRC_HOST_COORDS 0x0002000008000000ULL #define COUNT_INT_DST_HOST_COORDS 0x0002000010000000ULL #define COUNT_INT_SAMPLING_DIRECTION 0x0002000020000000ULL #define COUNT_INT_MPLS_PW_ID 0x0002000040000000ULL #define COUNT_INT_SRC_ROA 0x0002000080000000ULL #define COUNT_INT_DST_ROA 0x0002000100000000ULL #define COUNT_INT_VXLAN 0x0002000200000000ULL #define COUNT_INT_TUNNEL_SRC_MAC 0x0002000400000000ULL #define COUNT_INT_TUNNEL_DST_MAC 0x0002000800000000ULL #define COUNT_INT_TUNNEL_SRC_PORT 0x0002001000000000ULL #define COUNT_INT_TUNNEL_DST_PORT 0x0002002000000000ULL #define COUNT_INT_EXPORT_PROTO_TIME 0x0002004000000000ULL #define COUNT_INT_TIMESTAMP_EXPORT 0x0002004000000000ULL /* alias of COUNT_EXPORT_PROTO_TIME */ #define COUNT_INT_FWD_STATUS 0x0002008000000000ULL #define COUNT_INT_MPLS_LABEL_STACK 0x0002010000000000ULL #define COUNT_INT_FW_EVENT 0x0002020000000000ULL #define COUNT_INT_TUNNEL_TCPFLAGS 0x0002040000000000ULL #define COUNT_INT_OUT_VLAN 0x0002080000000000ULL #define COUNT_INT_CUSTOM_PRIMITIVES 0x0002800000000000ULL #define COUNT_INDEX_MASK 0xFFFF #define COUNT_INDEX_CP 0xFFFF000000000000ULL /* index 0xffff reserved to custom primitives */ #define COUNT_REGISTRY_MASK 0x0000FFFFFFFFFFFFULL #define COUNT_REGISTRY_BITS 48 /* external: first registry, ie. what_to_count, aggregation, etc. */ #define COUNT_SRC_HOST (COUNT_INT_SRC_HOST & COUNT_REGISTRY_MASK) #define COUNT_DST_HOST (COUNT_INT_DST_HOST & COUNT_REGISTRY_MASK) #define COUNT_SUM_HOST (COUNT_INT_SUM_HOST & COUNT_REGISTRY_MASK) #define COUNT_SRC_PORT (COUNT_INT_SRC_PORT & COUNT_REGISTRY_MASK) #define COUNT_DST_PORT (COUNT_INT_DST_PORT & COUNT_REGISTRY_MASK) #define COUNT_IP_PROTO (COUNT_INT_IP_PROTO & COUNT_REGISTRY_MASK) #define COUNT_SRC_MAC (COUNT_INT_SRC_MAC & COUNT_REGISTRY_MASK) #define COUNT_DST_MAC (COUNT_INT_DST_MAC & COUNT_REGISTRY_MASK) #define COUNT_SRC_NET (COUNT_INT_SRC_NET & COUNT_REGISTRY_MASK) #define COUNT_DST_NET (COUNT_INT_DST_NET & COUNT_REGISTRY_MASK) #define COUNT_TAG (COUNT_INT_TAG & COUNT_REGISTRY_MASK) #define COUNT_VLAN (COUNT_INT_VLAN & COUNT_REGISTRY_MASK) #define COUNT_IP_TOS (COUNT_INT_IP_TOS & COUNT_REGISTRY_MASK) #define COUNT_NONE (COUNT_INT_NONE & COUNT_REGISTRY_MASK) #define COUNT_SRC_AS (COUNT_INT_SRC_AS & COUNT_REGISTRY_MASK) #define COUNT_DST_AS (COUNT_INT_DST_AS & COUNT_REGISTRY_MASK) #define COUNT_SUM_NET (COUNT_INT_SUM_NET & COUNT_REGISTRY_MASK) #define COUNT_SUM_AS (COUNT_INT_SUM_AS & COUNT_REGISTRY_MASK) #define COUNT_SUM_PORT (COUNT_INT_SUM_PORT & COUNT_REGISTRY_MASK) #define TIMESTAMP (INT_TIMESTAMP & COUNT_REGISTRY_MASK) #define COUNT_FLOWS (COUNT_INT_FLOWS & COUNT_REGISTRY_MASK) #define COUNT_SUM_MAC (COUNT_INT_SUM_MAC & COUNT_REGISTRY_MASK) #define COUNT_CLASS (COUNT_INT_CLASS & COUNT_REGISTRY_MASK) #define COUNT_COUNTERS (COUNT_INT_COUNTERS & COUNT_REGISTRY_MASK) #define COUNT_PAYLOAD (COUNT_INT_PAYLOAD & COUNT_REGISTRY_MASK) #define COUNT_TCPFLAGS (COUNT_INT_TCPFLAGS & COUNT_REGISTRY_MASK) #define COUNT_STD_COMM (COUNT_INT_STD_COMM & COUNT_REGISTRY_MASK) #define COUNT_EXT_COMM (COUNT_INT_EXT_COMM & COUNT_REGISTRY_MASK) #define COUNT_AS_PATH (COUNT_INT_AS_PATH & COUNT_REGISTRY_MASK) #define COUNT_LOCAL_PREF (COUNT_INT_LOCAL_PREF & COUNT_REGISTRY_MASK) #define COUNT_MED (COUNT_INT_MED & COUNT_REGISTRY_MASK) #define COUNT_PEER_SRC_AS (COUNT_INT_PEER_SRC_AS & COUNT_REGISTRY_MASK) #define COUNT_PEER_DST_AS (COUNT_INT_PEER_DST_AS & COUNT_REGISTRY_MASK) #define COUNT_PEER_SRC_IP (COUNT_INT_PEER_SRC_IP & COUNT_REGISTRY_MASK) #define COUNT_PEER_DST_IP (COUNT_INT_PEER_DST_IP & COUNT_REGISTRY_MASK) #define COUNT_TAG2 (COUNT_INT_TAG2 & COUNT_REGISTRY_MASK) #define COUNT_SRC_AS_PATH (COUNT_INT_SRC_AS_PATH & COUNT_REGISTRY_MASK) #define COUNT_SRC_STD_COMM (COUNT_INT_SRC_STD_COMM & COUNT_REGISTRY_MASK) #define COUNT_SRC_EXT_COMM (COUNT_INT_SRC_EXT_COMM & COUNT_REGISTRY_MASK) #define COUNT_SRC_LOCAL_PREF (COUNT_INT_SRC_LOCAL_PREF & COUNT_REGISTRY_MASK) #define COUNT_SRC_MED (COUNT_INT_SRC_MED & COUNT_REGISTRY_MASK) #define COUNT_MPLS_VPN_RD (COUNT_INT_MPLS_VPN_RD & COUNT_REGISTRY_MASK) #define COUNT_IN_IFACE (COUNT_INT_IN_IFACE & COUNT_REGISTRY_MASK) #define COUNT_OUT_IFACE (COUNT_INT_OUT_IFACE & COUNT_REGISTRY_MASK) #define COUNT_SRC_NMASK (COUNT_INT_SRC_NMASK & COUNT_REGISTRY_MASK) #define COUNT_DST_NMASK (COUNT_INT_DST_NMASK & COUNT_REGISTRY_MASK) #define COUNT_COS (COUNT_INT_COS & COUNT_REGISTRY_MASK) #define COUNT_ETHERTYPE (COUNT_INT_ETHERTYPE & COUNT_REGISTRY_MASK) /* external: second registry, ie. what_to_count_2, aggregation_2, etc. */ #define COUNT_SAMPLING_RATE (COUNT_INT_SAMPLING_RATE & COUNT_REGISTRY_MASK) #define COUNT_SRC_HOST_COUNTRY (COUNT_INT_SRC_HOST_COUNTRY & COUNT_REGISTRY_MASK) #define COUNT_DST_HOST_COUNTRY (COUNT_INT_DST_HOST_COUNTRY & COUNT_REGISTRY_MASK) #define COUNT_EXPORT_PROTO_SYSID (COUNT_INT_EXPORT_PROTO_SYSID & COUNT_REGISTRY_MASK) #define COUNT_POST_NAT_SRC_HOST (COUNT_INT_POST_NAT_SRC_HOST & COUNT_REGISTRY_MASK) #define COUNT_POST_NAT_DST_HOST (COUNT_INT_POST_NAT_DST_HOST & COUNT_REGISTRY_MASK) #define COUNT_POST_NAT_SRC_PORT (COUNT_INT_POST_NAT_SRC_PORT & COUNT_REGISTRY_MASK) #define COUNT_POST_NAT_DST_PORT (COUNT_INT_POST_NAT_DST_PORT & COUNT_REGISTRY_MASK) #define COUNT_NAT_EVENT (COUNT_INT_NAT_EVENT & COUNT_REGISTRY_MASK) #define COUNT_TIMESTAMP_START (COUNT_INT_TIMESTAMP_START & COUNT_REGISTRY_MASK) #define COUNT_TIMESTAMP_END (COUNT_INT_TIMESTAMP_END & COUNT_REGISTRY_MASK) #define COUNT_TIMESTAMP_ARRIVAL (COUNT_INT_TIMESTAMP_ARRIVAL & COUNT_REGISTRY_MASK) #define COUNT_MPLS_LABEL_TOP (COUNT_INT_MPLS_LABEL_TOP & COUNT_REGISTRY_MASK) #define COUNT_MPLS_LABEL_BOTTOM (COUNT_INT_MPLS_LABEL_BOTTOM & COUNT_REGISTRY_MASK) #define COUNT_LABEL (COUNT_INT_LABEL & COUNT_REGISTRY_MASK) #define COUNT_EXPORT_PROTO_SEQNO (COUNT_INT_EXPORT_PROTO_SEQNO & COUNT_REGISTRY_MASK) #define COUNT_EXPORT_PROTO_VERSION (COUNT_INT_EXPORT_PROTO_VERSION & COUNT_REGISTRY_MASK) #define COUNT_LRG_COMM (COUNT_INT_LRG_COMM & COUNT_REGISTRY_MASK) #define COUNT_SRC_LRG_COMM (COUNT_INT_SRC_LRG_COMM & COUNT_REGISTRY_MASK) #define COUNT_SRC_HOST_POCODE (COUNT_INT_SRC_HOST_POCODE & COUNT_REGISTRY_MASK) #define COUNT_DST_HOST_POCODE (COUNT_INT_DST_HOST_POCODE & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_SRC_HOST (COUNT_INT_TUNNEL_SRC_HOST & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_DST_HOST (COUNT_INT_TUNNEL_DST_HOST & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_IP_PROTO (COUNT_INT_TUNNEL_IP_PROTO & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_IP_TOS (COUNT_INT_TUNNEL_IP_TOS & COUNT_REGISTRY_MASK) #define COUNT_NDPI_CLASS (COUNT_INT_NDPI_CLASS & COUNT_REGISTRY_MASK) #define COUNT_SRC_HOST_COORDS (COUNT_INT_SRC_HOST_COORDS & COUNT_REGISTRY_MASK) #define COUNT_DST_HOST_COORDS (COUNT_INT_DST_HOST_COORDS & COUNT_REGISTRY_MASK) #define COUNT_SAMPLING_DIRECTION (COUNT_INT_SAMPLING_DIRECTION & COUNT_REGISTRY_MASK) #define COUNT_MPLS_PW_ID (COUNT_INT_MPLS_PW_ID & COUNT_REGISTRY_MASK) #define COUNT_SRC_ROA (COUNT_INT_SRC_ROA & COUNT_REGISTRY_MASK) #define COUNT_DST_ROA (COUNT_INT_DST_ROA & COUNT_REGISTRY_MASK) #define COUNT_VXLAN (COUNT_INT_VXLAN & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_SRC_MAC (COUNT_INT_TUNNEL_SRC_MAC & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_DST_MAC (COUNT_INT_TUNNEL_DST_MAC & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_SRC_PORT (COUNT_INT_TUNNEL_SRC_PORT & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_DST_PORT (COUNT_INT_TUNNEL_DST_PORT & COUNT_REGISTRY_MASK) #define COUNT_EXPORT_PROTO_TIME (COUNT_INT_EXPORT_PROTO_TIME & COUNT_REGISTRY_MASK) #define COUNT_FWD_STATUS (COUNT_INT_FWD_STATUS & COUNT_REGISTRY_MASK) #define COUNT_MPLS_LABEL_STACK (COUNT_INT_MPLS_LABEL_STACK & COUNT_REGISTRY_MASK) #define COUNT_FW_EVENT (COUNT_INT_FW_EVENT & COUNT_REGISTRY_MASK) #define COUNT_TUNNEL_TCPFLAGS (COUNT_INT_TUNNEL_TCPFLAGS & COUNT_REGISTRY_MASK) #define COUNT_OUT_VLAN (COUNT_INT_OUT_VLAN & COUNT_REGISTRY_MASK) #define COUNT_CUSTOM_PRIMITIVES (COUNT_INT_CUSTOM_PRIMITIVES & COUNT_REGISTRY_MASK) /* PRIMITIVES DEFINITION: END */ /* BYTES and PACKETS are used into templates; we let their values to overlap with some values we will not need into templates */ #define LT_BYTES COUNT_SRC_NET #define LT_PACKETS COUNT_DST_NET #define LT_FLOWS COUNT_SUM_HOST #define LT_NO_L2 COUNT_SUM_NET #define FAKE_SRC_MAC 0x00000001 #define FAKE_DST_MAC 0x00000002 #define FAKE_SRC_HOST 0x00000004 #define FAKE_DST_HOST 0x00000008 #define FAKE_SRC_AS 0x00000010 #define FAKE_DST_AS 0x00000020 #define FAKE_COMMS 0x00000040 #define FAKE_PEER_SRC_AS 0x00000080 #define FAKE_PEER_DST_AS 0x00000100 #define FAKE_PEER_SRC_IP 0x00000200 #define FAKE_PEER_DST_IP 0x00000400 #define FAKE_AS_PATH 0x00000800 #define COUNT_SECONDLY 0x00000001 #define COUNT_MINUTELY 0x00000002 #define COUNT_HOURLY 0x00000004 #define COUNT_DAILY 0x00000008 #define COUNT_WEEKLY 0x00000010 #define COUNT_MONTHLY 0x00000020 #define WANT_STATS 0x00000001 #define WANT_ERASE 0x00000002 #define WANT_STATUS 0x00000004 #define WANT_COUNTER 0x00000008 #define WANT_MATCH 0x00000010 #define WANT_RESET 0x00000020 #define WANT_CLASS_TABLE 0x00000040 /* #define XXX 0x00000080 */ #define WANT_LOCK_OP 0x00000100 #define WANT_CUSTOM_PRIMITIVES_TABLE 0x00000200 #define WANT_ERASE_LAST_TSTAMP 0x00000400 #define PIPE_TYPE_METADATA 0x00000001 #define PIPE_TYPE_PAYLOAD 0x00000002 #define PIPE_TYPE_EXTRAS 0x00000004 #define PIPE_TYPE_BGP 0x00000008 #define PIPE_TYPE_MSG 0x00000010 #define PIPE_TYPE_NAT 0x00000020 #define PIPE_TYPE_MPLS 0x00000040 #define PIPE_TYPE_VLEN 0x00000080 #define PIPE_TYPE_LBGP 0x00000100 #define PIPE_TYPE_TUN 0x00000200 #define CHLD_WARNING 0x00000001 #define CHLD_ALERT 0x00000002 #define BGP_SRC_PRIMITIVES_UNK 0x00000000 #define BGP_SRC_PRIMITIVES_KEEP 0x00000001 #define BGP_SRC_PRIMITIVES_MAP 0x00000002 #define BGP_SRC_PRIMITIVES_BGP 0x00000004 #define BGP_ASPATH_HASH_PATHID 0x00000000 #define PRINT_OUTPUT_FORMATTED 0x00000001 #define PRINT_OUTPUT_CSV 0x00000002 #define PRINT_OUTPUT_JSON 0x00000004 #define PRINT_OUTPUT_EVENT 0x00000008 #define PRINT_OUTPUT_AVRO_BIN 0x00000010 #define PRINT_OUTPUT_AVRO_JSON 0x00000020 #define PRINT_OUTPUT_CUSTOM 0x00000040 #define DIRECTION_UNKNOWN 0x00000000 #define DIRECTION_IN 0x00000001 #define DIRECTION_OUT 0x00000002 #define DIRECTION_TAG 0x00000004 #define DIRECTION_TAG2 0x00000008 #define SAMPLING_DIRECTION_UNKNOWN 0 #define SAMPLING_DIRECTION_INGRESS 1 #define SAMPLING_DIRECTION_EGRESS 2 #define SAMPLING_DIRECTION_MAX 2 #define IFINDEX_STATIC 0x00000001 #define IFINDEX_TAG 0x00000002 #define IFINDEX_TAG2 0x00000004 #define CUSTOM_PRIMITIVE_TYPE_UNKNOWN 0 #define CUSTOM_PRIMITIVE_TYPE_UINT 1 #define CUSTOM_PRIMITIVE_TYPE_HEX 2 #define CUSTOM_PRIMITIVE_TYPE_STRING 3 #define CUSTOM_PRIMITIVE_TYPE_IP 4 #define CUSTOM_PRIMITIVE_TYPE_MAC 5 #define CUSTOM_PRIMITIVE_TYPE_RAW 6 #define CUSTOM_PRIMITIVE_TYPE_COMPLEX 7 #define FUNC_TYPE_NULL 0 #define FUNC_TYPE_BGP 1 #define FUNC_TYPE_BMP 2 #define FUNC_TYPE_RPKI 3 #define FUNC_TYPE_SFLOW_COUNTER 4 #define FUNC_TYPE_TELEMETRY 5 #define FUNC_TYPE_BGP_BLACKHOLE 6 #define FUNC_TYPE_MAX 7 #define PM_MSG_BIN_COPY 0 #define PM_MSG_STR_COPY 1 #define PM_MSG_STR_COPY_ZERO 2 #define DYN_STR_UNKNOWN 0 #define DYN_STR_KAFKA_TOPIC 1 #define DYN_STR_KAFKA_PART 2 #define DYN_STR_RABBITMQ_RK 3 #define DYN_STR_MONGODB_TABLE 4 #define DYN_STR_SQL_TABLE 5 #define DYN_STR_PRINT_FILE 6 #define DYN_STR_WRITER_ID 7 #define DYN_STR_MAX 7 typedef u_int32_t pm_class_t; typedef u_int64_t pm_id_t; typedef u_int64_t pm_cfgreg_t; #if defined (WITH_NDPI) typedef struct ndpi_proto pm_class2_t; #endif typedef struct { union { u_int32_t id; char str[PM_COUNTRY_T_STRLEN]; }; } pm_country_t; typedef struct { char str[PM_POCODE_T_STRLEN]; } pm_pocode_t; typedef struct { pm_cfgreg_t type; u_int32_t len; } __attribute__ ((packed)) pm_label_t; /* one-off: pt_ structures should all be defined in pretag.h */ typedef struct { u_int32_t len; char *val; } __attribute__ ((packed))pt_label_t; typedef struct { u_int8_t set; int n; } s_int_t; typedef struct { u_int8_t set; u_int8_t n; } s_uint8_t; typedef struct { u_int8_t set; u_int16_t n; } s_uint16_t; typedef u_int64_t pm_counter_t; /* Keep common NF_AS and NF_NET values aligned, ie. NF_[NET|AS]_KEEP == 0x00000001 */ #define NF_AS_COMPAT 0x00000000 /* Unused */ #define NF_AS_KEEP 0x00000001 /* Keep AS numbers in Sflow or NetFlow packets */ #define NF_AS_NEW 0x00000002 /* ignore ASN from NetFlow and generate from network files */ #define NF_AS_BGP 0x00000004 /* ignore ASN from NetFlow and generate from BGP peerings */ #define NF_AS_FALLBACK 0x80000000 /* Fallback flag */ #define NF_NET_COMPAT 0x00000000 /* Backward compatibility selection */ #define NF_NET_KEEP 0x00000001 /* Determine IP network prefixes from sFlow or NetFlow data */ #define NF_NET_NEW 0x00000002 /* Determine IP network prefixes from network files */ #define NF_NET_BGP 0x00000004 /* Determine IP network prefixes from BGP peerings */ #define NF_NET_STATIC 0x00000008 /* Determine IP network prefixes from static mask */ #define NF_NET_IGP 0x00000010 /* Determine IP network prefixes from IGP */ #define NF_NET_FALLBACK 0x80000000 /* Fallback flag */ /* flow type */ #define PM_FTYPE_TRAFFIC 1 #define PM_FTYPE_IPV4 2 #define PM_FTYPE_IPV6 3 #define PM_FTYPE_VLAN 5 #define PM_FTYPE_VLAN_IPV4 7 /* PM_FTYPE_VLAN + PM_FTYPE_IPV4 */ #define PM_FTYPE_VLAN_IPV6 8 /* PM_FTYPE_VLAN + PM_FTYPE_IPV6 */ #define PM_FTYPE_MPLS 10 #define PM_FTYPE_MPLS_IPV4 12 /* PM_FTYPE_MPLS + PM_FTYPE_IPV4 */ #define PM_FTYPE_MPLS_IPV6 13 /* PM_FTYPE_MPLS + PM_FTYPE_IPV6 */ #define PM_FTYPE_VLAN_MPLS 15 /* PM_FTYPE_MPLS + PM_FTYPE_VLAN */ #define PM_FTYPE_VLAN_MPLS_IPV4 17 /* PM_FTYPE_VLAN_MPLS + PM_FTYPE_IPV4 */ #define PM_FTYPE_VLAN_MPLS_IPV6 18 /* PM_FTYPE_VLAN_MPLS + PM_FTYPE_IPV6 */ #define PM_FTYPE_TRAFFIC_MAX 99 /* temporary: re-coding needed */ /* flow type: NetFlow/IPFIX extended code-points */ #define NF9_FTYPE_DLFS 4 #define NF9_FTYPE_EVENT 100 /* temporary: re-coding needed */ #define NF9_FTYPE_NAT_EVENT 100 #define NF9_FTYPE_OPTION 200 /* Packet pointers indexes */ #define CUSTOM_PRIMITIVE_PACKET_PTR 0 #define CUSTOM_PRIMITIVE_MAC_PTR 1 #define CUSTOM_PRIMITIVE_VLAN_PTR 2 #define CUSTOM_PRIMITIVE_MPLS_PTR 3 #define CUSTOM_PRIMITIVE_L3_PTR 4 #define CUSTOM_PRIMITIVE_L4_PTR 5 #define CUSTOM_PRIMITIVE_PAYLOAD_PTR 6 #define CUSTOM_PRIMITIVE_MAX_PPTRS_IDX 7 /* libpcap supports pkg-config only since recently, so fixing this little >= 1.1.0 definition here for OS's coming with vintage versions installed */ #ifndef PCAP_NETMASK_UNKNOWN #define PCAP_NETMASK_UNKNOWN 0xffffffff #endif pmacct-1.7.8/src/plugin_cmn_json.h0000644000175000017500000002043714354105275016144 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLUGIN_CMN_JSON_H #define PLUGIN_CMN_JSON_H /* typedefs */ #ifdef WITH_JANSSON typedef void (*compose_json_handler)(json_t *, struct chained_cache *); #endif #ifdef WITH_JANSSON /* global vars */ extern compose_json_handler cjhandler[N_PRIMITIVES]; /* prototypes */ extern void compose_json_map_label(json_t *, struct chained_cache *); extern void compose_json_array_tcpflags(json_t *, struct chained_cache *); extern void compose_json_string_fwd_status(json_t *, struct chained_cache *); extern void compose_json_array_mpls_label_stack(json_t *, struct chained_cache *); extern void compose_json_array_tunnel_tcp_flags(json_t *, struct chained_cache *); extern json_t *compose_label_json_data(cdada_list_t *, int); extern json_t *compose_tcpflags_json_data(cdada_list_t *, int); extern json_t *compose_fwd_status_json_data(size_t, cdada_list_t *, int); extern json_t *compose_mpls_label_stack_json_data(u_int32_t *, int); extern void compose_json_event_type(json_t *, struct chained_cache *); extern void compose_json_tag(json_t *, struct chained_cache *); extern void compose_json_tag2(json_t *, struct chained_cache *); extern void compose_json_label(json_t *, struct chained_cache *); extern void compose_json_class(json_t *, struct chained_cache *); #if defined (WITH_NDPI) extern void compose_json_ndpi_class(json_t *, struct chained_cache *); #endif extern void compose_json_src_mac(json_t *, struct chained_cache *); extern void compose_json_dst_mac(json_t *, struct chained_cache *); extern void compose_json_vlan(json_t *, struct chained_cache *); extern void compose_json_out_vlan(json_t *, struct chained_cache *); extern void compose_json_cos(json_t *, struct chained_cache *); extern void compose_json_etype(json_t *, struct chained_cache *); extern void compose_json_src_as(json_t *, struct chained_cache *); extern void compose_json_dst_as(json_t *, struct chained_cache *); extern void compose_json_std_comm(json_t *, struct chained_cache *); extern void compose_json_ext_comm(json_t *, struct chained_cache *); extern void compose_json_lrg_comm(json_t *, struct chained_cache *); extern void compose_json_as_path(json_t *, struct chained_cache *); extern void compose_json_local_pref(json_t *, struct chained_cache *); extern void compose_json_med(json_t *, struct chained_cache *); extern void compose_json_dst_roa(json_t *, struct chained_cache *); extern void compose_json_peer_src_as(json_t *, struct chained_cache *); extern void compose_json_peer_dst_as(json_t *, struct chained_cache *); extern void compose_json_peer_src_ip(json_t *, struct chained_cache *); extern void compose_json_peer_dst_ip(json_t *, struct chained_cache *); extern void compose_json_src_std_comm(json_t *, struct chained_cache *); extern void compose_json_src_ext_comm(json_t *, struct chained_cache *); extern void compose_json_src_lrg_comm(json_t *, struct chained_cache *); extern void compose_json_src_as_path(json_t *, struct chained_cache *); extern void compose_json_src_local_pref(json_t *, struct chained_cache *); extern void compose_json_src_med(json_t *, struct chained_cache *); extern void compose_json_src_roa(json_t *, struct chained_cache *); extern void compose_json_in_iface(json_t *, struct chained_cache *); extern void compose_json_out_iface(json_t *, struct chained_cache *); extern void compose_json_mpls_vpn_rd(json_t *, struct chained_cache *); extern void compose_json_mpls_pw_id(json_t *, struct chained_cache *); extern void compose_json_src_host(json_t *, struct chained_cache *); extern void compose_json_src_net(json_t *, struct chained_cache *); extern void compose_json_dst_host(json_t *, struct chained_cache *); extern void compose_json_dst_net(json_t *, struct chained_cache *); extern void compose_json_src_mask(json_t *, struct chained_cache *); extern void compose_json_dst_mask(json_t *, struct chained_cache *); extern void compose_json_src_port(json_t *, struct chained_cache *); extern void compose_json_dst_port(json_t *, struct chained_cache *); #if defined (WITH_GEOIP) extern void compose_json_src_host_country(json_t *, struct chained_cache *); extern void compose_json_dst_host_country(json_t *, struct chained_cache *); #endif #if defined (WITH_GEOIPV2) extern void compose_json_src_host_country(json_t *, struct chained_cache *); extern void compose_json_dst_host_country(json_t *, struct chained_cache *); extern void compose_json_src_host_pocode(json_t *, struct chained_cache *); extern void compose_json_dst_host_pocode(json_t *, struct chained_cache *); extern void compose_json_src_host_coords(json_t *, struct chained_cache *); extern void compose_json_dst_host_coords(json_t *, struct chained_cache *); #endif extern void compose_json_tcp_flags(json_t *, struct chained_cache *); extern void compose_json_fwd_status(json_t *, struct chained_cache *); extern void compose_json_mpls_label_stack(json_t *, struct chained_cache *); extern void compose_json_proto(json_t *, struct chained_cache *); extern void compose_json_tos(json_t *, struct chained_cache *); extern void compose_json_sampling_rate(json_t *, struct chained_cache *); extern void compose_json_sampling_direction(json_t *, struct chained_cache *); extern void compose_json_post_nat_src_host(json_t *, struct chained_cache *); extern void compose_json_post_nat_dst_host(json_t *, struct chained_cache *); extern void compose_json_post_nat_src_port(json_t *, struct chained_cache *); extern void compose_json_post_nat_dst_port(json_t *, struct chained_cache *); extern void compose_json_nat_event(json_t *, struct chained_cache *); extern void compose_json_fw_event(json_t *, struct chained_cache *); extern void compose_json_mpls_label_top(json_t *, struct chained_cache *); extern void compose_json_mpls_label_bottom(json_t *, struct chained_cache *); extern void compose_json_tunnel_src_mac(json_t *, struct chained_cache *); extern void compose_json_tunnel_dst_mac(json_t *, struct chained_cache *); extern void compose_json_tunnel_src_host(json_t *, struct chained_cache *); extern void compose_json_tunnel_dst_host(json_t *, struct chained_cache *); extern void compose_json_tunnel_proto(json_t *, struct chained_cache *); extern void compose_json_tunnel_tos(json_t *, struct chained_cache *); extern void compose_json_tunnel_src_port(json_t *, struct chained_cache *); extern void compose_json_tunnel_dst_port(json_t *, struct chained_cache *); extern void compose_json_tunnel_tcp_flags(json_t *, struct chained_cache *); extern void compose_json_vxlan(json_t *, struct chained_cache *); extern void compose_json_timestamp_start(json_t *, struct chained_cache *); extern void compose_json_timestamp_end(json_t *, struct chained_cache *); extern void compose_json_timestamp_arrival(json_t *, struct chained_cache *); extern void compose_json_timestamp_export(json_t *, struct chained_cache *); extern void compose_json_timestamp_stitching(json_t *, struct chained_cache *); extern void compose_json_export_proto_seqno(json_t *, struct chained_cache *); extern void compose_json_export_proto_version(json_t *, struct chained_cache *); extern void compose_json_export_proto_sysid(json_t *, struct chained_cache *); extern void compose_json_custom_primitives(json_t *, struct chained_cache *); extern void compose_json_history(json_t *, struct chained_cache *); extern void compose_json_flows(json_t *, struct chained_cache *); extern void compose_json_counters(json_t *, struct chained_cache *); #endif extern void compose_json(u_int64_t, u_int64_t); extern void *compose_purge_init_json(char *, pid_t); extern void *compose_purge_close_json(char *, pid_t, int, int, int); #endif //PLUGIN_CMN_JSON_H pmacct-1.7.8/src/preprocess.h0000644000175000017500000000776314354105275015154 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PREPROCESS_H #define PREPROCESS_H /* defines */ #define PREP_DICT_SQL 1 #define PREP_DICT_PRINT 2 /* structures */ struct _preprocess_dictionary_line { char key[SRVBUFLEN]; }; struct preprocess { u_int32_t qnum; u_int16_t minp; u_int16_t minf; u_int32_t minb; u_int16_t maxp; u_int16_t maxf; u_int32_t maxb; u_int16_t maxbpp; u_int16_t maxppf; u_int16_t minbpp; u_int16_t minppf; u_int32_t fss; /* threshold: flow size (flow size dependent sampling) */ u_int32_t fsrc; /* threshold: flows number (flow sampling with resource constraints) */ int usrf; /* renormalization factor for uniform sampling methods */ int adjb; /* adjusts bytes counter by 'adjb' bytes */ u_int8_t recover; u_int8_t num; /* total number of preprocess clauses specified: actions + checks */ u_int8_t checkno; /* number of checks */ u_int8_t actionno; /* number of actions */ }; struct fsrc_queue_elem { struct fsrc_queue_elem *next; struct db_cache *cache_ptr; float z; }; struct _fsrc_queue { struct fsrc_queue_elem head; u_int32_t num; }; /* typedefs */ //fwd decl struct chained_cache; typedef int (*sql_preprocess_func) (struct db_cache *[], int *, int); typedef int (*P_preprocess_func) (struct chained_cache *[], int *, int); extern void set_preprocess_funcs(char *, struct preprocess *, int); extern int cond_qnum(struct db_cache *[], int *, int); extern int check_minp(struct db_cache *[], int *, int); extern int check_minb(struct db_cache *[], int *, int); extern int check_minf(struct db_cache *[], int *, int); extern int check_maxp(struct db_cache *[], int *, int); extern int check_maxb(struct db_cache *[], int *, int); extern int check_maxf(struct db_cache *[], int *, int); extern int check_maxbpp(struct db_cache *[], int *, int); extern int check_maxppf(struct db_cache *[], int *, int); extern int check_minbpp(struct db_cache *[], int *, int); extern int check_minppf(struct db_cache *[], int *, int); extern int check_fss(struct db_cache *[], int *, int); extern int check_fsrc(struct db_cache *[], int *, int); extern int action_usrf(struct db_cache *[], int *, int); extern int action_adjb(struct db_cache *[], int *, int); extern int P_check_minp(struct chained_cache *[], int *, int); extern int P_check_minb(struct chained_cache *[], int *, int); extern int P_check_minf(struct chained_cache *[], int *, int); extern int P_check_maxp(struct chained_cache *[], int *, int); extern int P_check_maxb(struct chained_cache *[], int *, int); extern int P_check_maxf(struct chained_cache *[], int *, int); extern int P_check_minbpp(struct chained_cache *[], int *, int); extern int P_check_minppf(struct chained_cache *[], int *, int); extern int mandatory_invalidate(struct db_cache *[], int *, int); extern int mandatory_validate(struct db_cache *[], int *, int); extern void check_validity(struct db_cache *, int); extern int P_mandatory_invalidate(struct chained_cache *[], int *, int); extern void P_check_validity(struct chained_cache *, int); extern sql_preprocess_func sql_preprocess_funcs[2*N_FUNCS]; /* 20 */ extern P_preprocess_func P_preprocess_funcs[2*N_FUNCS]; /* 20 */ extern struct preprocess prep; extern struct _fsrc_queue fsrc_queue; #endif // PREPROCESS_H pmacct-1.7.8/src/plugin_cmn_avro.c0000644000175000017500000017012314354105275016133 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_common.h" #include "plugin_cmn_json.h" #include "plugin_cmn_avro.h" #include "ip_flow.h" #include "classifier.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif #ifdef WITH_AVRO /* global variables */ avro_schema_t p_avro_acct_schema, p_avro_acct_init_schema, p_avro_acct_close_schema; avro_schema_t sc_type_array, sc_type_map, sc_type_string, sc_type_union; /* functions */ avro_schema_t p_avro_schema_build_acct_data(u_int64_t wtc, u_int64_t wtc_2) { avro_schema_t schema = avro_schema_record("acct_data", NULL); avro_schema_t optlong_s = avro_schema_union(); avro_schema_t optstr_s = avro_schema_union(); Log(LOG_INFO, "INFO ( %s/%s ): p_avro_schema_build_acct_data(): building acct schema.\n", config.name, config.type); avro_schema_union_append(optlong_s, avro_schema_null()); avro_schema_union_append(optlong_s, avro_schema_long()); avro_schema_union_append(optstr_s, avro_schema_null()); avro_schema_union_append(optstr_s, avro_schema_string()); if (wtc & COUNT_TAG) avro_schema_record_field_append(schema, "tag", avro_schema_long()); if (wtc & COUNT_TAG2) avro_schema_record_field_append(schema, "tag2", avro_schema_long()); if (wtc_2 & COUNT_LABEL) { if (config.pretag_label_encode_as_map) { compose_label_avro_schema_nonopt(schema); } else { avro_schema_record_field_append(schema, "label", avro_schema_string()); } } if (wtc & COUNT_CLASS) avro_schema_record_field_append(schema, "class_legacy", avro_schema_string()); #if defined (WITH_NDPI) if (wtc_2 & COUNT_NDPI_CLASS) avro_schema_record_field_append(schema, "class", avro_schema_string()); #endif #if defined (HAVE_L2) if (wtc & (COUNT_SRC_MAC|COUNT_SUM_MAC)) avro_schema_record_field_append(schema, "mac_src", avro_schema_string()); if (wtc & COUNT_DST_MAC) avro_schema_record_field_append(schema, "mac_dst", avro_schema_string()); if (wtc & COUNT_VLAN) { if (config.tmp_vlan_legacy) { avro_schema_record_field_append(schema, "vlan", avro_schema_long()); } else { avro_schema_record_field_append(schema, "vlan_in", avro_schema_long()); } } if (wtc_2 & COUNT_OUT_VLAN) avro_schema_record_field_append(schema, "vlan_out", avro_schema_long()); if (wtc & COUNT_COS) avro_schema_record_field_append(schema, "cos", avro_schema_long()); if (wtc & COUNT_ETHERTYPE) avro_schema_record_field_append(schema, "etype", avro_schema_string()); #endif if (wtc & (COUNT_SRC_AS|COUNT_SUM_AS)) avro_schema_record_field_append(schema, "as_src", avro_schema_long()); if (wtc & COUNT_DST_AS) avro_schema_record_field_append(schema, "as_dst", avro_schema_long()); if (wtc & COUNT_STD_COMM) avro_schema_record_field_append(schema, "comms", avro_schema_string()); if (wtc & COUNT_EXT_COMM) avro_schema_record_field_append(schema, "ecomms", avro_schema_string()); if (wtc_2 & COUNT_LRG_COMM) avro_schema_record_field_append(schema, "lcomms", avro_schema_string()); if (wtc & COUNT_AS_PATH) avro_schema_record_field_append(schema, "as_path", avro_schema_string()); if (wtc & COUNT_LOCAL_PREF) avro_schema_record_field_append(schema, "local_pref", avro_schema_long()); if (wtc & COUNT_MED) avro_schema_record_field_append(schema, "med", avro_schema_long()); if (wtc_2 & COUNT_DST_ROA) avro_schema_record_field_append(schema, "roa_dst", avro_schema_string()); if (wtc & COUNT_PEER_SRC_AS) avro_schema_record_field_append(schema, "peer_as_src", avro_schema_long()); if (wtc & COUNT_PEER_DST_AS) avro_schema_record_field_append(schema, "peer_as_dst", avro_schema_long()); if (wtc & COUNT_PEER_SRC_IP) avro_schema_record_field_append(schema, "peer_ip_src", avro_schema_string()); if (wtc & COUNT_PEER_DST_IP) avro_schema_record_field_append(schema, "peer_ip_dst", avro_schema_string()); if (wtc & COUNT_SRC_STD_COMM) avro_schema_record_field_append(schema, "comms_src", avro_schema_string()); if (wtc & COUNT_SRC_EXT_COMM) avro_schema_record_field_append(schema, "ecomms_src", avro_schema_string()); if (wtc_2 & COUNT_SRC_LRG_COMM) avro_schema_record_field_append(schema, "lcomms_src", avro_schema_string()); if (wtc & COUNT_SRC_AS_PATH) avro_schema_record_field_append(schema, "as_path_src", avro_schema_string()); if (wtc & COUNT_SRC_LOCAL_PREF) avro_schema_record_field_append(schema, "local_pref_src", avro_schema_long()); if (wtc & COUNT_SRC_MED) avro_schema_record_field_append(schema, "med_src", avro_schema_long()); if (wtc_2 & COUNT_SRC_ROA) avro_schema_record_field_append(schema, "roa_src", avro_schema_string()); if (wtc & COUNT_IN_IFACE) avro_schema_record_field_append(schema, "iface_in", avro_schema_long()); if (wtc & COUNT_OUT_IFACE) avro_schema_record_field_append(schema, "iface_out", avro_schema_long()); if (wtc & COUNT_MPLS_VPN_RD) avro_schema_record_field_append(schema, "mpls_vpn_rd", avro_schema_string()); if (wtc_2 & COUNT_MPLS_PW_ID) avro_schema_record_field_append(schema, "mpls_pw_id", avro_schema_long()); if (wtc & (COUNT_SRC_HOST|COUNT_SUM_HOST)) avro_schema_record_field_append(schema, "ip_src", avro_schema_string()); if (wtc & (COUNT_SRC_NET|COUNT_SUM_NET)) avro_schema_record_field_append(schema, "net_src", avro_schema_string()); if (wtc & COUNT_DST_HOST) avro_schema_record_field_append(schema, "ip_dst", avro_schema_string()); if (wtc & COUNT_DST_NET) avro_schema_record_field_append(schema, "net_dst", avro_schema_string()); if (wtc & COUNT_SRC_NMASK) avro_schema_record_field_append(schema, "mask_src", avro_schema_long()); if (wtc & COUNT_DST_NMASK) avro_schema_record_field_append(schema, "mask_dst", avro_schema_long()); if (wtc & (COUNT_SRC_PORT|COUNT_SUM_PORT)) avro_schema_record_field_append(schema, "port_src", avro_schema_long()); if (wtc & COUNT_DST_PORT) avro_schema_record_field_append(schema, "port_dst", avro_schema_long()); #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) avro_schema_record_field_append(schema, "country_ip_src", avro_schema_string()); if (wtc_2 & COUNT_DST_HOST_COUNTRY) avro_schema_record_field_append(schema, "country_ip_dst", avro_schema_string()); #endif #if defined (WITH_GEOIPV2) if (wtc_2 & COUNT_SRC_HOST_POCODE) avro_schema_record_field_append(schema, "pocode_ip_src", avro_schema_string()); if (wtc_2 & COUNT_DST_HOST_POCODE) avro_schema_record_field_append(schema, "pocode_ip_dst", avro_schema_string()); if (wtc_2 & COUNT_SRC_HOST_COORDS) { avro_schema_record_field_append(schema, "lat_ip_src", avro_schema_double()); avro_schema_record_field_append(schema, "lon_ip_src", avro_schema_double()); } if (wtc_2 & COUNT_DST_HOST_COORDS) { avro_schema_record_field_append(schema, "lat_ip_dst", avro_schema_double()); avro_schema_record_field_append(schema, "lon_ip_dst", avro_schema_double()); } #endif if (wtc & COUNT_TCPFLAGS) { if (config.tcpflags_encode_as_array) { compose_tcpflags_avro_schema(schema); } else { avro_schema_record_field_append(schema, "tcp_flags", avro_schema_string()); } } if (wtc_2 & COUNT_FWD_STATUS) { if (config.fwd_status_encode_as_string) { compose_fwd_status_avro_schema(schema); } else { avro_schema_record_field_append(schema, "fwd_status", avro_schema_string()); } } if (wtc_2 & COUNT_MPLS_LABEL_STACK) { if (config.mpls_label_stack_encode_as_array) { compose_mpls_label_stack_schema(schema); } else { avro_schema_record_field_append(schema, "mpls_label_stack", avro_schema_string()); } } if (wtc & COUNT_IP_PROTO) avro_schema_record_field_append(schema, "ip_proto", avro_schema_string()); if (wtc & COUNT_IP_TOS) avro_schema_record_field_append(schema, "tos", avro_schema_long()); if (wtc_2 & COUNT_SAMPLING_RATE) avro_schema_record_field_append(schema, "sampling_rate", avro_schema_long()); if (wtc_2 & COUNT_SAMPLING_DIRECTION) avro_schema_record_field_append(schema, "sampling_direction", avro_schema_string()); if (wtc_2 & COUNT_POST_NAT_SRC_HOST) avro_schema_record_field_append(schema, "post_nat_ip_src", avro_schema_string()); if (wtc_2 & COUNT_POST_NAT_DST_HOST) avro_schema_record_field_append(schema, "post_nat_ip_dst", avro_schema_string()); if (wtc_2 & COUNT_POST_NAT_SRC_PORT) avro_schema_record_field_append(schema, "post_nat_port_src", avro_schema_long()); if (wtc_2 & COUNT_POST_NAT_DST_PORT) avro_schema_record_field_append(schema, "post_nat_port_dst", avro_schema_long()); if (wtc_2 & COUNT_NAT_EVENT) avro_schema_record_field_append(schema, "nat_event", avro_schema_long()); if (wtc_2 & COUNT_FW_EVENT) avro_schema_record_field_append(schema, "fw_event", avro_schema_long()); if (wtc_2 & COUNT_MPLS_LABEL_TOP) avro_schema_record_field_append(schema, "mpls_label_top", avro_schema_long()); if (wtc_2 & COUNT_MPLS_LABEL_BOTTOM) avro_schema_record_field_append(schema, "mpls_label_bottom", avro_schema_long()); if (wtc_2 & COUNT_TUNNEL_SRC_MAC) avro_schema_record_field_append(schema, "tunnel_mac_src", avro_schema_string()); if (wtc_2 & COUNT_TUNNEL_DST_MAC) avro_schema_record_field_append(schema, "tunnel_mac_dst", avro_schema_string()); if (wtc_2 & COUNT_TUNNEL_SRC_HOST) avro_schema_record_field_append(schema, "tunnel_ip_src", avro_schema_string()); if (wtc_2 & COUNT_TUNNEL_DST_HOST) avro_schema_record_field_append(schema, "tunnel_ip_dst", avro_schema_string()); if (wtc_2 & COUNT_TUNNEL_IP_PROTO) avro_schema_record_field_append(schema, "tunnel_ip_proto", avro_schema_string()); if (wtc_2 & COUNT_TUNNEL_IP_TOS) avro_schema_record_field_append(schema, "tunnel_tos", avro_schema_long()); if (wtc_2 & COUNT_TUNNEL_SRC_PORT) avro_schema_record_field_append(schema, "tunnel_port_src", avro_schema_long()); if (wtc_2 & COUNT_TUNNEL_DST_PORT) avro_schema_record_field_append(schema, "tunnel_port_dst", avro_schema_long()); if (wtc & COUNT_TUNNEL_TCPFLAGS) { if (config.tcpflags_encode_as_array) { compose_tunnel_tcpflags_avro_schema(schema); } else { avro_schema_record_field_append(schema, "tunnel_tcp_flags", avro_schema_string()); } } if (wtc_2 & COUNT_VXLAN) avro_schema_record_field_append(schema, "vxlan", avro_schema_long()); if (wtc_2 & COUNT_TIMESTAMP_START) avro_schema_record_field_append(schema, "timestamp_start", avro_schema_string()); if (wtc_2 & COUNT_TIMESTAMP_END) avro_schema_record_field_append(schema, "timestamp_end", avro_schema_string()); if (wtc_2 & COUNT_TIMESTAMP_ARRIVAL) avro_schema_record_field_append(schema, "timestamp_arrival", avro_schema_string()); if (config.nfacctd_stitching) { avro_schema_record_field_append(schema, "timestamp_min", optstr_s); avro_schema_record_field_append(schema, "timestamp_max", optstr_s); } if (wtc_2 & COUNT_EXPORT_PROTO_SEQNO) avro_schema_record_field_append(schema, "export_proto_seqno", avro_schema_long()); if (wtc_2 & COUNT_EXPORT_PROTO_VERSION) avro_schema_record_field_append(schema, "export_proto_version", avro_schema_long()); if (wtc_2 & COUNT_EXPORT_PROTO_SYSID) avro_schema_record_field_append(schema, "export_proto_sysid", avro_schema_long()); if (wtc_2 & COUNT_EXPORT_PROTO_TIME) avro_schema_record_field_append(schema, "timestamp_export", avro_schema_string()); if (config.cpptrs.num > 0) { avro_schema_record_field_append( schema, "custom_primitives", avro_schema_map(avro_schema_string())); } if (config.sql_history) { avro_schema_record_field_append(schema, "stamp_inserted", optstr_s); avro_schema_record_field_append(schema, "stamp_updated", optstr_s); } avro_schema_record_field_append(schema, "packets", optlong_s); avro_schema_record_field_append(schema, "flows", optlong_s); avro_schema_record_field_append(schema, "bytes", optlong_s); avro_schema_decref(optlong_s); avro_schema_decref(optstr_s); return schema; } avro_schema_t p_avro_schema_build_acct_init() { avro_schema_t schema = avro_schema_record("acct_init", NULL); Log(LOG_INFO, "INFO ( %s/%s ): p_avro_schema_build_acct_init(): building acct_init schema.\n", config.name, config.type); avro_schema_record_field_append(schema, "event_type", avro_schema_string()); avro_schema_record_field_append(schema, "writer_id", avro_schema_string()); return schema; } avro_schema_t p_avro_schema_build_acct_close() { avro_schema_t schema = avro_schema_record("acct_close", NULL); Log(LOG_INFO, "INFO ( %s/%s ): p_avro_schema_build_acct_close(): building acct_close schema.\n", config.name, config.type); avro_schema_record_field_append(schema, "event_type", avro_schema_string()); avro_schema_record_field_append(schema, "writer_id", avro_schema_string()); avro_schema_record_field_append(schema, "purged_entries", avro_schema_long()); avro_schema_record_field_append(schema, "total_entries", avro_schema_long()); avro_schema_record_field_append(schema, "duration", avro_schema_int()); return schema; } void p_avro_schema_add_writer_id(avro_schema_t schema) { avro_schema_record_field_append(schema, "writer_id", avro_schema_string()); } avro_value_t compose_avro_acct_init(char *writer_name, pid_t writer_pid, avro_value_iface_t *iface) { char event_type[] = "purge_init", wid[SHORTSHORTBUFLEN]; avro_value_t value; avro_value_t field; pm_avro_check(avro_generic_value_new(iface, &value)); pm_avro_check(avro_value_get_by_name(&value, "event_type", &field, NULL)); pm_avro_check(avro_value_set_string(&field, event_type)); snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", writer_name, writer_pid); pm_avro_check(avro_value_get_by_name(&value, "writer_id", &field, NULL)); pm_avro_check(avro_value_set_string(&field, wid)); return value; } avro_value_t compose_avro_acct_close(char *writer_name, pid_t writer_pid, int purged_entries, int total_entries, int duration, avro_value_iface_t *iface) { char event_type[] = "purge_close", wid[SHORTSHORTBUFLEN]; avro_value_t value; avro_value_t field; pm_avro_check(avro_generic_value_new(iface, &value)); pm_avro_check(avro_value_get_by_name(&value, "event_type", &field, NULL)); pm_avro_check(avro_value_set_string(&field, event_type)); snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", writer_name, writer_pid); pm_avro_check(avro_value_get_by_name(&value, "writer_id", &field, NULL)); pm_avro_check(avro_value_set_string(&field, wid)); pm_avro_check(avro_value_get_by_name(&value, "purged_entries", &field, NULL)); pm_avro_check(avro_value_set_long(&field, purged_entries)); pm_avro_check(avro_value_get_by_name(&value, "total_entries", &field, NULL)); pm_avro_check(avro_value_set_long(&field, total_entries)); pm_avro_check(avro_value_get_by_name(&value, "duration", &field, NULL)); pm_avro_check(avro_value_set_int(&field, total_entries)); return value; } avro_value_t compose_avro_acct_data(u_int64_t wtc, u_int64_t wtc_2, u_int8_t flow_type, struct pkt_primitives *pbase, struct pkt_bgp_primitives *pbgp, struct pkt_nat_primitives *pnat, struct pkt_mpls_primitives *pmpls, struct pkt_tunnel_primitives *ptun, u_char *pcust, struct pkt_vlen_hdr_primitives *pvlen, pm_counter_t bytes_counter, pm_counter_t packet_counter, pm_counter_t flow_counter, u_int8_t tcp_flags, u_int8_t tunnel_tcp_flags, struct timeval *basetime, struct pkt_stitching *stitch, avro_value_iface_t *iface) { char src_mac[18], dst_mac[18], src_host[INET6_ADDRSTRLEN], dst_host[INET6_ADDRSTRLEN], ip_address[INET6_ADDRSTRLEN]; char rd_str[SRVBUFLEN], misc_str[SRVBUFLEN], *as_path, *bgp_comm, empty_string[] = "", *str_ptr; char tstamp_str[SRVBUFLEN]; avro_value_t value; avro_value_t field; avro_value_t branch; pm_avro_check(avro_generic_value_new(iface, &value)); if (wtc & COUNT_TAG) { pm_avro_check(avro_value_get_by_name(&value, "tag", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->tag)); } if (wtc & COUNT_TAG2) { pm_avro_check(avro_value_get_by_name(&value, "tag2", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->tag2)); } if (wtc_2 & COUNT_LABEL) { vlen_prims_get(pvlen, COUNT_INT_LABEL, &str_ptr); if (!str_ptr) str_ptr = empty_string; if (config.pretag_label_encode_as_map) { compose_label_avro_data_nonopt(str_ptr, value); } else { pm_avro_check(avro_value_get_by_name(&value, "label", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } } if (wtc & COUNT_CLASS) { pm_avro_check(avro_value_get_by_name(&value, "class", &field, NULL)); pm_avro_check(avro_value_set_string(&field, ((pbase->class && class[(pbase->class)-1].id) ? class[(pbase->class)-1].protocol : "unknown" ))); } #if defined (WITH_NDPI) if (wtc_2 & COUNT_NDPI_CLASS) { char ndpi_class[SUPERSHORTBUFLEN]; snprintf(ndpi_class, SUPERSHORTBUFLEN, "%s/%s", ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, pbase->ndpi_class.master_protocol), ndpi_get_proto_name(pm_ndpi_wfl->ndpi_struct, pbase->ndpi_class.app_protocol)); pm_avro_check(avro_value_get_by_name(&value, "class", &field, NULL)); pm_avro_check(avro_value_set_string(&field, ndpi_class)); } #endif #if defined (HAVE_L2) if (wtc & (COUNT_SRC_MAC|COUNT_SUM_MAC)) { etheraddr_string(pbase->eth_shost, src_mac); pm_avro_check(avro_value_get_by_name(&value, "mac_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_mac)); } if (wtc & COUNT_DST_MAC) { etheraddr_string(pbase->eth_dhost, dst_mac); pm_avro_check(avro_value_get_by_name(&value, "mac_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_mac)); } if (wtc & COUNT_VLAN) { if (config.tmp_vlan_legacy) { pm_avro_check(avro_value_get_by_name(&value, "vlan", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->vlan_id)); } else { pm_avro_check(avro_value_get_by_name(&value, "vlan_in", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->vlan_id)); } } if (wtc_2 & COUNT_OUT_VLAN) { pm_avro_check(avro_value_get_by_name(&value, "vlan_out", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->out_vlan_id)); } if (wtc & COUNT_COS) { pm_avro_check(avro_value_get_by_name(&value, "cos", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->cos)); } if (wtc & COUNT_ETHERTYPE) { sprintf(misc_str, "%x", pbase->etype); pm_avro_check(avro_value_get_by_name(&value, "etype", &field, NULL)); pm_avro_check(avro_value_set_string(&field, misc_str)); } #endif if (wtc & (COUNT_SRC_AS|COUNT_SUM_AS)) { pm_avro_check(avro_value_get_by_name(&value, "as_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->src_as)); } if (wtc & COUNT_DST_AS) { pm_avro_check(avro_value_get_by_name(&value, "as_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->dst_as)); } if (wtc & COUNT_STD_COMM) { vlen_prims_get(pvlen, COUNT_INT_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "comms", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_EXT_COMM) { vlen_prims_get(pvlen, COUNT_INT_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "ecomms", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc_2 & COUNT_LRG_COMM) { vlen_prims_get(pvlen, COUNT_INT_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "lcomms", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_AS_PATH) { vlen_prims_get(pvlen, COUNT_INT_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "as_path", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_LOCAL_PREF) { pm_avro_check(avro_value_get_by_name(&value, "local_pref", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->local_pref)); } if (wtc & COUNT_MED) { pm_avro_check(avro_value_get_by_name(&value, "med", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->med)); } if (wtc_2 & COUNT_DST_ROA) { pm_avro_check(avro_value_get_by_name(&value, "roa_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, rpki_roa_print(pbgp->dst_roa))); } if (wtc & COUNT_PEER_SRC_AS) { pm_avro_check(avro_value_get_by_name(&value, "peer_as_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->peer_src_as)); } if (wtc & COUNT_PEER_DST_AS) { pm_avro_check(avro_value_get_by_name(&value, "peer_as_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->peer_dst_as)); } if (wtc & COUNT_PEER_SRC_IP) { pm_avro_check(avro_value_get_by_name(&value, "peer_ip_src", &field, NULL)); addr_to_str(ip_address, &pbgp->peer_src_ip); pm_avro_check(avro_value_set_string(&field, ip_address)); } if (wtc & COUNT_PEER_DST_IP) { pm_avro_check(avro_value_get_by_name(&value, "peer_ip_dst", &field, NULL)); addr_to_str2(ip_address, &pbgp->peer_dst_ip, ft2af(flow_type)); pm_avro_check(avro_value_set_string(&field, ip_address)); } if (wtc & COUNT_STD_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_STD_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "comms_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_SRC_EXT_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_EXT_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "ecomms_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc_2 & COUNT_SRC_LRG_COMM) { vlen_prims_get(pvlen, COUNT_INT_SRC_LRG_COMM, &str_ptr); if (str_ptr) { bgp_comm = str_ptr; while (bgp_comm) { bgp_comm = strchr(str_ptr, ' '); if (bgp_comm) *bgp_comm = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "lcomms_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_SRC_AS_PATH) { vlen_prims_get(pvlen, COUNT_INT_SRC_AS_PATH, &str_ptr); if (str_ptr) { as_path = str_ptr; while (as_path) { as_path = strchr(str_ptr, ' '); if (as_path) *as_path = '_'; } } else str_ptr = empty_string; pm_avro_check(avro_value_get_by_name(&value, "as_path_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, str_ptr)); } if (wtc & COUNT_SRC_LOCAL_PREF) { pm_avro_check(avro_value_get_by_name(&value, "local_pref_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->src_local_pref)); } if (wtc & COUNT_SRC_MED) { pm_avro_check(avro_value_get_by_name(&value, "med_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->src_med)); } if (wtc_2 & COUNT_SRC_ROA) { pm_avro_check(avro_value_get_by_name(&value, "roa_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, rpki_roa_print(pbgp->src_roa))); } if (wtc & COUNT_IN_IFACE) { pm_avro_check(avro_value_get_by_name(&value, "iface_in", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->ifindex_in)); } if (wtc & COUNT_OUT_IFACE) { pm_avro_check(avro_value_get_by_name(&value, "iface_out", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->ifindex_out)); } if (wtc & COUNT_MPLS_VPN_RD) { bgp_rd2str(rd_str, &pbgp->mpls_vpn_rd); pm_avro_check(avro_value_get_by_name(&value, "mpls_vpn_rd", &field, NULL)); pm_avro_check(avro_value_set_string(&field, rd_str)); } if (wtc_2 & COUNT_MPLS_PW_ID) { pm_avro_check(avro_value_get_by_name(&value, "mpls_pw_id", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbgp->mpls_pw_id)); } if (wtc & (COUNT_SRC_HOST|COUNT_SUM_HOST)) { addr_to_str(src_host, &pbase->src_ip); pm_avro_check(avro_value_get_by_name(&value, "ip_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_host)); } if (wtc & (COUNT_SRC_NET|COUNT_SUM_NET)) { addr_to_str(src_host, &pbase->src_net); pm_avro_check(avro_value_get_by_name(&value, "net_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_host)); } if (wtc & COUNT_DST_HOST) { addr_to_str(dst_host, &pbase->dst_ip); pm_avro_check(avro_value_get_by_name(&value, "ip_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_host)); } if (wtc & COUNT_DST_NET) { addr_to_str(dst_host, &pbase->dst_net); pm_avro_check(avro_value_get_by_name(&value, "net_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_host)); } if (wtc & COUNT_SRC_NMASK) { pm_avro_check(avro_value_get_by_name(&value, "mask_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->src_nmask)); } if (wtc & COUNT_DST_NMASK) { pm_avro_check(avro_value_get_by_name(&value, "mask_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->dst_nmask)); } if (wtc & (COUNT_SRC_PORT|COUNT_SUM_PORT)) { pm_avro_check(avro_value_get_by_name(&value, "port_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->src_port)); } if (wtc & COUNT_DST_PORT) { pm_avro_check(avro_value_get_by_name(&value, "port_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->dst_port)); } #if defined (WITH_GEOIP) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { pm_avro_check(avro_value_get_by_name(&value, "country_ip_src", &field, NULL)); if (pbase->src_ip_country.id > 0) pm_avro_check(avro_value_set_string(&field, GeoIP_code_by_id(pbase->src_ip_country.id))); else pm_avro_check(avro_value_set_string(&field, empty_string)); } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { pm_avro_check(avro_value_get_by_name(&value, "country_ip_dst", &field, NULL)); if (pbase->dst_ip_country.id > 0) pm_avro_check(avro_value_set_string(&field, GeoIP_code_by_id(pbase->dst_ip_country.id))); else pm_avro_check(avro_value_set_string(&field, empty_string)); } #endif #if defined (WITH_GEOIPV2) if (wtc_2 & COUNT_SRC_HOST_COUNTRY) { pm_avro_check(avro_value_get_by_name(&value, "country_ip_src", &field, NULL)); if (strlen(pbase->src_ip_country.str)) pm_avro_check(avro_value_set_string(&field, pbase->src_ip_country.str)); else pm_avro_check(avro_value_set_string(&field, empty_string)); } if (wtc_2 & COUNT_DST_HOST_COUNTRY) { pm_avro_check(avro_value_get_by_name(&value, "country_ip_dst", &field, NULL)); if (strlen(pbase->dst_ip_country.str)) pm_avro_check(avro_value_set_string(&field, pbase->dst_ip_country.str)); else pm_avro_check(avro_value_set_string(&field, empty_string)); } if (wtc_2 & COUNT_SRC_HOST_POCODE) { pm_avro_check(avro_value_get_by_name(&value, "pocode_ip_src", &field, NULL)); if (strlen(pbase->src_ip_pocode.str)) pm_avro_check(avro_value_set_string(&field, pbase->src_ip_pocode.str)); else pm_avro_check(avro_value_set_string(&field, empty_string)); } if (wtc_2 & COUNT_DST_HOST_POCODE) { pm_avro_check(avro_value_get_by_name(&value, "pocode_ip_dst", &field, NULL)); if (strlen(pbase->dst_ip_pocode.str)) pm_avro_check(avro_value_set_string(&field, pbase->dst_ip_pocode.str)); else pm_avro_check(avro_value_set_string(&field, empty_string)); } if (wtc_2 & COUNT_SRC_HOST_COORDS) { pm_avro_check(avro_value_get_by_name(&value, "lat_ip_src", &field, NULL)); pm_avro_check(avro_value_set_double(&field, pbase->src_ip_lat)); pm_avro_check(avro_value_get_by_name(&value, "lon_ip_src", &field, NULL)); pm_avro_check(avro_value_set_double(&field, pbase->src_ip_lon)); } if (wtc_2 & COUNT_DST_HOST_COORDS) { pm_avro_check(avro_value_get_by_name(&value, "lat_ip_dst", &field, NULL)); pm_avro_check(avro_value_set_double(&field, pbase->dst_ip_lat)); pm_avro_check(avro_value_get_by_name(&value, "lon_ip_dst", &field, NULL)); pm_avro_check(avro_value_set_double(&field, pbase->dst_ip_lon)); } #endif if (wtc & COUNT_TCPFLAGS) { sprintf(misc_str, "%u", tcp_flags); if (config.tcpflags_encode_as_array) { compose_tcpflags_avro_data(tcp_flags, value); } else { pm_avro_check(avro_value_get_by_name(&value, "tcp_flags", &field, NULL)); pm_avro_check(avro_value_set_string(&field, misc_str)); } } if (wtc_2 & COUNT_FWD_STATUS) { sprintf(misc_str, "%u", pnat->fwd_status); if (config.fwd_status_encode_as_string) { compose_fwd_status_avro_data(pnat->fwd_status, value); } else { pm_avro_check(avro_value_get_by_name(&value, "fwd_status", &field, NULL)); pm_avro_check(avro_value_set_string(&field, misc_str)); } } if (wtc_2 & COUNT_MPLS_LABEL_STACK) { char label_stack[MAX_MPLS_LABEL_STACK]; char *label_stack_ptr = NULL; int label_stack_len = 0; memset(label_stack, 0, MAX_MPLS_LABEL_STACK); label_stack_len = vlen_prims_get(pvlen, COUNT_INT_MPLS_LABEL_STACK, &label_stack_ptr); if (label_stack_ptr) { if (config.mpls_label_stack_encode_as_array) { compose_mpls_label_stack_data((u_int32_t *)label_stack_ptr, label_stack_len, value); } else { mpls_label_stack_to_str(label_stack, sizeof(label_stack), (u_int32_t *)label_stack_ptr, label_stack_len); pm_avro_check(avro_value_get_by_name(&value, "mpls_label_stack", &field, NULL)); pm_avro_check(avro_value_set_string(&field, label_stack)); } } } if (wtc & COUNT_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; pm_avro_check(avro_value_get_by_name(&value, "ip_proto", &field, NULL)); pm_avro_check(avro_value_set_string(&field, ip_proto_print(pbase->proto, proto, PROTO_NUM_STRLEN))); } if (wtc & COUNT_IP_TOS) { pm_avro_check(avro_value_get_by_name(&value, "tos", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->tos)); } if (wtc_2 & COUNT_SAMPLING_RATE) { pm_avro_check(avro_value_get_by_name(&value, "sampling_rate", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->sampling_rate)); } if (wtc_2 & COUNT_SAMPLING_DIRECTION) { pm_avro_check(avro_value_get_by_name(&value, "sampling_direction", &field, NULL)); pm_avro_check(avro_value_set_string(&field, sampling_direction_print(pbase->sampling_direction))); } if (wtc_2 & COUNT_POST_NAT_SRC_HOST) { addr_to_str(src_host, &pnat->post_nat_src_ip); pm_avro_check(avro_value_get_by_name(&value, "post_nat_ip_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_host)); } if (wtc_2 & COUNT_POST_NAT_DST_HOST) { addr_to_str(dst_host, &pnat->post_nat_dst_ip); pm_avro_check(avro_value_get_by_name(&value, "post_nat_ip_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_host)); } if (wtc_2 & COUNT_POST_NAT_SRC_PORT) { pm_avro_check(avro_value_get_by_name(&value, "post_nat_port_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pnat->post_nat_src_port)); } if (wtc_2 & COUNT_POST_NAT_DST_PORT) { pm_avro_check(avro_value_get_by_name(&value, "post_nat_port_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pnat->post_nat_dst_port)); } if (wtc_2 & COUNT_NAT_EVENT) { pm_avro_check(avro_value_get_by_name(&value, "nat_event", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pnat->nat_event)); } if (wtc_2 & COUNT_FW_EVENT) { pm_avro_check(avro_value_get_by_name(&value, "fw_event", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pnat->fw_event)); } if (wtc_2 & COUNT_MPLS_LABEL_TOP) { pm_avro_check(avro_value_get_by_name(&value, "mpls_label_top", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pmpls->mpls_label_top)); } if (wtc_2 & COUNT_MPLS_LABEL_BOTTOM) { pm_avro_check(avro_value_get_by_name(&value, "mpls_label_bottom", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pmpls->mpls_label_bottom)); } if (wtc_2 & COUNT_TUNNEL_SRC_MAC) { etheraddr_string(ptun->tunnel_eth_shost, src_mac); pm_avro_check(avro_value_get_by_name(&value, "tunnel_mac_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_mac)); } if (wtc_2 & COUNT_TUNNEL_DST_MAC) { etheraddr_string(ptun->tunnel_eth_dhost, dst_mac); pm_avro_check(avro_value_get_by_name(&value, "tunnel_mac_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_mac)); } if (wtc_2 & COUNT_TUNNEL_SRC_HOST) { addr_to_str(src_host, &ptun->tunnel_src_ip); pm_avro_check(avro_value_get_by_name(&value, "tunnel_ip_src", &field, NULL)); pm_avro_check(avro_value_set_string(&field, src_host)); } if (wtc_2 & COUNT_TUNNEL_DST_HOST) { addr_to_str(dst_host, &ptun->tunnel_dst_ip); pm_avro_check(avro_value_get_by_name(&value, "tunnel_ip_dst", &field, NULL)); pm_avro_check(avro_value_set_string(&field, dst_host)); } if (wtc_2 & COUNT_TUNNEL_IP_PROTO) { char proto[PROTO_NUM_STRLEN]; pm_avro_check(avro_value_get_by_name(&value, "tunnel_ip_proto", &field, NULL)); pm_avro_check(avro_value_set_string(&field, ip_proto_print(ptun->tunnel_proto, proto, PROTO_NUM_STRLEN))); } if (wtc_2 & COUNT_TUNNEL_IP_TOS) { pm_avro_check(avro_value_get_by_name(&value, "tunnel_tos", &field, NULL)); pm_avro_check(avro_value_set_long(&field, ptun->tunnel_tos)); } if (wtc_2 & COUNT_TUNNEL_SRC_PORT) { pm_avro_check(avro_value_get_by_name(&value, "tunnel_port_src", &field, NULL)); pm_avro_check(avro_value_set_long(&field, ptun->tunnel_src_port)); } if (wtc_2 & COUNT_TUNNEL_DST_PORT) { pm_avro_check(avro_value_get_by_name(&value, "tunnel_port_dst", &field, NULL)); pm_avro_check(avro_value_set_long(&field, ptun->tunnel_dst_port)); } if (wtc & COUNT_TUNNEL_TCPFLAGS) { sprintf(misc_str, "%u", tunnel_tcp_flags); if (config.tcpflags_encode_as_array) { compose_tunnel_tcpflags_avro_data(tunnel_tcp_flags, value); } else { pm_avro_check(avro_value_get_by_name(&value, "tunnel_tcp_flags", &field, NULL)); pm_avro_check(avro_value_set_string(&field, misc_str)); } } if (wtc_2 & COUNT_VXLAN) { pm_avro_check(avro_value_get_by_name(&value, "vxlan", &field, NULL)); pm_avro_check(avro_value_set_long(&field, ptun->tunnel_id)); } if (wtc_2 & COUNT_TIMESTAMP_START) { compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_start, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_start", &field, NULL)); pm_avro_check(avro_value_set_string(&field, tstamp_str)); } if (wtc_2 & COUNT_TIMESTAMP_END) { compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_end, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_end", &field, NULL)); pm_avro_check(avro_value_set_string(&field, tstamp_str)); } if (wtc_2 & COUNT_TIMESTAMP_ARRIVAL) { compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_arrival, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_arrival", &field, NULL)); pm_avro_check(avro_value_set_string(&field, tstamp_str)); } if (config.nfacctd_stitching) { if (stitch) { compose_timestamp(tstamp_str, SRVBUFLEN, &stitch->timestamp_min, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_min", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_string(&branch, tstamp_str)); compose_timestamp(tstamp_str, SRVBUFLEN, &stitch->timestamp_max, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_max", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_string(&branch, tstamp_str)); } else { pm_avro_check(avro_value_get_by_name(&value, "timestamp_min", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); pm_avro_check(avro_value_get_by_name(&value, "timestamp_max", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); } } if (wtc_2 & COUNT_EXPORT_PROTO_SEQNO) { pm_avro_check(avro_value_get_by_name(&value, "export_proto_seqno", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->export_proto_seqno)); } if (wtc_2 & COUNT_EXPORT_PROTO_VERSION) { pm_avro_check(avro_value_get_by_name(&value, "export_proto_version", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->export_proto_version)); } if (wtc_2 & COUNT_EXPORT_PROTO_SYSID) { pm_avro_check(avro_value_get_by_name(&value, "export_proto_sysid", &field, NULL)); pm_avro_check(avro_value_set_long(&field, pbase->export_proto_sysid)); } if (wtc_2 & COUNT_EXPORT_PROTO_TIME) { compose_timestamp(tstamp_str, SRVBUFLEN, &pnat->timestamp_export, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "timestamp_export", &field, NULL)); pm_avro_check(avro_value_set_string(&field, tstamp_str)); } /* all custom primitives printed here */ { if (config.cpptrs.num > 0) pm_avro_check(avro_value_get_by_name(&value, "custom_primitives", &field, NULL)); int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { avro_value_t map_value; avro_value_add(&field, config.cpptrs.primitive[cp_idx].name, &map_value, NULL, NULL); if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) { char cp_str[SRVBUFLEN]; custom_primitive_value_print(cp_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], FALSE); avro_value_set_string(&map_value, cp_str); } else { char *label_ptr = NULL; vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr); if (!label_ptr) label_ptr = empty_string; avro_value_set_string(&map_value, label_ptr); } } } if (config.sql_history) { if (basetime) { struct timeval tv; tv.tv_sec = basetime->tv_sec; tv.tv_usec = 0; compose_timestamp(tstamp_str, SRVBUFLEN, &tv, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "stamp_inserted", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_string(&branch, tstamp_str)); tv.tv_sec = time(NULL); tv.tv_usec = 0; compose_timestamp(tstamp_str, SRVBUFLEN, &tv, FALSE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); pm_avro_check(avro_value_get_by_name(&value, "stamp_updated", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_string(&branch, tstamp_str)); } else { pm_avro_check(avro_value_get_by_name(&value, "stamp_inserted", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); pm_avro_check(avro_value_get_by_name(&value, "stamp_updated", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); } } if (flow_type != NF9_FTYPE_EVENT && flow_type != NF9_FTYPE_OPTION) { pm_avro_check(avro_value_get_by_name(&value, "packets", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_long(&branch, packet_counter)); pm_avro_check(avro_value_get_by_name(&value, "flows", &field, NULL)); if (wtc & COUNT_FLOWS) { pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_long(&branch, flow_counter)); } else { pm_avro_check(avro_value_set_branch(&field, 0, &branch)); } pm_avro_check(avro_value_get_by_name(&value, "bytes", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 1, &branch)); pm_avro_check(avro_value_set_long(&branch, bytes_counter)); } else { pm_avro_check(avro_value_get_by_name(&value, "packets", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); pm_avro_check(avro_value_get_by_name(&value, "flows", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); pm_avro_check(avro_value_get_by_name(&value, "bytes", &field, NULL)); pm_avro_check(avro_value_set_branch(&field, 0, &branch)); } return value; } void add_writer_name_and_pid_avro(avro_value_t value, char *name, pid_t writer_pid) { char wid[SHORTSHORTBUFLEN]; avro_value_t field; snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", name, writer_pid); pm_avro_check(avro_value_get_by_name(&value, "writer_id", &field, NULL)); pm_avro_check(avro_value_set_string(&field, wid)); } void add_writer_name_and_pid_avro_v2(avro_value_t value, struct dynname_tokens *tokens) { char wid[SHORTSHORTBUFLEN]; avro_value_t field; memset(wid, 0, sizeof(wid)); dynname_tokens_compose(wid, sizeof(wid), tokens, NULL); pm_avro_check(avro_value_get_by_name(&value, "writer_id", &field, NULL)); pm_avro_check(avro_value_set_string(&field, wid)); } void write_avro_schema_to_file(char *filename, avro_schema_t schema) { FILE *avro_fp; avro_writer_t p_avro_schema_writer; avro_fp = open_output_file(filename, "w", TRUE); if (avro_fp) { p_avro_schema_writer = avro_writer_file(avro_fp); if (p_avro_schema_writer) { if (avro_schema_to_json(schema, p_avro_schema_writer)) { goto exit_lane; } } else goto exit_lane; close_output_file(avro_fp); } else goto exit_lane; return; exit_lane: Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_schema_to_file(): unable to dump Avro schema: %s\n", config.name, config.type, avro_strerror()); pm_avro_exit_gracefully(1); } void write_avro_schema_to_file_with_suffix(char *filename, char *suffix, char *buf, avro_schema_t schema) { strcpy(buf, filename); strcat(buf, suffix); write_avro_schema_to_file(buf, schema); } char *write_avro_schema_to_memory(avro_schema_t avro_schema) { avro_writer_t p_avro_writer; char *p_avro_buf = NULL; if (!config.avro_buffer_size) config.avro_buffer_size = LARGEBUFLEN; p_avro_buf = malloc(config.avro_buffer_size); if (!p_avro_buf) { Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_schema_to_memory(): malloc() failed. Exiting.\n", config.name, config.type); pm_avro_exit_gracefully(1); } else memset(p_avro_buf, 0, config.avro_buffer_size); p_avro_writer = avro_writer_memory(p_avro_buf, config.avro_buffer_size); if (avro_schema_to_json(avro_schema, p_avro_writer)) { Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_schema_to_memory(): unable to dump Avro schema: %s\n", config.name, config.type, avro_strerror()); free(p_avro_buf); p_avro_buf = NULL; } if (!avro_writer_tell(p_avro_writer)) { Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_schema_to_memory(): unable to tell Avro schema: %s\n", config.name, config.type, avro_strerror()); free(p_avro_buf); p_avro_buf = NULL; } avro_writer_free(p_avro_writer); return p_avro_buf; } char *compose_avro_purge_schema(avro_schema_t avro_schema, char *writer_name) { char *p_avro_buf = NULL, *json_str = NULL; p_avro_buf = write_avro_schema_to_memory(avro_schema); if (p_avro_buf) { char event_type[] = "purge_schema", wid[SHORTSHORTBUFLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", writer_name, 0); json_object_set_new_nocheck(obj, "writer_id", json_string(wid)); json_object_set_new_nocheck(obj, "schema", json_string(p_avro_buf)); free(p_avro_buf); json_str = compose_json_str(obj); } else { Log(LOG_ERR, "ERROR ( %s/%s ): compose_avro_purge_schema(): no p_avro_buf. Exiting.\n", config.name, config.type); pm_avro_exit_gracefully(1); } return json_str; } char *compose_avro_schema_name(char *extra1, char *extra2) { int len_base = 0, len_extra1 = 0, len_extra2 = 0, len_total = 0; char *schema_name = NULL; if (extra1) len_extra1 = strlen(extra1); if (extra2) { if (len_extra1) len_extra1++; len_extra2 = strlen(extra2); } if (len_extra1 || len_extra2) len_base = strlen("pmacct_"); else len_base = strlen("pmacct"); len_total = len_base + len_extra1 + len_extra2 + 1; schema_name = malloc(len_total); if (!schema_name) { Log(LOG_ERR, "ERROR ( %s/%s ): compose_avro_schema_name(): malloc() failed. Exiting.\n", config.name, config.type); pm_avro_exit_gracefully(1); } else memset(schema_name, 0, len_total); strcpy(schema_name, "pmacct"); if (len_extra1 || len_extra2) { strcat(schema_name, "_"); if (len_extra1) { strcat(schema_name, extra1); if (len_extra2) strcat(schema_name, "_"); } if (len_extra2) strcat(schema_name, extra2); } schema_name[len_total] = '\0'; /* pedantic */ return schema_name; } #ifdef WITH_SERDES void p_avro_serdes_logger(serdes_t *sd_desc, int level, const char *fac, const char *buf, void *opaque) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): SERDES-%i-%s: %s\n", config.name, config.type, level, fac, buf); } serdes_schema_t *compose_avro_schema_registry_name_2(char *topic, int is_topic_dyn, avro_schema_t avro_schema, char *type, char *name, char *schema_registry) { serdes_schema_t *loc_schema = NULL; char *loc_schema_name = NULL; int len = 0; if (!topic || !type || !name) return NULL; len = (strlen(topic) + strlen(type) + strlen(name) + 3 /* two seps + term */); loc_schema_name = malloc(len); memset(loc_schema_name, 0, len); strcpy(loc_schema_name, topic); strcat(loc_schema_name, "-"); strcat(loc_schema_name, type); strcat(loc_schema_name, "_"); strcat(loc_schema_name, name); loc_schema = compose_avro_schema_registry_name(loc_schema_name, FALSE, avro_schema, NULL, NULL, schema_registry); free(loc_schema_name); return loc_schema; } serdes_schema_t *compose_avro_schema_registry_name(char *topic, int is_topic_dyn, avro_schema_t avro_schema, char *type, char *name, char *schema_registry) { serdes_conf_t *sd_conf; serdes_t *sd_desc; serdes_schema_t *loc_schema = NULL; char sd_errstr[LONGSRVBUFLEN]; char *p_avro_schema_str = write_avro_schema_to_memory(avro_schema); char *p_avro_schema_name; if (!is_topic_dyn) { p_avro_schema_name = malloc(strlen(topic) + 1); strcpy(p_avro_schema_name, topic); } else { p_avro_schema_name = compose_avro_schema_name(type, name); } sd_conf = serdes_conf_new(NULL, 0, "schema.registry.url", schema_registry, NULL); if (!sd_conf) { Log(LOG_ERR, "ERROR ( %s/%s ): serdes_conf_new() failed: %s. Exiting.\n", config.name, config.type, sd_errstr); pm_avro_exit_gracefully(1); } serdes_conf_set_log_cb(sd_conf, p_avro_serdes_logger); sd_desc = serdes_new(sd_conf, sd_errstr, sizeof(sd_errstr)); if (!sd_desc) { Log(LOG_ERR, "ERROR ( %s/%s ): serdes_new() failed: %s. Exiting.\n", config.name, config.type, sd_errstr); pm_avro_exit_gracefully(1); } loc_schema = serdes_schema_add(sd_desc, p_avro_schema_name, -1, p_avro_schema_str, -1, sd_errstr, sizeof(sd_errstr)); if (!loc_schema) { Log(LOG_WARNING, "WARN ( %s/%s ): serdes_schema_add() failed: %s\n", config.name, config.type, sd_errstr); } else { if (!config.debug) { Log(LOG_INFO, "INFO ( %s/%s ): serdes_schema_add(): name=%s id=%d\n", config.name, config.type, serdes_schema_name(loc_schema), serdes_schema_id(loc_schema)); } else { Log(LOG_DEBUG, "DEBUG ( %s/%s ): serdes_schema_add(): name=%s id=%d definition=%s\n", config.name, config.type, serdes_schema_name(loc_schema), serdes_schema_id(loc_schema), serdes_schema_definition(loc_schema)); } } return loc_schema; } #endif void write_avro_json_record_to_file(FILE *fp, avro_value_t value) { char *json_str; if (avro_value_to_json(&value, TRUE, &json_str)) { Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_json_record_to_file() unable to value to JSON: %s\n", config.name, config.type, avro_strerror()); pm_avro_exit_gracefully(1); } fprintf(fp, "%s\n", json_str); free(json_str); } char *write_avro_json_record_to_buf(avro_value_t value) { char *json_str; if (avro_value_to_json(&value, TRUE, &json_str)) { Log(LOG_ERR, "ERROR ( %s/%s ): write_avro_json_record_to_buf() unable to value to JSON: %s\n", config.name, config.type, avro_strerror()); pm_avro_exit_gracefully(1); } return json_str; } #endif void pm_avro_exit_gracefully(int status) { if (!config.debug) { exit_gracefully(status); } else { /* gather additional info on exit */ assert(1 == 0); } } /* Compose optional label schema, ie. in BGP, BMP */ void compose_label_avro_schema_opt(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); sc_type_union = avro_schema_union(); avro_schema_union_append(sc_type_union, avro_schema_null()); avro_schema_union_append(sc_type_union, avro_schema_map(sc_type_string)); avro_schema_record_field_append(sc_type_record, "label", sc_type_union); /* free-up memory - avro union*/ avro_schema_decref(sc_type_union); avro_schema_decref(sc_type_string); } /* Compose mandatory / non-optional label schema, ie. in IPFIX */ void compose_label_avro_schema_nonopt(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); sc_type_map = avro_schema_map(sc_type_string); avro_schema_record_field_append(sc_type_record, "label", sc_type_map); /* free-up memory - avro map only*/ avro_schema_decref(sc_type_map); avro_schema_decref(sc_type_string); } void compose_tcpflags_avro_schema(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); sc_type_array = avro_schema_array(sc_type_string); avro_schema_record_field_append(sc_type_record, "tcp_flags", sc_type_array); /* free-up memory */ avro_schema_decref(sc_type_array); avro_schema_decref(sc_type_string); } void compose_tunnel_tcpflags_avro_schema(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); sc_type_array = avro_schema_array(sc_type_string); avro_schema_record_field_append(sc_type_record, "tunnel_tcp_flags", sc_type_array); /* free-up memory */ avro_schema_decref(sc_type_array); avro_schema_decref(sc_type_string); } void compose_fwd_status_avro_schema(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); avro_schema_record_field_append(sc_type_record, "fwd_status", sc_type_string); /* free-up memory */ avro_schema_decref(sc_type_string); } void compose_mpls_label_stack_schema(avro_schema_t sc_type_record) { sc_type_string = avro_schema_string(); sc_type_array = avro_schema_array(sc_type_string); avro_schema_record_field_append(sc_type_record, "mpls_label_stack", sc_type_array); /* free-up memory */ avro_schema_decref(sc_type_array); avro_schema_decref(sc_type_string); } /* Insert mandatory / non-optional label data, ie. in IPFIX */ int compose_label_avro_data_nonopt(char *str_ptr, avro_value_t v_type_record) { /* labels normalization */ cdada_str_t *lbls_cdada = cdada_str_create(str_ptr); cdada_str_replace_all(lbls_cdada, PRETAG_LABEL_KV_SEP, DEFAULT_SEP); const char *lbls_norm = cdada_str(lbls_cdada); /* linked-list creation */ ptm_label lbl; cdada_list_t *ll = ptm_labels_to_linked_list(lbls_norm); size_t ll_size = cdada_list_size(ll); avro_value_t v_type_string, v_type_map; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&lbl, 0, sizeof(lbl)); cdada_list_get(ll, idx_0, &lbl); if (avro_value_get_by_name(&v_type_record, "label", &v_type_map, NULL) == 0) { if (avro_value_add(&v_type_map, lbl.key, &v_type_string, NULL, NULL) == 0) { avro_value_set_string(&v_type_string, lbl.value); } } } /* free-up memory - to be review: the scope of the decref should be reviewd */ cdada_str_destroy(lbls_cdada); cdada_list_destroy(ll); return 0; } /* Insert optional label data, ie. in BGP, BMP */ int compose_label_avro_data_opt(char *str_ptr, avro_value_t v_type_record) { /* labels normalization */ cdada_str_t *lbls_cdada = cdada_str_create(str_ptr); cdada_str_replace_all(lbls_cdada, PRETAG_LABEL_KV_SEP, DEFAULT_SEP); const char *lbls_norm = cdada_str(lbls_cdada); /* linked-list creation */ ptm_label lbl; cdada_list_t *ll = ptm_labels_to_linked_list(lbls_norm); size_t ll_size = cdada_list_size(ll); avro_value_t v_type_union, v_type_branch, v_type_string; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&lbl, 0, sizeof(lbl)); cdada_list_get(ll, idx_0, &lbl); /* handling label with value */ if (lbl.value) { if (avro_value_get_by_name(&v_type_record, "label", &v_type_union, NULL) == 0) { avro_value_set_branch(&v_type_union, TRUE, &v_type_branch); if (avro_value_add(&v_type_branch, lbl.key, &v_type_string, NULL, NULL) == 0) { avro_value_set_string(&v_type_string, lbl.value); } } } /* handling label without value */ else { if (avro_value_get_by_name(&v_type_record, "label", &v_type_union, NULL) == 0) { avro_value_set_branch(&v_type_union, FALSE, &v_type_branch); } } } /* free-up memory */ cdada_str_destroy(lbls_cdada); cdada_list_destroy(ll); return 0; } int compose_tcpflags_avro_data(size_t tcpflags_decimal, avro_value_t v_type_record) { tcpflag tcpstate; /* linked-list creation */ cdada_list_t *ll = tcpflags_to_linked_list(tcpflags_decimal); size_t ll_size = cdada_list_size(ll); avro_value_t v_type_array, v_type_string; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&tcpstate, 0, sizeof(tcpstate)); cdada_list_get(ll, idx_0, &tcpstate); if (avro_value_get_by_name(&v_type_record, "tcp_flags", &v_type_array, NULL) == 0) { /* Serialize only flags set to 1 */ if (strcmp(tcpstate.flag, "NULL") != 0) { if (avro_value_append(&v_type_array, &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, tcpstate.flag); } } } } /* free-up memory */ cdada_list_destroy(ll); return 0; } int compose_tunnel_tcpflags_avro_data(size_t tcpflags_decimal, avro_value_t v_type_record) { tcpflag tcpstate; /* linked-list creation */ cdada_list_t *ll = tcpflags_to_linked_list(tcpflags_decimal); size_t ll_size = cdada_list_size(ll); avro_value_t v_type_array, v_type_string; size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&tcpstate, 0, sizeof(tcpstate)); cdada_list_get(ll, idx_0, &tcpstate); if (avro_value_get_by_name(&v_type_record, "tunnel_tcp_flags", &v_type_array, NULL) == 0) { /* Serialize only flags set to 1 */ if (strcmp(tcpstate.flag, "NULL") != 0) { if (avro_value_append(&v_type_array, &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, tcpstate.flag); } } } } /* free-up memory */ cdada_list_destroy(ll); return 0; } int compose_fwd_status_avro_data(size_t fwdstatus_decimal, avro_value_t v_type_record) { fwd_status fwdstate; /* linked-list creation */ cdada_list_t *ll = fwd_status_to_linked_list(); size_t ll_size = cdada_list_size(ll); avro_value_t v_type_string; /* default fwdstatus */ if ((fwdstatus_decimal >= 0) && (fwdstatus_decimal <= 63)) { if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, "UNKNOWN Unclassified"); } } else if ((fwdstatus_decimal >= 64) && (fwdstatus_decimal <= 127)) { if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, "FORWARDED Unclassified"); } } else if ((fwdstatus_decimal >= 128) && (fwdstatus_decimal <= 191)) { if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, "DROPPED Unclassified"); } } else if ((fwdstatus_decimal >= 192) && (fwdstatus_decimal <= 255)) { if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, "CONSUMED Unclassified"); } } else { if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, "RFC-7270 Misinterpreted"); } } size_t idx_0; for (idx_0 = 0; idx_0 < ll_size; idx_0++) { memset(&fwdstate, 0, sizeof(fwdstate)); cdada_list_get(ll, idx_0, &fwdstate); if (avro_value_get_by_name(&v_type_record, "fwd_status", &v_type_string, NULL) == 0) { if (fwdstate.decimal == fwdstatus_decimal) { avro_value_set_string(&v_type_string, fwdstate.description); } } } /* free-up memory */ cdada_list_destroy(ll); return 0; } int compose_mpls_label_stack_data(u_int32_t *label_stack, int ls_len, avro_value_t v_type_record) { const int MAX_IDX_LEN = 4; const int MAX_MPLS_LABEL_IDX_LEN = (MAX_IDX_LEN + MAX_MPLS_LABEL_LEN); int max_mpls_label_idx_len_dec = 0; char label_buf[MAX_MPLS_LABEL_LEN]; char label_idx_buf[MAX_MPLS_LABEL_IDX_LEN]; char idx_buf[MAX_IDX_LEN]; u_int8_t ls_depth = 0; if (!(ls_len % 4)) { ls_depth = (ls_len / 4); } else { return ERR; } avro_value_t v_type_array, v_type_string; size_t idx_0; for (idx_0 = 0; idx_0 < ls_depth; idx_0++) { memset(&label_buf, 0, sizeof(label_buf)); snprintf(label_buf, MAX_MPLS_LABEL_LEN, "%u", *(label_stack + idx_0)); if (avro_value_get_by_name(&v_type_record, "mpls_label_stack", &v_type_array, NULL) == 0) { memset(&idx_buf, 0, sizeof(idx_buf)); memset(&label_idx_buf, 0, sizeof(label_idx_buf)); snprintf(idx_buf, MAX_IDX_LEN, "%zu", idx_0); strncat(label_idx_buf, idx_buf, (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); strncat(label_idx_buf, "-", (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); strncat(label_idx_buf, label_buf, (MAX_MPLS_LABEL_IDX_LEN - max_mpls_label_idx_len_dec)); max_mpls_label_idx_len_dec = (strlen(idx_buf) + strlen("-") + strlen(label_buf) + 3); if (avro_value_append(&v_type_array, &v_type_string, NULL) == 0) { avro_value_set_string(&v_type_string, label_idx_buf); } } } return FALSE; } pmacct-1.7.8/src/cfg.h0000644000175000017500000004673114354105275013524 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CFG_H #define CFG_H #include "cfg_handlers.h" #include "bgp/bgp_prefix.h" /* defines */ #define CFG_LINE_LEN(x) (SRVBUFLEN-strlen(x)) #define MAX_CUSTOM_PRIMITIVES 64 #define MAX_CUSTOM_PRIMITIVE_NAMELEN 64 #define MAX_CUSTOM_PRIMITIVE_PD_PTRS 8 /* structures */ struct _dictionary_line { char key[SRVBUFLEN]; int (*func)(char *, char *, char *); }; struct packet_data_ptr { s_uint8_t ptr_idx; u_int16_t off; s_uint16_t proto; }; struct custom_primitive_entry { /* compiled from map */ char name[MAX_CUSTOM_PRIMITIVE_NAMELEN]; struct packet_data_ptr pd_ptr[MAX_CUSTOM_PRIMITIVE_PD_PTRS]; u_int32_t pen; u_int16_t field_type; u_int16_t len; u_int16_t alloc_len; u_int8_t semantics; u_int8_t repeat_id; /* generated internally */ pm_cfgreg_t type; }; struct custom_primitives { struct custom_primitive_entry primitive[MAX_CUSTOM_PRIMITIVES]; int num; }; struct custom_primitive_ptrs { char *name; u_int16_t off; struct custom_primitive_entry *ptr; }; struct custom_primitives_ptrs { struct custom_primitive_ptrs primitive[MAX_CUSTOM_PRIMITIVES]; int num; int len; }; struct configuration { pm_cfgreg_t what_to_count; /* first registry */ pm_cfgreg_t what_to_count_2; /* second registry */ pm_cfgreg_t nfprobe_what_to_count; pm_cfgreg_t nfprobe_what_to_count_2; char *aggregate_primitives; int aggregate_unknown_etype; struct custom_primitives_ptrs cpptrs; char *progname; char *name; char *type; int type_id; int is_forked; int propagate_signals; int pmacctd_nonroot; char *proc_name; int proc_priority; char *cluster_name; int cluster_id; char *redis_host; int redis_db; int sock; int bgp_sock; int acct_type; int data_type; int pipe_homegrown; u_int64_t pipe_size; u_int64_t buffer_size; int buffer_immediate; int pipe_zmq; int pipe_zmq_retry; int pipe_zmq_profile; int pipe_zmq_hwm; int plugin_exit_any; int files_umask; int files_uid; int files_gid; int handle_fragments; int handle_flows; int frag_bufsz; int flow_bufsz; int flow_hashsz; int conntrack_bufsz; int flow_lifetime; int flow_tcp_lifetime; int num_protos; int num_hosts; char *dtls_path; #ifdef WITH_GNUTLS pm_dtls_glob_t dtls_globs; #endif char *imt_plugin_path; char *imt_plugin_passwd; char *sql_db; char *sql_table; char *sql_table_schema; int sql_table_version; char *sql_table_type; char *sql_user; char *sql_passwd; char *sql_conn_ca_file; char *sql_host; int sql_port; char *sql_data; char *sql_backup_host; int sql_optimize_clauses; int sql_refresh_time; int sql_history; int sql_history_offset; int sql_history_howmany; /* internal */ int sql_startup_delay; int sql_cache_entries; int sql_dont_try_update; char *sql_history_roundoff; int sql_trigger_time; int sql_trigger_time_howmany; /* internal */ char *sql_trigger_exec; int sql_max_queries; char *sql_preprocess; int sql_preprocess_type; int sql_multi_values; char *sql_locking_style; int sql_use_copy; char *sql_delimiter; int timestamps_rfc3339; int timestamps_utc; int timestamps_secs; int timestamps_since_epoch; int mongo_insert_batch; int message_broker_output; int avro_buffer_size; char *avro_schema_file; char *amqp_exchange_type; int amqp_persistent_msg; u_int32_t amqp_frame_max; u_int32_t amqp_heartbeat_interval; char *amqp_vhost; int amqp_routing_key_rr; char *amqp_avro_schema_routing_key; int amqp_avro_schema_refresh_time; int kafka_broker_port; int kafka_partition; int kafka_partition_dynamic; char *kafka_partition_key; int kafka_partition_keylen; char *kafka_avro_schema_topic; int kafka_avro_schema_refresh_time; char *kafka_avro_schema_registry; char *kafka_config_file; char *kafka_writer_id; int print_cache_entries; int print_markers; int print_output; int print_output_file_append; int print_write_empty_file; char *print_output_lock_file; char *print_output_separator; char *print_output_file; char *print_output_custom_lib; char *print_output_custom_cfg_file; char *print_latest_file; int nfacctd_port; char *nfacctd_ip; char *nfacctd_interface; int nfacctd_ipv6_only; char *nfacctd_rp_ebpf_prog; char *nfacctd_kafka_broker_host; int nfacctd_kafka_broker_port; char *nfacctd_kafka_topic; char *nfacctd_kafka_config_file; char *nfacctd_zmq_address; int nfacctd_dtls_port; #ifdef WITH_GNUTLS int nfacctd_dtls_sock; #endif char *writer_id_string; char *nfacctd_allow_file; int nfacctd_time; int nfacctd_time_new; int nfacctd_pro_rating; char *nfacctd_templates_file; char *nfacctd_templates_receiver; int nfacctd_templates_port; int nfacctd_templates_sock; int nfacctd_account_options; int nfacctd_stitching; u_int32_t nfacctd_as; u_int32_t nfacctd_net; int nfacctd_pipe_size; int sfacctd_renormalize; int sfacctd_counter_output; char *sfacctd_counter_file; int sfacctd_counter_max_nodes; char *sfacctd_counter_amqp_host; char *sfacctd_counter_amqp_vhost; char *sfacctd_counter_amqp_user; char *sfacctd_counter_amqp_passwd; char *sfacctd_counter_amqp_exchange; char *sfacctd_counter_amqp_exchange_type; char *sfacctd_counter_amqp_routing_key; int sfacctd_counter_amqp_persistent_msg; u_int32_t sfacctd_counter_amqp_frame_max; u_int32_t sfacctd_counter_amqp_heartbeat_interval; int sfacctd_counter_amqp_retry; char *sfacctd_counter_kafka_broker_host; char *sfacctd_counter_kafka_topic; int sfacctd_counter_kafka_partition; char *sfacctd_counter_kafka_partition_key; int sfacctd_counter_kafka_partition_keylen; int sfacctd_counter_kafka_broker_port; int sfacctd_counter_kafka_retry; char *sfacctd_counter_kafka_config_file; int nfacctd_disable_checks; int nfacctd_disable_opt_scope_check; int telemetry_daemon; int telemetry_sock; int telemetry_port_tcp; int telemetry_port_udp; char *telemetry_ip; char *telemetry_interface; int telemetry_udp_notif_port; char *telemetry_udp_notif_ip; char *telemetry_udp_notif_interface; int telemetry_udp_notif_ipv6_only; int telemetry_udp_notif_nmsgs; char *telemetry_udp_notif_rp_ebpf_prog; int telemetry_ipv6_only; char *telemetry_zmq_address; char *telemetry_kafka_broker_host; int telemetry_kafka_broker_port; char *telemetry_kafka_topic; char *telemetry_kafka_config_file; char *telemetry_decoder; int telemetry_decoder_id; int telemetry_max_peers; int telemetry_peer_timeout; char *telemetry_tag_map; char *telemetry_allow_file; int telemetry_pipe_size; int telemetry_ipprec; char *telemetry_msglog_file; int telemetry_msglog_output; char *telemetry_msglog_amqp_host; char *telemetry_msglog_amqp_vhost; char *telemetry_msglog_amqp_user; char *telemetry_msglog_amqp_passwd; char *telemetry_msglog_amqp_exchange; char *telemetry_msglog_amqp_exchange_type; char *telemetry_msglog_amqp_routing_key; int telemetry_msglog_amqp_routing_key_rr; int telemetry_msglog_amqp_persistent_msg; u_int32_t telemetry_msglog_amqp_frame_max; u_int32_t telemetry_msglog_amqp_heartbeat_interval; int telemetry_msglog_amqp_retry; char *telemetry_dump_file; char *telemetry_dump_latest_file; int telemetry_dump_output; int telemetry_dump_refresh_time; int telemetry_dump_time_slots; char *telemetry_dump_amqp_host; char *telemetry_dump_amqp_vhost; char *telemetry_dump_amqp_user; char *telemetry_dump_amqp_passwd; char *telemetry_dump_amqp_exchange; char *telemetry_dump_amqp_exchange_type; char *telemetry_dump_amqp_routing_key; int telemetry_dump_amqp_routing_key_rr; int telemetry_dump_amqp_persistent_msg; u_int32_t telemetry_dump_amqp_frame_max; u_int32_t telemetry_dump_amqp_heartbeat_interval; int telemetry_dump_workers; char *telemetry_msglog_kafka_broker_host; int telemetry_msglog_kafka_broker_port; char *telemetry_msglog_kafka_topic; int telemetry_msglog_kafka_topic_rr; int telemetry_msglog_kafka_partition; char *telemetry_msglog_kafka_partition_key; int telemetry_msglog_kafka_partition_keylen; int telemetry_msglog_kafka_retry; char *telemetry_msglog_kafka_config_file; char *telemetry_dump_kafka_broker_host; int telemetry_dump_kafka_broker_port; char *telemetry_dump_kafka_topic; int telemetry_dump_kafka_topic_rr; int telemetry_dump_kafka_partition; char *telemetry_dump_kafka_partition_key; int telemetry_dump_kafka_partition_keylen; char *telemetry_dump_kafka_config_file; int bgp_daemon; int bgp_daemon_msglog_output; char *bgp_daemon_msglog_file; char *bgp_daemon_msglog_avro_schema_file; char *bgp_daemon_msglog_amqp_host; char *bgp_daemon_msglog_amqp_vhost; char *bgp_daemon_msglog_amqp_user; char *bgp_daemon_msglog_amqp_passwd; char *bgp_daemon_msglog_amqp_exchange; char *bgp_daemon_msglog_amqp_exchange_type; char *bgp_daemon_msglog_amqp_routing_key; int bgp_daemon_msglog_amqp_routing_key_rr; int bgp_daemon_msglog_amqp_persistent_msg; u_int32_t bgp_daemon_msglog_amqp_frame_max; u_int32_t bgp_daemon_msglog_amqp_heartbeat_interval; int bgp_daemon_msglog_amqp_retry; char *bgp_daemon_msglog_kafka_broker_host; char *bgp_daemon_msglog_kafka_topic; int bgp_daemon_msglog_kafka_topic_rr; int bgp_daemon_msglog_kafka_partition; char *bgp_daemon_msglog_kafka_partition_key; int bgp_daemon_msglog_kafka_partition_keylen; int bgp_daemon_msglog_kafka_broker_port; int bgp_daemon_msglog_kafka_retry; char *bgp_daemon_msglog_kafka_config_file; char *bgp_daemon_msglog_kafka_avro_schema_registry; char *bgp_daemon_id; char *bgp_daemon_ip; char *bgp_daemon_interface; int bgp_daemon_ipv6_only; as_t bgp_daemon_as; int bgp_daemon_port; char *bgp_daemon_rp_ebpf_prog; char *bgp_daemon_tag_map; int bgp_daemon_pipe_size; int bgp_daemon_ipprec; char *bgp_daemon_allow_file; int bgp_daemon_max_peers; int bgp_daemon_add_path_ignore; int bgp_daemon_aspath_radius; char *bgp_daemon_stdcomm_pattern; char *bgp_daemon_extcomm_pattern; char *bgp_daemon_lrgcomm_pattern; char *bgp_daemon_stdcomm_pattern_to_asn; char *bgp_daemon_lrgcomm_pattern_to_asn; char *bgp_blackhole_stdcomm_list; int bgp_daemon_peer_as_src_type; int bgp_daemon_src_std_comm_type; int bgp_daemon_src_ext_comm_type; int bgp_daemon_src_lrg_comm_type; int bgp_daemon_src_as_path_type; int bgp_daemon_src_local_pref_type; int bgp_daemon_src_med_type; int bgp_daemon_src_roa_type; int bgp_daemon_peer_as_skip_subas; int bgp_daemon_batch; int bgp_daemon_batch_interval; char *bgp_daemon_peer_as_src_map; char *bgp_daemon_src_local_pref_map; char *bgp_daemon_src_med_map; char *bgp_daemon_to_xflow_agent_map; char *nfacctd_flow_to_rd_map; int bgp_daemon_follow_default; struct prefix bgp_daemon_follow_nexthop[FOLLOW_BGP_NH_ENTRIES]; int bgp_daemon_follow_nexthop_external; char *bgp_daemon_neighbors_file; char *bgp_daemon_md5_file; int bgp_table_peer_buckets; int bgp_table_per_peer_buckets; int bgp_table_attr_hash_buckets; int bgp_table_per_peer_hash; int bgp_table_dump_output; char *bgp_table_dump_file; char *bgp_table_dump_latest_file; char *bgp_table_dump_avro_schema_file; int bgp_table_dump_refresh_time; int bgp_table_dump_time_slots; char *bgp_table_dump_amqp_host; char *bgp_table_dump_amqp_vhost; char *bgp_table_dump_amqp_user; char *bgp_table_dump_amqp_passwd; char *bgp_table_dump_amqp_exchange; char *bgp_table_dump_amqp_exchange_type; char *bgp_table_dump_amqp_routing_key; int bgp_table_dump_amqp_routing_key_rr; int bgp_table_dump_amqp_persistent_msg; u_int32_t bgp_table_dump_amqp_frame_max; u_int32_t bgp_table_dump_amqp_heartbeat_interval; char *bgp_table_dump_kafka_broker_host; char *bgp_table_dump_kafka_topic; int bgp_table_dump_kafka_topic_rr; int bgp_table_dump_kafka_partition; char *bgp_table_dump_kafka_partition_key; int bgp_table_dump_kafka_partition_keylen; int bgp_table_dump_kafka_broker_port; char *bgp_table_dump_kafka_config_file; char *bgp_table_dump_kafka_avro_schema_registry; int bgp_table_dump_workers; int bgp_lg; char *bgp_lg_ip; int bgp_lg_port; int bgp_lg_threads; char *bgp_lg_user; char *bgp_lg_passwd; char *bgp_xconnect_map; int bgp_disable_router_id_check; int bmp_sock; int bmp_daemon; char *bmp_daemon_ip; char *bmp_daemon_interface; int bmp_daemon_ipv6_only; int bmp_daemon_port; char *bmp_daemon_rp_ebpf_prog; char *bmp_daemon_tag_map; int bmp_daemon_pipe_size; int bmp_daemon_max_peers; char *bmp_daemon_allow_file; int bmp_daemon_ipprec; int bmp_daemon_batch; int bmp_daemon_batch_interval; int bmp_daemon_msglog_output; char *bmp_daemon_msglog_file; char *bmp_daemon_msglog_avro_schema_file; char *bmp_daemon_msglog_amqp_host; char *bmp_daemon_msglog_amqp_vhost; char *bmp_daemon_msglog_amqp_user; char *bmp_daemon_msglog_amqp_passwd; char *bmp_daemon_msglog_amqp_exchange; char *bmp_daemon_msglog_amqp_exchange_type; char *bmp_daemon_msglog_amqp_routing_key; int bmp_daemon_msglog_amqp_routing_key_rr; int bmp_daemon_msglog_amqp_persistent_msg; u_int32_t bmp_daemon_msglog_amqp_frame_max; u_int32_t bmp_daemon_msglog_amqp_heartbeat_interval; int bmp_daemon_msglog_amqp_retry; char *bmp_daemon_msglog_kafka_broker_host; char *bmp_daemon_msglog_kafka_topic; int bmp_daemon_msglog_kafka_topic_rr; int bmp_daemon_msglog_kafka_partition; char *bmp_daemon_msglog_kafka_partition_key; int bmp_daemon_msglog_kafka_partition_keylen; int bmp_daemon_msglog_kafka_broker_port; int bmp_daemon_msglog_kafka_retry; char *bmp_daemon_msglog_kafka_config_file; char *bmp_daemon_msglog_kafka_avro_schema_registry; int bmp_table_peer_buckets; int bmp_table_per_peer_buckets; int bmp_table_attr_hash_buckets; int bmp_table_per_peer_hash; int bmp_dump_output; int bmp_dump_workers; char *bmp_dump_file; char *bmp_dump_latest_file; char *bmp_dump_avro_schema_file; int bmp_dump_refresh_time; int bmp_dump_time_slots; char *bmp_dump_amqp_host; char *bmp_dump_amqp_vhost; char *bmp_dump_amqp_user; char *bmp_dump_amqp_passwd; char *bmp_dump_amqp_exchange; char *bmp_dump_amqp_exchange_type; char *bmp_dump_amqp_routing_key; int bmp_dump_amqp_routing_key_rr; int bmp_dump_amqp_persistent_msg; u_int32_t bmp_dump_amqp_frame_max; u_int32_t bmp_dump_amqp_heartbeat_interval; char *bmp_dump_kafka_broker_host; char *bmp_dump_kafka_topic; int bmp_dump_kafka_topic_rr; int bmp_dump_kafka_partition; char *bmp_dump_kafka_partition_key; int bmp_dump_kafka_partition_keylen; int bmp_dump_kafka_broker_port; char *bmp_dump_kafka_config_file; char *bmp_dump_kafka_avro_schema_registry; int nfacctd_isis; char *nfacctd_isis_ip; char *nfacctd_isis_net; char *nfacctd_isis_iface; int nfacctd_isis_mtu; int nfacctd_isis_msglog; char *igp_daemon_map; char *igp_daemon_map_msglog; char *geoip_ipv4_file; char *geoip_ipv6_file; #if defined WITH_GEOIP GeoIP *geoip_ipv4; GeoIP *geoip_ipv6; #endif char *geoipv2_file; #if defined WITH_GEOIPV2 MMDB_s geoipv2_db; #endif int promisc; /* pcap_open_live() promisc parameter */ char *clbuf; /* pcap filter */ int pcap_protocol; char *pcap_savefile; int pcap_direction; int pcap_ifindex; char *pcap_interfaces_map; char *pcap_if; int pcap_if_wait; int pcap_sf_wait; int pcap_sf_delay; int pcap_sf_replay; int num_memory_pools; int memory_pool_size; int buckets; int daemon; int active_plugins; char *logfile; FILE *logfile_fd; char *pidfile; int networks_mask; char *networks_file; int networks_file_filter; int networks_file_no_lpm; int networks_no_mask_if_zero; int networks_cache_entries; char *ports_file; char *protos_file; char *tos_file; char *a_filter; int bpfp_a_num; struct bpf_program *bpfp_a_table[AGG_FILTER_ENTRIES]; struct pretag_filter ptf; struct pretag_filter pt2f; struct pretag_label_filter ptlf; int pretag_label_encode_as_map; int tcpflags_encode_as_array; int mpls_label_stack_encode_as_array; int fwd_status_encode_as_string; int tos_encode_as_dscp; int maps_refresh; int maps_index; int maps_entries; int maps_row_len; char *pre_tag_map; struct id_table ptm; int ptm_alloc; int ptm_global; int ptm_complex; pm_id_t post_tag; pm_id_t post_tag2; int ext_sampling_rate; int sampling_rate; char *sampling_map; char *syslog; int debug; int debug_internal_msg; int snaplen; int classifier_table_num; int classifier_ndpi; u_int32_t ndpi_num_roots; u_int32_t ndpi_max_flows; int ndpi_proto_guess; u_int32_t ndpi_idle_scan_period; u_int32_t ndpi_idle_max_time; u_int32_t ndpi_idle_scan_budget; int ndpi_giveup_proto_tcp; int ndpi_giveup_proto_udp; int ndpi_giveup_proto_other; char *nfprobe_timeouts; int nfprobe_id; int nfprobe_hoplimit; int nfprobe_maxflows; char *nfprobe_receiver; int nfprobe_dtls; char *nfprobe_dtls_verify_cert; int nfprobe_version; char *nfprobe_engine; int nfprobe_peer_as; char *nfprobe_source_ip; struct host_addr nfprobe_source_ha; int nfprobe_ipprec; int nfprobe_direction; u_int32_t nfprobe_ifindex; int nfprobe_ifindex_override; int nfprobe_ifindex_type; int nfprobe_dont_cache; int nfprobe_tstamp_usec; char *sfprobe_receiver; char *sfprobe_agentip; int sfprobe_agentsubid; u_int64_t sfprobe_ifspeed; int tee_transparent; int tee_max_receivers; int tee_max_receiver_pools; char *tee_receivers; int tee_pipe_size; char *tee_kafka_config_file; int uacctd_group; int uacctd_nl_size; int uacctd_threshold; char *tunnel0; int use_ip_next_hop; int pcap_arista_trailer_offset; int pcap_arista_trailer_flag_value; int dump_max_writers; int tmp_asa_bi_flow; int tmp_vlan_legacy; int tmp_bgp_lookup_compare_ports; int tmp_bgp_daemon_route_refresh; int tmp_bgp_daemon_origin_type_int; int tmp_telemetry_udp_notif_legacy; int tmp_telemetry_decode_cisco_v1_json_string; size_t thread_stack; char *rpki_roas_file; char *rpki_rtr_cache; int rpki_rtr_cache_version; int rpki_rtr_cache_pipe_size; int rpki_rtr_cache_ipprec; int bmp_daemon_parse_proxy_header; }; /* prototypes */ extern void evaluate_configuration(char *, int); extern int parse_configuration_file(char *); extern int parse_plugin_names(char *, int, int); extern void parse_core_process_name(char *, int, int); extern void compose_default_plugin_name(char *, int, char *); extern int create_plugin(char *, char *, char *); extern int delete_plugin_by_id(int); extern struct plugins_list_entry *search_plugin_by_pipe(int); extern struct plugins_list_entry *search_plugin_by_pid(pid_t); extern void sanitize_cfg(int, char *); extern void set_default_values(); /* global vars */ extern char *cfg[LARGEBUFLEN], *cfg_cmdline[SRVBUFLEN]; extern struct custom_primitives custom_primitives_registry; extern pm_cfgreg_t custom_primitives_type; extern int rows; extern char default_proc_name[]; #endif //CFG_H pmacct-1.7.8/src/pmbmpd.h0000644000175000017500000000172114354105275014232 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PMBMPD_H #define PMBMPD_H /* prototypes */ extern void usage_daemon(char *); extern void compute_once(); #endif //PMBMPD_H pmacct-1.7.8/src/isis/0000755000175000017500000000000014354105416013545 5ustar paolopaolopmacct-1.7.8/src/isis/isis-data.h0000644000175000017500000000223414354105275015600 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ const struct _map_dictionary_line igp_daemon_map_dictionary[] = { {"node", igp_daemon_map_node_handler}, {"area_id", igp_daemon_map_area_id_handler}, {"adj_metric", igp_daemon_map_adj_metric_handler}, {"reach_metric", igp_daemon_map_reach_metric_handler}, {"reach6_metric", igp_daemon_map_reach6_metric_handler}, {"", NULL} }; pmacct-1.7.8/src/isis/table.c0000644000175000017500000002252214354105275015006 0ustar paolopaolo/* * Routing Table functions. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "prefix.h" #include "table.h" #include "sockunion.h" void route_node_delete (struct route_node *); void route_table_free (struct route_table *); struct route_table * route_table_init (void) { struct route_table *rt; rt = calloc(1, sizeof(struct route_table)); return rt; } void route_table_finish (struct route_table *rt) { route_table_free (rt); } /* Allocate new route node. */ static struct route_node * route_node_new (void) { struct route_node *node; node = calloc(1, sizeof (struct route_node)); return node; } /* Allocate new route node with prefix set. */ static struct route_node * route_node_set (struct route_table *table, struct isis_prefix *prefix) { struct route_node *node; node = route_node_new (); isis_prefix_copy (&node->p, prefix); node->table = table; return node; } /* Free route node. */ static void route_node_free (struct route_node *node) { free(node); } /* Free route table. */ void route_table_free (struct route_table *rt) { struct route_node *tmp_node; struct route_node *node; if (rt == NULL) return; node = rt->top; while (node) { if (node->l_left) { node = node->l_left; continue; } if (node->l_right) { node = node->l_right; continue; } tmp_node = node; node = node->parent; if (node != NULL) { if (node->l_left == tmp_node) node->l_left = NULL; else node->l_right = NULL; route_node_free (tmp_node); } else { route_node_free (tmp_node); break; } } free(rt); return; } /* Utility mask array. */ static const u_char maskbit[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; /* Common prefix route genaration. */ static void route_common (struct isis_prefix *n, struct isis_prefix *p, struct isis_prefix *new) { int i; u_char diff; u_char mask; u_char *np = (u_char *)&n->u.prefix; u_char *pp = (u_char *)&p->u.prefix; u_char *newp = (u_char *)&new->u.prefix; for (i = 0; i < p->prefixlen / 8; i++) { if (np[i] == pp[i]) newp[i] = np[i]; else break; } new->prefixlen = i * 8; if (new->prefixlen != p->prefixlen) { diff = np[i] ^ pp[i]; mask = 0x80; while (new->prefixlen < p->prefixlen && !(mask & diff)) { mask >>= 1; new->prefixlen++; } newp[i] = np[i] & maskbit[new->prefixlen % 8]; } } static void set_link (struct route_node *node, struct route_node *new) { unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen); node->link[bit] = new; new->parent = node; } /* Lock node. */ struct route_node * route_lock_node (struct route_node *node) { node->lock++; return node; } /* Unlock node. */ void route_unlock_node (struct route_node *node) { node->lock--; if (node->lock == 0) route_node_delete (node); } /* Find matched prefix. */ struct route_node * route_node_match (const struct route_table *table, const struct isis_prefix *p) { struct route_node *node; struct route_node *matched; matched = NULL; node = table->top; /* Walk down tree. If there is matched route then store it to matched. */ while (node && node->p.prefixlen <= p->prefixlen && isis_prefix_match (&node->p, p)) { if (node->info) matched = node; if (node->p.prefixlen == p->prefixlen) break; node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } /* If matched route found, return it. */ if (matched) return route_lock_node (matched); return NULL; } struct route_node * route_node_match_ipv4 (const struct route_table *table, const struct in_addr *addr) { struct prefix_ipv4 p; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = *addr; return route_node_match (table, (struct isis_prefix *) &p); } struct route_node * route_node_match_ipv6 (const struct route_table *table, const struct in6_addr *addr) { struct prefix_ipv6 p; memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; p.prefix = *addr; return route_node_match (table, (struct isis_prefix *) &p); } /* Lookup same prefix node. Return NULL when we can't find route. */ struct route_node * route_node_lookup (struct route_table *table, struct isis_prefix *p) { struct route_node *node; node = table->top; while (node && node->p.prefixlen <= p->prefixlen && isis_prefix_match (&node->p, p)) { if (node->p.prefixlen == p->prefixlen) return node->info ? route_lock_node (node) : NULL; node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } return NULL; } /* Add node to routing table. */ struct route_node * route_node_get (struct route_table *table, struct isis_prefix *p) { struct route_node *new; struct route_node *node; struct route_node *match; match = NULL; node = table->top; while (node && node->p.prefixlen <= p->prefixlen && isis_prefix_match (&node->p, p)) { if (node->p.prefixlen == p->prefixlen) return route_lock_node (node); match = node; node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } if (node == NULL) { new = route_node_set (table, p); if (match) set_link (match, new); else table->top = new; } else { new = route_node_new (); route_common (&node->p, p, &new->p); new->p.family = p->family; new->table = table; set_link (new, node); if (match) set_link (match, new); else table->top = new; if (new->p.prefixlen != p->prefixlen) { match = new; new = route_node_set (table, p); set_link (match, new); } } route_lock_node (new); return new; } /* Delete node from the routing table. */ void route_node_delete (struct route_node *node) { struct route_node *child; struct route_node *parent; assert (node->lock == 0); assert (node->info == NULL); if (node->l_left && node->l_right) return; if (node->l_left) child = node->l_left; else child = node->l_right; parent = node->parent; if (child) child->parent = parent; if (parent) { if (parent->l_left == node) parent->l_left = child; else parent->l_right = child; } else node->table->top = child; route_node_free (node); /* If parent node is stub then delete it also. */ if (parent && parent->lock == 0) route_node_delete (parent); } /* Get fist node and lock it. This function is useful when one want to lookup all the node exist in the routing table. */ struct route_node * route_top (struct route_table *table) { /* If there is no node in the routing table return NULL. */ if (table->top == NULL) return NULL; /* Lock the top node and return it. */ route_lock_node (table->top); return table->top; } /* Unlock current node and lock next node then return it. */ struct route_node * route_next (struct route_node *node) { struct route_node *next; struct route_node *start; /* Node may be deleted from route_unlock_node so we have to preserve next node's pointer. */ if (node->l_left) { next = node->l_left; route_lock_node (next); route_unlock_node (node); return next; } if (node->l_right) { next = node->l_right; route_lock_node (next); route_unlock_node (node); return next; } start = node; while (node->parent) { if (node->parent->l_left == node && node->parent->l_right) { next = node->parent->l_right; route_lock_node (next); route_unlock_node (start); return next; } node = node->parent; } route_unlock_node (start); return NULL; } /* Unlock current node and lock next node until limit. */ struct route_node * route_next_until (struct route_node *node, struct route_node *limit) { struct route_node *next; struct route_node *start; /* Node may be deleted from route_unlock_node so we have to preserve next node's pointer. */ if (node->l_left) { next = node->l_left; route_lock_node (next); route_unlock_node (node); return next; } if (node->l_right) { next = node->l_right; route_lock_node (next); route_unlock_node (node); return next; } start = node; while (node->parent && node != limit) { if (node->parent->l_left == node && node->parent->l_right) { next = node->parent->l_right; route_lock_node (next); route_unlock_node (start); return next; } node = node->parent; } route_unlock_node (start); return NULL; } pmacct-1.7.8/src/isis/isis_network.h0000644000175000017500000000264514354105275016450 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_network.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_NETWORK_H_ #define _ISIS_NETWORK_H_ extern u_char ALL_L1_ISYSTEMS[]; extern u_char ALL_L2_ISYSTEMS[]; /* int isis_sock_init (struct isis_circuit *circuit); int isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa); int isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa); int isis_send_pdu_bcast (struct isis_circuit *circuit, int level); int isis_send_pdu_p2p (struct isis_circuit *circuit, int level); */ #endif /* _ISIS_NETWORK_H_ */ pmacct-1.7.8/src/isis/hash.h0000644000175000017500000000401314354105275014642 0ustar paolopaolo/* Hash routine. Copyright (C) 1998 Kunihiro Ishiguro This file is part of GNU Zebra. GNU Zebra 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, or (at your option) any later version. GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _HASH_H_ #define _HASH_H_ /* Default hash table size. */ #define HASHTABSIZE 1024 struct hash_backet { /* Linked list. */ struct hash_backet *next; /* Hash key. */ unsigned int key; /* Data. */ void *data; }; struct hash { /* Hash backet. */ struct hash_backet **index; /* Hash table size. */ unsigned int size; /* Key make function. */ unsigned int (*hash_key) (void *); /* Data compare function. */ int (*hash_cmp) (const void *, const void *); /* Backet alloc. */ unsigned long count; }; extern struct hash *isis_hash_create (unsigned int (*) (void *), int (*) (const void *, const void *)); extern struct hash *isis_hash_create_size (unsigned int, unsigned int (*) (void *), int (*) (const void *, const void *)); extern void *isis_hash_get (struct hash *, void *, void * (*) (void *)); extern void *isis_hash_alloc_intern (void *); extern void *isis_hash_lookup (struct hash *, void *); extern void *isis_hash_release (struct hash *, void *); extern void isis_hash_iterate (struct hash *, void (*) (struct hash_backet *, void *), void *); extern void isis_hash_clean (struct hash *, void (*) (void *)); extern void isis_hash_free (struct hash *); extern unsigned int string_hash_make (const char *); #endif /* _HASH_H_ */ pmacct-1.7.8/src/isis/isis_lsp.c0000644000175000017500000013510214354105275015543 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_lsp.c * LSP processing * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "thread.h" #include "stream.h" #include "prefix.h" #include "hash.h" #include "checksum.h" #include "dict.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isisd.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "isis_dynhn.h" #include "isis_misc.h" #include "isis_flags.h" #include "isis_csm.h" #include "isis_adjacency.h" #include "isis_spf.h" #define LSP_MEMORY_PREASSIGN extern struct isis *isis; /* staticly assigned vars for printing purposes */ char lsp_bits_string[200]; /* FIXME: enough ? */ int lsp_id_cmp (u_char * id1, u_char * id2) { return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2); } dict_t * lsp_db_init (void) { dict_t *dict; dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp); return dict; } struct isis_lsp * lsp_search (u_char * id, dict_t * lspdb) { dnode_t *node; node = dict_lookup (lspdb, id); if (node) return (struct isis_lsp *) dnode_get (node); return NULL; } static void lsp_clear_data (struct isis_lsp *lsp) { if (!lsp) return; if (lsp->own_lsp) { if (lsp->tlv_data.nlpids) free(lsp->tlv_data.nlpids); if (lsp->tlv_data.hostname) free(lsp->tlv_data.hostname); } if (lsp->tlv_data.is_neighs) pm_list_delete (lsp->tlv_data.is_neighs); if (lsp->tlv_data.te_is_neighs) pm_list_delete (lsp->tlv_data.te_is_neighs); if (lsp->tlv_data.area_addrs) pm_list_delete (lsp->tlv_data.area_addrs); if (lsp->tlv_data.es_neighs) pm_list_delete (lsp->tlv_data.es_neighs); if (lsp->tlv_data.ipv4_addrs) pm_list_delete (lsp->tlv_data.ipv4_addrs); if (lsp->tlv_data.ipv4_int_reachs) pm_list_delete (lsp->tlv_data.ipv4_int_reachs); if (lsp->tlv_data.ipv4_ext_reachs) pm_list_delete (lsp->tlv_data.ipv4_ext_reachs); if (lsp->tlv_data.te_ipv4_reachs) pm_list_delete (lsp->tlv_data.te_ipv4_reachs); if (lsp->tlv_data.ipv6_addrs) pm_list_delete (lsp->tlv_data.ipv6_addrs); if (lsp->tlv_data.ipv6_reachs) pm_list_delete (lsp->tlv_data.ipv6_reachs); memset (&lsp->tlv_data, 0, sizeof (struct tlvs)); return; } static void lsp_destroy (struct isis_lsp *lsp) { if (!lsp) return; lsp_clear_data (lsp); if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) { pm_list_delete (lsp->lspu.frags); } if (lsp->pdu) stream_free (lsp->pdu); free(lsp); } void lsp_db_destroy (dict_t * lspdb) { dnode_t *dnode, *next; struct isis_lsp *lsp; dnode = dict_first (lspdb); while (dnode) { next = dict_next (lspdb, dnode); lsp = dnode_get (dnode); lsp_destroy (lsp); dict_delete_free (lspdb, dnode); dnode = next; } dict_free (lspdb); return; } /* * Remove all the frags belonging to the given lsp */ static void lsp_remove_frags (struct pm_list *frags, dict_t * lspdb) { dnode_t *dnode; struct pm_listnode *lnode, *lnnode; struct isis_lsp *lsp; for (PM_ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp)) { dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id); lsp_destroy (lsp); dnode_destroy (dict_delete (lspdb, dnode)); } pm_list_delete_all_node (frags); return; } void lsp_search_and_destroy (u_char * id, dict_t * lspdb) { dnode_t *node; struct isis_lsp *lsp; node = dict_lookup (lspdb, id); if (node) { node = dict_delete (lspdb, node); lsp = dnode_get (node); /* * If this is a zero lsp, remove all the frags now */ if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0) { if (lsp->lspu.frags) lsp_remove_frags (lsp->lspu.frags, lspdb); } else { /* * else just remove this frag, from the zero lsps' frag list */ if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags) pm_listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp); } lsp_destroy (lsp); dnode_destroy (node); } } /* * Compares a LSP to given values * Params are given in net order */ int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, u_int16_t checksum, u_int16_t rem_lifetime) { /* no point in double ntohl on seqnum */ if (lsp->lsp_header->seq_num == seq_num && lsp->lsp_header->checksum == checksum && /*comparing with 0, no need to do ntohl */ ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) || (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) { if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): is equal to ours seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime)); } return LSP_EQUAL; } if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num)) { if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime)); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): is newer than ours seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); } return LSP_NEWER; } if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime)); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): is older than ours seq 0x%08x, cksum 0x%04x, lifetime %us\n", config.name, areatag, ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); } return LSP_OLDER; } void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num) { u_int32_t newseq; if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num) newseq = ntohl (lsp->lsp_header->seq_num) + 1; else newseq = seq_num++; lsp->lsp_header->seq_num = htonl (newseq); fletcher_checksum (STREAM_DATA (lsp->pdu) + 12, ntohs (lsp->lsp_header->pdu_len) - 12, 12); return; } /* * Genetates checksum for LSP and its frags */ static void lsp_seqnum_update (struct isis_lsp *lsp0) { struct isis_lsp *lsp; struct pm_listnode *node; lsp_inc_seqnum (lsp0, 0); if (!lsp0->lspu.frags) return; for (PM_ALL_LIST_ELEMENTS_RO (lsp0->lspu.frags, node, lsp)) lsp_inc_seqnum (lsp, 0); return; } int isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area, int pdulen, struct isis_passwd *passwd) { uint32_t expected = 0, found; struct tlvs tlvs; int retval = 0; expected |= TLVFLAG_AUTH_INFO; retval = parse_tlvs (area->area_tag, stream->data + ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, pdulen - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs); if (retval || !(found & TLVFLAG_AUTH_INFO)) return 1; /* Auth fail (parsing failed or no auth-tlv) */ return authentication_check (passwd, &tlvs.auth_info); } static void lsp_update_data (struct isis_lsp *lsp, struct stream *stream, struct isis_area *area) { uint32_t expected = 0, found; int retval; /* copying only the relevant part of our stream */ lsp->pdu = stream_dup (stream); /* setting pointers to the correct place */ lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN); lsp->age_out = ZERO_AGE_LIFETIME; lsp->installed = time (NULL); /* * Get LSP data i.e. TLVs */ expected |= TLVFLAG_AUTH_INFO; expected |= TLVFLAG_AREA_ADDRS; expected |= TLVFLAG_IS_NEIGHS; if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */ expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS; expected |= TLVFLAG_NLPID; if (area->dynhostname) expected |= TLVFLAG_DYN_HOSTNAME; if (area->newmetric) { expected |= TLVFLAG_TE_IS_NEIGHS; expected |= TLVFLAG_TE_IPV4_REACHABILITY; expected |= TLVFLAG_TE_ROUTER_ID; } expected |= TLVFLAG_IPV4_ADDR; expected |= TLVFLAG_IPV4_INT_REACHABILITY; expected |= TLVFLAG_IPV4_EXT_REACHABILITY; expected |= TLVFLAG_IPV6_ADDR; expected |= TLVFLAG_IPV6_REACHABILITY; retval = parse_tlvs (area->area_tag, lsp->pdu->data + ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, ntohs (lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, &expected, &found, &lsp->tlv_data); (void)retval; //TODO treat error if (found & TLVFLAG_DYN_HOSTNAME) { if (area->dynhostname) isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname, (lsp->lsp_header->lsp_bits & LSPBIT_IST) == IS_LEVEL_1_AND_2 ? IS_LEVEL_2 : (lsp->lsp_header->lsp_bits & LSPBIT_IST)); } } void lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr, struct stream *stream, struct isis_area *area, int level) { dnode_t *dnode = NULL; /* Remove old LSP from LSP database. */ dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id); if (dnode) dnode_destroy (dict_delete (area->lspdb[level - 1], dnode)); /* free the old lsp data */ free(lsp->pdu); lsp_clear_data (lsp); /* rebuild the lsp data */ lsp_update_data (lsp, stream, area); /* set the new values for lsp header */ memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN); if (dnode) lsp_insert (lsp, area->lspdb[level - 1]); } /* creation of LSP directly from what we received */ struct isis_lsp * lsp_new_from_stream_ptr (struct stream *stream, u_int16_t pdu_len, struct isis_lsp *lsp0, struct isis_area *area) { struct isis_lsp *lsp; lsp = calloc(1, sizeof (struct isis_lsp)); lsp_update_data (lsp, stream, area); if (lsp0 == NULL) { /* * zero lsp -> create the list for fragments */ lsp->lspu.frags = pm_list_new (); } else { /* * a fragment -> set the backpointer and add this to zero lsps frag list */ lsp->lspu.zero_lsp = lsp0; pm_listnode_add (lsp0->lspu.frags, lsp); } return lsp; } struct isis_lsp * lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num, u_int8_t lsp_bits, u_int16_t checksum, int level) { struct isis_lsp *lsp; lsp = calloc(1, sizeof (struct isis_lsp)); if (!lsp) { /* FIXME: set lspdbol bit */ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): lsp_new(): out of memory\n", config.name); return NULL; } #ifdef LSP_MEMORY_PREASSIGN lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */ #else /* We need to do realloc on TLVs additions */ lsp->pdu = calloc(1, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); #endif /* LSP_MEMORY_PREASSIGN */ if (LSP_FRAGMENT (lsp_id) == 0) lsp->lspu.frags = pm_list_new (); lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN); /* at first we fill the FIXED HEADER */ (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) : fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE); /* now for the LSP HEADER */ /* Minimal LSP PDU size */ lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2); lsp->lsp_header->checksum = checksum; /* Provided in network order */ lsp->lsp_header->seq_num = htonl (seq_num); lsp->lsp_header->rem_lifetime = htons (rem_lifetime); lsp->lsp_header->lsp_bits = lsp_bits; lsp->level = level; lsp->age_out = ZERO_AGE_LIFETIME; stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): New LSP with ID %s-%02x-%02x seqnum %08x\n", config.name, sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id), LSP_FRAGMENT (lsp->lsp_header->lsp_id), ntohl (lsp->lsp_header->seq_num)); return lsp; } void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb) { dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp); } /* * Build a list of LSPs with non-zero ht bounded by start and stop ids */ void lsp_build_isis_list_nonzero_ht (u_char * start_id, u_char * stop_id, struct pm_list *list, dict_t * lspdb) { dnode_t *first, *last, *curr; first = dict_lower_bound (lspdb, start_id); if (!first) return; last = dict_upper_bound (lspdb, stop_id); curr = first; if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime) pm_listnode_add (list, first->dict_data); while (curr) { curr = dict_next (lspdb, curr); if (curr && ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime) pm_listnode_add (list, curr->dict_data); if (curr == last) break; } return; } /* * Build a list of all LSPs bounded by start and stop ids */ void lsp_build_list (u_char * start_id, u_char * stop_id, struct pm_list *list, dict_t * lspdb) { dnode_t *first, *last, *curr; first = dict_lower_bound (lspdb, start_id); if (!first) return; last = dict_upper_bound (lspdb, stop_id); curr = first; pm_listnode_add (list, first->dict_data); while (curr) { curr = dict_next (lspdb, curr); if (curr) pm_listnode_add (list, curr->dict_data); if (curr == last) break; } return; } /* * Build a list of LSPs with SSN flag set for the given circuit */ void lsp_build_isis_list_ssn (struct isis_circuit *circuit, struct pm_list *list, dict_t * lspdb) { dnode_t *dnode, *next; struct isis_lsp *lsp; dnode = dict_first (lspdb); while (dnode != NULL) { next = dict_next (lspdb, dnode); lsp = dnode_get (dnode); if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit)) pm_listnode_add (list, lsp); dnode = next; } return; } /* Convert the lsp attribute bits to attribute string */ const char * lsp_bits2string (u_char * lsp_bits) { char *pos = lsp_bits_string; if (!*lsp_bits) return " none"; /* we only focus on the default metric */ pos += sprintf (pos, "%d/", ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0); pos += sprintf (pos, "%d/", ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0); pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0); *(pos) = '\0'; return lsp_bits_string; } #define FRAG_THOLD(S,T) \ ((STREAM_SIZE(S)*T)/100) /* stream*, area->lsp_frag_threshold, increment */ #define FRAG_NEEDED(S,T,I) \ (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T)) /* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have * variable length (TE TLVs, sub TLVs). */ static void lsp_tlv_fit (struct isis_lsp *lsp, struct pm_list **from, struct pm_list **to, int tlvsize, int frag_thold, int tlv_build_func (struct pm_list *, struct stream *)) { int count, i; /* can we fit all ? */ if (!FRAG_NEEDED (lsp->pdu, frag_thold, pm_listcount (*from) * tlvsize + 2)) { tlv_build_func (*from, lsp->pdu); *to = *from; *from = NULL; } else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2)) { /* fit all we can */ count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 - (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu)); if (count) count = count / tlvsize; for (i = 0; i < count; i++) { pm_listnode_add (*to, pm_listgetdata (pm_listhead (*from))); pm_listnode_delete (*from, pm_listgetdata (pm_listhead (*from))); } tlv_build_func (*to, lsp->pdu); } lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); return; } static struct isis_lsp * lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area, int level) { struct isis_lsp *lsp; u_char frag_id[ISIS_SYS_ID_LEN + 2]; memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT (frag_id) = frag_num; lsp = lsp_search (frag_id, area->lspdb[level - 1]); if (lsp) { /* * Clear the TLVs, but inherit the authinfo */ lsp_clear_data (lsp); if (lsp0->tlv_data.auth_info.type) { /* FIXME: this is broken. Detected by GCC 8.3 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info, sizeof (struct isis_passwd)); */ tlv_add_authinfo (lsp->tlv_data.auth_info.type, lsp->tlv_data.auth_info.len, lsp->tlv_data.auth_info.passwd, lsp->pdu); } return lsp; } lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type, 0, level); lsp->own_lsp = 1; lsp_insert (lsp, area->lspdb[level - 1]); pm_listnode_add (lsp0->lspu.frags, lsp); lsp->lspu.zero_lsp = lsp0; /* * Copy the authinfo from zero LSP */ if (lsp0->tlv_data.auth_info.type) { /* FIXME: this is broken. Detected by GCC 8.3 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info, sizeof (struct isis_passwd)); */ tlv_add_authinfo (lsp->tlv_data.auth_info.type, lsp->tlv_data.auth_info.len, lsp->tlv_data.auth_info.passwd, lsp->pdu); } return lsp; } /* * Builds the LSP data part. This func creates a new frag whenever * area->lsp_frag_threshold is exceeded. */ static void lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area) { struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; struct pm_listnode *node, *ipnode; int level = lsp->level; struct isis_circuit *circuit; struct prefix_ipv4 *ipv4; struct ipv4_reachability *ipreach; struct te_ipv4_reachability *te_ipreach; struct isis_adjacency *nei; struct prefix_ipv6 *ipv6, *ip6prefix; struct ipv6_reachability *ip6reach; struct tlvs tlv_data; struct isis_lsp *lsp0 = lsp; struct isis_passwd *passwd; struct in_addr *routerid; /* * First add the tlvs related to area */ /* Area addresses */ if (lsp->tlv_data.area_addrs == NULL) lsp->tlv_data.area_addrs = pm_list_new (); pm_list_add_list (lsp->tlv_data.area_addrs, area->area_addrs); /* Protocols Supported */ if (area->ip_circuits > 0 || area->ipv6_circuits > 0) { lsp->tlv_data.nlpids = calloc(1, sizeof (struct nlpids)); lsp->tlv_data.nlpids->count = 0; if (area->ip_circuits > 0) { lsp->tlv_data.nlpids->count++; lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; } if (area->ipv6_circuits > 0) { lsp->tlv_data.nlpids->count++; lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = NLPID_IPV6; } } /* XXX: Dynamic Hostname */ /* if (area->dynhostname) { lsp->tlv_data.hostname = calloc(1, sizeof (struct hostname)); memcpy (lsp->tlv_data.hostname->name, unix_hostname (), strlen (unix_hostname ())); lsp->tlv_data.hostname->namelen = strlen (unix_hostname ()); } */ /* * Building the zero lsp */ /* Reset stream endp. Stream is always there and on every LSP refresh only * TLV part of it is overwritten. So we must seek past header we will not * touch. */ stream_reset (lsp->pdu); stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); /* * Add the authentication info if its present */ (level == 1) ? (passwd = &area->area_passwd) : (passwd = &area->domain_passwd); if (passwd->type) { memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd)); tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu); } if (lsp->tlv_data.nlpids) tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu); if (lsp->tlv_data.hostname) tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu); if (lsp->tlv_data.area_addrs && pm_listcount (lsp->tlv_data.area_addrs) > 0) tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu); /* IPv4 address and TE router ID TLVs. In case of the first one we don't * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into * LSP and this address is same as router id. */ if (router_id_zebra.s_addr != 0) { if (lsp->tlv_data.ipv4_addrs == NULL) { lsp->tlv_data.ipv4_addrs = pm_list_new (); lsp->tlv_data.ipv4_addrs->del = free_tlv; } routerid = calloc(1, sizeof (struct in_addr)); routerid->s_addr = router_id_zebra.s_addr; pm_listnode_add (lsp->tlv_data.ipv4_addrs, routerid); tlv_add_in_addr (routerid, lsp->pdu, IPV4_ADDR); /* Exactly same data is put into TE router ID TLV, but only if new style * TLV's are in use. */ if (area->newmetric) { lsp->tlv_data.router_id = calloc(1, sizeof (struct in_addr)); lsp->tlv_data.router_id->id.s_addr = router_id_zebra.s_addr; tlv_add_in_addr (&lsp->tlv_data.router_id->id, lsp->pdu, TE_ROUTER_ID); } } memset (&tlv_data, 0, sizeof (struct tlvs)); /* * Then build lists of tlvs related to circuits */ for (PM_ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) { if (circuit->state != C_STATE_UP) continue; /* * Add IPv4 internal reachability of this circuit */ if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) { if (area->oldmetric) { if (tlv_data.ipv4_int_reachs == NULL) { tlv_data.ipv4_int_reachs = pm_list_new (); tlv_data.ipv4_int_reachs->del = free_tlv; } for (PM_ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) { ipreach = calloc(1, sizeof (struct ipv4_reachability)); ipreach->metrics = circuit->metrics[level - 1]; isis_masklen2ip (ipv4->prefixlen, &ipreach->mask); ipreach->prefix.s_addr = ((ipreach->mask.s_addr) & (ipv4->prefix.s_addr)); pm_listnode_add (tlv_data.ipv4_int_reachs, ipreach); } tlv_data.ipv4_int_reachs->del = free_tlv; } if (area->newmetric) { if (tlv_data.te_ipv4_reachs == NULL) { tlv_data.te_ipv4_reachs = pm_list_new (); tlv_data.te_ipv4_reachs->del = free_tlv; } for (PM_ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) { /* FIXME All this assumes that we have no sub TLVs. */ te_ipreach = calloc(1, sizeof (struct te_ipv4_reachability) + ((ipv4->prefixlen + 7)/8) - 1); if (area->oldmetric) te_ipreach->te_metric = htonl (circuit->metrics[level - 1].metric_default); else te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]); te_ipreach->control = (ipv4->prefixlen & 0x3F); memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr, (ipv4->prefixlen + 7)/8); pm_listnode_add (tlv_data.te_ipv4_reachs, te_ipreach); } } } /* * Add IPv6 reachability of this circuit */ if (circuit->ipv6_router && circuit->ipv6_non_link && circuit->ipv6_non_link->count > 0) { if (tlv_data.ipv6_reachs == NULL) { tlv_data.ipv6_reachs = pm_list_new (); tlv_data.ipv6_reachs->del = free_tlv; } for (PM_ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6)) { ip6reach = calloc(1, sizeof (struct ipv6_reachability)); if (area->oldmetric) ip6reach->metric = htonl (circuit->metrics[level - 1].metric_default); else ip6reach->metric = htonl (circuit->te_metric[level - 1]); ip6reach->control_info = 0; ip6reach->prefix_len = ipv6->prefixlen; memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix)); isis_apply_mask_ipv6 (ip6prefix); memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr, sizeof (ip6reach->prefix)); pm_listnode_add (tlv_data.ipv6_reachs, ip6reach); } } switch (circuit->circ_type) { case CIRCUIT_T_BROADCAST: if (level & circuit->circuit_is_type) { if (area->oldmetric) { if (tlv_data.is_neighs == NULL) { tlv_data.is_neighs = pm_list_new (); tlv_data.is_neighs->del = free_tlv; } is_neigh = calloc(1, sizeof (struct is_neigh)); if (level == 1) memcpy (is_neigh->neigh_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); else memcpy (is_neigh->neigh_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); is_neigh->metrics = circuit->metrics[level - 1]; pm_listnode_add (tlv_data.is_neighs, is_neigh); tlv_data.is_neighs->del = free_tlv; } if (area->newmetric) { uint32_t metric; if (tlv_data.te_is_neighs == NULL) { tlv_data.te_is_neighs = pm_list_new (); tlv_data.te_is_neighs->del = free_tlv; } te_is_neigh = calloc(1, sizeof (struct te_is_neigh)); if (level == 1) memcpy (te_is_neigh->neigh_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); else memcpy (te_is_neigh->neigh_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); if (area->oldmetric) metric = ((htonl(circuit->metrics[level - 1].metric_default) >> 8) & 0xffffff); else metric = ((htonl(*circuit->te_metric) >> 8) & 0xffffff); memcpy (te_is_neigh->te_metric, &metric, 3); pm_listnode_add (tlv_data.te_is_neighs, te_is_neigh); } } break; case CIRCUIT_T_P2P: nei = circuit->u.p2p.neighbor; if (nei && (level & nei->circuit_t)) { if (area->oldmetric) { if (tlv_data.is_neighs == NULL) { tlv_data.is_neighs = pm_list_new (); tlv_data.is_neighs->del = free_tlv; } is_neigh = calloc(1, sizeof (struct is_neigh)); memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); is_neigh->metrics = circuit->metrics[level - 1]; pm_listnode_add (tlv_data.is_neighs, is_neigh); } if (area->newmetric) { uint32_t metric; if (tlv_data.te_is_neighs == NULL) { tlv_data.te_is_neighs = pm_list_new (); tlv_data.te_is_neighs->del = free_tlv; } te_is_neigh = calloc(1, sizeof (struct te_is_neigh)); memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); metric = ((htonl(*circuit->te_metric) >> 8) & 0xffffff); memcpy (te_is_neigh->te_metric, &metric, 3); pm_listnode_add (tlv_data.te_is_neighs, te_is_neigh); } } break; case CIRCUIT_T_STATIC_IN: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): lsp_area_create: unsupported circuit type\n", config.name); break; case CIRCUIT_T_STATIC_OUT: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): lsp_area_create: unsupported circuit type\n", config.name); break; case CIRCUIT_T_DA: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): lsp_area_create: unsupported circuit type\n", config.name); break; default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): lsp_area_create: unknown circuit type\n", config.name); } } while (tlv_data.ipv4_int_reachs && pm_listcount (tlv_data.ipv4_int_reachs)) { if (lsp->tlv_data.ipv4_int_reachs == NULL) lsp->tlv_data.ipv4_int_reachs = pm_list_new (); lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN, area->lsp_frag_threshold, tlv_add_ipv4_reachs); if (tlv_data.ipv4_int_reachs && pm_listcount (tlv_data.ipv4_int_reachs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } /* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit() * for now. lsp_tlv_fit() needs to be fixed to deal with variable length * TLVs (sub TLVs!). */ while (tlv_data.te_ipv4_reachs && pm_listcount (tlv_data.te_ipv4_reachs)) { if (lsp->tlv_data.te_ipv4_reachs == NULL) lsp->tlv_data.te_ipv4_reachs = pm_list_new (); lsp_tlv_fit (lsp, &tlv_data.te_ipv4_reachs, &lsp->tlv_data.te_ipv4_reachs, 9, area->lsp_frag_threshold, tlv_add_te_ipv4_reachs); if (tlv_data.te_ipv4_reachs && pm_listcount (tlv_data.te_ipv4_reachs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } while (tlv_data.ipv6_reachs && pm_listcount (tlv_data.ipv6_reachs)) { if (lsp->tlv_data.ipv6_reachs == NULL) lsp->tlv_data.ipv6_reachs = pm_list_new (); lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs, &lsp->tlv_data.ipv6_reachs, IPV6_REACH_LEN, area->lsp_frag_threshold, tlv_add_ipv6_reachs); if (tlv_data.ipv6_reachs && pm_listcount (tlv_data.ipv6_reachs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } while (tlv_data.is_neighs && pm_listcount (tlv_data.is_neighs)) { if (lsp->tlv_data.is_neighs == NULL) lsp->tlv_data.is_neighs = pm_list_new (); lsp_tlv_fit (lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs, IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, tlv_add_is_neighs); if (tlv_data.is_neighs && pm_listcount (tlv_data.is_neighs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } while (tlv_data.te_is_neighs && pm_listcount (tlv_data.te_is_neighs)) { if (lsp->tlv_data.te_is_neighs == NULL) lsp->tlv_data.te_is_neighs = pm_list_new (); lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs, IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, tlv_add_te_is_neighs); if (tlv_data.te_is_neighs && pm_listcount (tlv_data.te_is_neighs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } free_tlvs (&tlv_data); return; } /* * 7.3.7 Generation on non-pseudonode LSPs */ static int lsp_generate_non_pseudo (struct isis_area *area, int level) { struct isis_lsp *oldlsp, *newlsp; u_int32_t seq_num = 0; u_char lspid[ISIS_SYS_ID_LEN + 2]; memset (&lspid, 0, ISIS_SYS_ID_LEN + 2); memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN); /* only builds the lsp if the area shares the level */ if ((area->is_type & level) == level) { oldlsp = lsp_search (lspid, area->lspdb[level - 1]); if (oldlsp) { seq_num = ntohl (oldlsp->lsp_header->seq_num); lsp_search_and_destroy (oldlsp->lsp_header->lsp_id, area->lspdb[level - 1]); /* FIXME: we should actually initiate a purge */ } newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num, area->is_type, 0, level); newlsp->own_lsp = 1; lsp_insert (newlsp, area->lspdb[level - 1]); /* build_lsp_data (newlsp, area); */ lsp_build_nonpseudo (newlsp, area); /* time to calculate our checksum */ lsp_seqnum_update (newlsp); } /* DEBUG_ADJ_PACKETS */ if (config.nfacctd_isis_msglog) { /* FIXME: is this place right? fix missing info */ Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): Building L%d LSP\n", config.name, area->area_tag, level); } return ISIS_OK; } /* * 7.3.9 Generation of level 1 LSPs (non-pseudonode) */ int lsp_l1_generate (struct isis_area *area) { THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area, MAX_LSP_GEN_INTERVAL); return lsp_generate_non_pseudo (area, 1); } /* * 7.3.9 Generation of level 2 LSPs (non-pseudonode) */ int lsp_l2_generate (struct isis_area *area) { THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area, MAX_LSP_GEN_INTERVAL); return lsp_generate_non_pseudo (area, 2); } static int lsp_non_pseudo_regenerate (struct isis_area *area, int level) { dict_t *lspdb = area->lspdb[level - 1]; struct isis_lsp *lsp, *frag; struct pm_listnode *node; u_char lspid[ISIS_SYS_ID_LEN + 2]; memset (lspid, 0, ISIS_SYS_ID_LEN + 2); memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); lsp = lsp_search (lspid, lspdb); if (!lsp) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!\n", config.name, area->area_tag, level); return ISIS_ERROR; } lsp_clear_data (lsp); lsp_build_nonpseudo (lsp, area); lsp->lsp_header->rem_lifetime = htons (isis_jitter (area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER)); lsp_seqnum_update (lsp); if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): refreshing our L%d LSP %s, seq 0x%08x, cksum 0x%04x lifetime %us\n", config.name, area->area_tag, level, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); } lsp->last_generated = time (NULL); area->lsp_regenerate_pending[level - 1] = 0; ISIS_FLAGS_SET_ALL (lsp->SRMflags); for (PM_ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag)) { frag->lsp_header->rem_lifetime = htons (isis_jitter (area-> max_lsp_lifetime[level - 1], MAX_AGE_JITTER)); ISIS_FLAGS_SET_ALL (frag->SRMflags); } if (area->ip_circuits) isis_spf_schedule (area, level); if (area->ipv6_circuits) isis_spf_schedule6 (area, level); return ISIS_OK; } /* * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding * time and set SRM */ int lsp_refresh_l1 (struct thread *thread) { struct isis_area *area; unsigned long ref_time; area = THREAD_ARG (thread); assert (area); area->t_lsp_refresh[0] = NULL; if (area->is_type & IS_LEVEL_1) lsp_non_pseudo_regenerate (area, 1); ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0]; THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area, isis_jitter (ref_time, MAX_AGE_JITTER)); return ISIS_OK; } int lsp_refresh_l2 (struct thread *thread) { struct isis_area *area; unsigned long ref_time; area = THREAD_ARG (thread); assert (area); area->t_lsp_refresh[1] = NULL; if (area->is_type & IS_LEVEL_2) lsp_non_pseudo_regenerate (area, 2); ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1]; THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area, isis_jitter (ref_time, MAX_AGE_JITTER)); return ISIS_OK; } /* * Something has changed -> regenerate LSP */ static int lsp_l1_regenerate (struct thread *thread) { struct isis_area *area; area = THREAD_ARG (thread); area->lsp_regenerate_pending[0] = 0; return lsp_non_pseudo_regenerate (area, 1); } static int lsp_l2_regenerate (struct thread *thread) { struct isis_area *area; area = THREAD_ARG (thread); area->lsp_regenerate_pending[1] = 0; return lsp_non_pseudo_regenerate (area, 2); } int lsp_regenerate_schedule (struct isis_area *area) { struct isis_lsp *lsp; u_char id[ISIS_SYS_ID_LEN + 2]; time_t now, diff; memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0; now = time (NULL); /* * First level 1 */ if (area->is_type & IS_LEVEL_1) { lsp = lsp_search (id, area->lspdb[0]); if (!lsp || area->lsp_regenerate_pending[0]) goto L2; /* * Throttle avoidance */ diff = now - lsp->last_generated; if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[0] = 1; area->t_lsp_l1_regenerate=thread_add_timer (master, lsp_l1_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); goto L2; } else lsp_non_pseudo_regenerate (area, 1); } /* * then 2 */ L2: if (area->is_type & IS_LEVEL_2) { lsp = lsp_search (id, area->lspdb[1]); if (!lsp || area->lsp_regenerate_pending[1]) return ISIS_OK; /* * Throttle avoidance */ diff = now - lsp->last_generated; if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[1] = 1; area->t_lsp_l2_regenerate=thread_add_timer (master, lsp_l2_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); return ISIS_OK; } else lsp_non_pseudo_regenerate (area, 2); } return ISIS_OK; } /* * Funcs for pseudonode LSPs */ /* * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs */ static void lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit, int level) { struct isis_adjacency *adj; struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; struct es_neigh *es_neigh; struct pm_list *adj_list; struct pm_listnode *node; struct isis_passwd *passwd; assert (circuit); assert (circuit->circ_type == CIRCUIT_T_BROADCAST); if (!circuit->u.bc.is_dr[level - 1]) return; /* we are not DIS on this circuit */ lsp->level = level; if (level == 1) lsp->lsp_header->lsp_bits |= IS_LEVEL_1; else lsp->lsp_header->lsp_bits |= IS_LEVEL_2; /* * add self to IS neighbours */ if (circuit->area->oldmetric) { if (lsp->tlv_data.is_neighs == NULL) { lsp->tlv_data.is_neighs = pm_list_new (); lsp->tlv_data.is_neighs->del = free_tlv; } is_neigh = calloc(1, sizeof (struct is_neigh)); memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); pm_listnode_add (lsp->tlv_data.is_neighs, is_neigh); } if (circuit->area->newmetric) { if (lsp->tlv_data.te_is_neighs == NULL) { lsp->tlv_data.te_is_neighs = pm_list_new (); lsp->tlv_data.te_is_neighs->del = free_tlv; } te_is_neigh = calloc(1, sizeof (struct te_is_neigh)); memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); pm_listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); } adj_list = pm_list_new (); isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list); for (PM_ALL_LIST_ELEMENTS_RO (adj_list, node, adj)) { if (adj->circuit_t & level) { if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) || (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS && adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS)) { /* an IS neighbour -> add it */ if (circuit->area->oldmetric) { is_neigh = calloc(1, sizeof (struct is_neigh)); memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); pm_listnode_add (lsp->tlv_data.is_neighs, is_neigh); } if (circuit->area->newmetric) { te_is_neigh = calloc(1, sizeof (struct te_is_neigh)); memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); pm_listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); } } else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES) { /* an ES neigbour add it, if we are building level 1 LSP */ /* FIXME: the tlv-format is hard to use here */ if (lsp->tlv_data.es_neighs == NULL) { lsp->tlv_data.es_neighs = pm_list_new (); lsp->tlv_data.es_neighs->del = free_tlv; } es_neigh = calloc(1, sizeof (struct es_neigh)); memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN); pm_listnode_add (lsp->tlv_data.es_neighs, es_neigh); } } } /* Reset endp of stream to overwrite only TLV part of it. */ stream_reset (lsp->pdu); stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); /* * Add the authentication info if it's present */ (level == 1) ? (passwd = &circuit->area->area_passwd) : (passwd = &circuit->area->domain_passwd); if (passwd->type) { memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd)); tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu); } if (lsp->tlv_data.is_neighs && pm_listcount (lsp->tlv_data.is_neighs) > 0) tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu); if (lsp->tlv_data.te_is_neighs && pm_listcount (lsp->tlv_data.te_is_neighs) > 0) tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu); if (lsp->tlv_data.es_neighs && pm_listcount (lsp->tlv_data.es_neighs) > 0) tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu); lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); fletcher_checksum (STREAM_DATA (lsp->pdu) + 12, ntohs (lsp->lsp_header->pdu_len) - 12, 12); pm_list_delete (adj_list); return; } static int lsp_pseudo_regenerate (struct isis_circuit *circuit, int level) { dict_t *lspdb = circuit->area->lspdb[level - 1]; struct isis_lsp *lsp; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; LSP_FRAGMENT (lsp_id) = 0; lsp = lsp_search (lsp_id, lspdb); if (!lsp) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): lsp_pseudo_regenerate(): no l%d LSP %s found!\n", config.name, level, rawlspid_print (lsp_id)); return ISIS_ERROR; } lsp_clear_data (lsp); lsp_build_pseudo (lsp, circuit, level); lsp->lsp_header->rem_lifetime = htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER)); lsp_inc_seqnum (lsp, 0); if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): refreshing pseudo LSP L%d %s\n", config.name, circuit->area->area_tag, level, rawlspid_print (lsp->lsp_header->lsp_id)); } lsp->last_generated = time (NULL); ISIS_FLAGS_SET_ALL (lsp->SRMflags); return ISIS_OK; } int lsp_l1_refresh_pseudo (struct thread *thread) { struct isis_circuit *circuit; int retval; unsigned long ref_time; circuit = THREAD_ARG (thread); if (!circuit->u.bc.is_dr[0]) return ISIS_ERROR; /* FIXME: purge and such */ circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL; retval = lsp_pseudo_regenerate (circuit, 1); ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0]; THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0], lsp_l1_refresh_pseudo, circuit, isis_jitter (ref_time, MAX_AGE_JITTER)); return retval; } int lsp_l1_pseudo_generate (struct isis_circuit *circuit) { struct isis_lsp *lsp; u_char id[ISIS_SYS_ID_LEN + 2]; unsigned long ref_time; memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); LSP_FRAGMENT (id) = 0; LSP_PSEUDO_ID (id) = circuit->circuit_id; /* * If for some reason have a pseudo LSP in the db already -> regenerate */ if (lsp_search (id, circuit->area->lspdb[0])) return lsp_pseudo_regenerate (circuit, 1); lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0], 1, circuit->area->is_type, 0, 1); lsp_build_pseudo (lsp, circuit, 1); lsp->own_lsp = 1; lsp_insert (lsp, circuit->area->lspdb[0]); ISIS_FLAGS_SET_ALL (lsp->SRMflags); ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0]; THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0], lsp_l1_refresh_pseudo, circuit, isis_jitter (ref_time, MAX_AGE_JITTER)); return lsp_regenerate_schedule (circuit->area); } int lsp_l2_refresh_pseudo (struct thread *thread) { struct isis_circuit *circuit; int retval; unsigned long ref_time; circuit = THREAD_ARG (thread); if (!circuit->u.bc.is_dr[1]) return ISIS_ERROR; /* FIXME: purge and such */ circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL; retval = lsp_pseudo_regenerate (circuit, 2); ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1]; THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1], lsp_l2_refresh_pseudo, circuit, isis_jitter (ref_time, MAX_AGE_JITTER)); return retval; } int lsp_l2_pseudo_generate (struct isis_circuit *circuit) { struct isis_lsp *lsp; u_char id[ISIS_SYS_ID_LEN + 2]; unsigned long ref_time; memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); LSP_FRAGMENT (id) = 0; LSP_PSEUDO_ID (id) = circuit->circuit_id; if (lsp_search (id, circuit->area->lspdb[1])) return lsp_pseudo_regenerate (circuit, 2); lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1], 1, circuit->area->is_type, 0, 2); lsp_build_pseudo (lsp, circuit, 2); ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1]; lsp->own_lsp = 1; lsp_insert (lsp, circuit->area->lspdb[1]); ISIS_FLAGS_SET_ALL (lsp->SRMflags); THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1], lsp_l2_refresh_pseudo, circuit, isis_jitter (ref_time, MAX_AGE_JITTER)); return lsp_regenerate_schedule (circuit->area); } void lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level) { struct isis_lsp *lsp; lsp = lsp_search (id, circuit->area->lspdb[level - 1]); if (lsp && lsp->purged == 0) { lsp->lsp_header->rem_lifetime = htons (0); lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); lsp->purged = 0; fletcher_checksum (STREAM_DATA (lsp->pdu) + 12, ntohs (lsp->lsp_header->pdu_len) - 12, 12); ISIS_FLAGS_SET_ALL (lsp->SRMflags); } return; } /* * Purge own LSP that is received and we don't have. * -> Do as in 7.3.16.4 */ void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr, struct isis_area *area) { struct isis_lsp *lsp; /* * We need to create the LSP to be purged */ Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): LSP PURGE NON EXIST\n", config.name); lsp = calloc(1, sizeof (struct isis_lsp)); /*FIXME: BUG BUG BUG! the lsp doesn't exist here! */ /*did smt here, maybe good probably not */ lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2; lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu); fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE : L2_LINK_STATE); lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN); memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN); /* * Retain only LSP header */ lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); /* * Set the remaining lifetime to 0 */ lsp->lsp_header->rem_lifetime = 0; /* * Put the lsp into LSPdb */ lsp_insert (lsp, area->lspdb[lsp->level - 1]); /* * Send in to whole area */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); return; } pmacct-1.7.8/src/isis/isisd.c0000644000175000017500000002070314354105275015031 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isisd.c * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "hash.h" #include "prefix.h" #include "table.h" #include "dict.h" #include "thread.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isis_flags.h" #include "isisd.h" #include "isis_misc.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_constants.h" #include "isis_adjacency.h" #include "isis_dynhn.h" #include "isis_pdu.h" #include "isis_spf.h" #include "isis_route.h" #include "isis_csm.h" extern struct thread_master *master; void isis_new(unsigned long); struct isis_area *isis_area_create(void); int isis_area_get(const char *); int isis_area_destroy(const char *); void isis_new (unsigned long process_id) { isis = calloc(1, sizeof (struct isis)); /* * Default values */ isis->max_area_addrs = 3; isis->process_id = process_id; isis->area_list = pm_list_new (); isis->init_circ_list = pm_list_new (); isis->uptime = time (NULL); isis->nexthops = pm_list_new (); isis->nexthops6 = pm_list_new (); /* * uncomment the next line for full debugs */ /* isis->debugs = 0xFFFF; */ } void isis_init () { isis_new (0); } struct isis_area * isis_area_create () { struct isis_area *area; area = calloc(1, sizeof (struct isis_area)); /* * The first instance is level-1-2 rest are level-1, unless otherwise * configured */ if (pm_listcount (isis->area_list) > 0) area->is_type = IS_LEVEL_1; else area->is_type = IS_LEVEL_1_AND_2; /* * intialize the databases */ area->lspdb[0] = lsp_db_init (); area->lspdb[1] = lsp_db_init (); spftree_area_init (area); area->route_table[0] = route_table_init (); area->route_table[1] = route_table_init (); area->route_table6[0] = route_table_init (); area->route_table6[1] = route_table_init (); area->circuit_list = pm_list_new (); area->area_addrs = pm_list_new (); flags_initialize (&area->flags); /* * Default values */ area->max_lsp_lifetime[0] = MAX_AGE; /* 1200 */ area->max_lsp_lifetime[1] = MAX_AGE; /* 1200 */ area->lsp_gen_interval[0] = LSP_GEN_INTERVAL_DEFAULT; area->lsp_gen_interval[1] = LSP_GEN_INTERVAL_DEFAULT; area->lsp_refresh[0] = MAX_LSP_GEN_INTERVAL; /* 900 */ area->lsp_refresh[1] = MAX_LSP_GEN_INTERVAL; /* 900 */ area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; area->dynhostname = 1; area->oldmetric = 1; area->lsp_frag_threshold = 90; /* FIXME: Think of a better way... */ area->min_bcast_mtu = 1497; return area; } struct isis_area * isis_area_lookup (const char *area_tag) { struct isis_area *area; struct pm_listnode *node; for (PM_ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) if ((area->area_tag == NULL && area_tag == NULL) || (area->area_tag && area_tag && strcmp (area->area_tag, area_tag) == 0)) return area; return NULL; } int isis_area_get (const char *area_tag) { struct isis_area *area; area = isis_area_lookup (area_tag); if (area) { return FALSE; } area = isis_area_create (); area->area_tag = strdup (area_tag); pm_listnode_add (isis->area_list, area); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): New IS-IS area instance %s\n", config.name, area->area_tag); return FALSE; } int isis_area_destroy (const char *area_tag) { struct isis_area *area; struct pm_listnode *node, *nnode; struct isis_circuit *circuit; area = isis_area_lookup (area_tag); if (area == NULL) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't find ISIS instance %s\n", config.name, area_tag); return TRUE; } if (area->circuit_list) { for (PM_ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) { /* The fact that it's in circuit_list means that it was configured */ isis_csm_state_change (ISIS_DISABLE, circuit, area); isis_circuit_down (circuit); isis_circuit_deconfigure (circuit, area); } pm_list_delete (area->circuit_list); } pm_listnode_delete (isis->area_list, area); if (area->t_remove_aged) thread_cancel (area->t_remove_aged); THREAD_TIMER_OFF (area->spftree[0]->t_spf); THREAD_TIMER_OFF (area->spftree[1]->t_spf); free(area); isis->sysid_set=0; return FALSE; } int area_net_title (struct isis_area *area, const char *net_title) { struct area_addr *addr; struct area_addr *addrp; struct pm_listnode *node; char buff[255]; if (!area) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't find ISIS instance\n", config.name); return TRUE; } /* We check that we are not over the maximal number of addresses */ if (pm_listcount (area->area_addrs) >= isis->max_area_addrs) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Maximum of area addresses (%d) already reached\n", config.name, isis->max_area_addrs); return TRUE; } addr = calloc(1, sizeof (struct area_addr)); addr->addr_len = dotformat2buff (buff, net_title); memcpy (addr->area_addr, buff, addr->addr_len); if (addr->addr_len < 8 || addr->addr_len > 20) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): area address must be at least 8..20 octets long (%d)\n", config.name, addr->addr_len); free(addr); return TRUE; } if (isis->sysid_set == 0) { /* * First area address - get the SystemID for this router */ memcpy (isis->sysid, GETSYSID (addr, ISIS_SYS_ID_LEN), ISIS_SYS_ID_LEN); isis->sysid_set = 1; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): Router has SystemID %s\n", config.name, sysid_print (isis->sysid)); } else { /* * Check that the SystemID portions match */ if (memcmp (isis->sysid, GETSYSID (addr, ISIS_SYS_ID_LEN), ISIS_SYS_ID_LEN)) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): System ID must not change when defining additional area addresses\n", config.name); free(addr); return TRUE; } /* now we see that we don't already have this address */ for (PM_ALL_LIST_ELEMENTS_RO (area->area_addrs, node, addrp)) { if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) != (addr->addr_len)) continue; if (!memcmp (addrp->area_addr, addr->area_addr, addr->addr_len)) { free(addr); return FALSE; /* silent fail */ } } } /* * Forget the systemID part of the address */ addr->addr_len -= (ISIS_SYS_ID_LEN + 1); pm_listnode_add (area->area_addrs, addr); /* Only now we can safely generate our LSPs for this area */ if (pm_listcount (area->area_addrs) > 0) { lsp_l1_generate (area); lsp_l2_generate (area); } return FALSE; } int area_clear_net_title (struct isis_area *area, const char *net_title) { struct area_addr addr, *addrp = NULL; struct pm_listnode *node; char buff[255]; if (!area) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't find ISIS instance\n", config.name); return TRUE; } addr.addr_len = dotformat2buff (buff, net_title); if (addr.addr_len < 8 || addr.addr_len > 20) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Unsupported area address length %d, should be 8...20\n", config.name, addr.addr_len); return TRUE; } memcpy (addr.area_addr, buff, (int) addr.addr_len); for (PM_ALL_LIST_ELEMENTS_RO (area->area_addrs, node, addrp)) if (addrp->addr_len == addr.addr_len && !memcmp (addrp->area_addr, addr.area_addr, addr.addr_len)) break; if (!addrp) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): No area address %s for area %s\n", config.name, net_title, area->area_tag); return TRUE; } pm_listnode_delete (area->area_addrs, addrp); return FALSE; } pmacct-1.7.8/src/isis/isis_flags.c0000644000175000017500000000415314354105275016042 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_flags.c * Routines for manipulation of SSN and SRM flags * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" void flags_initialize (struct flags *flags) { flags->maxindex = 0; flags->free_idcs = NULL; } long int flags_get_index (struct flags *flags) { struct pm_listnode *node; long int index; if (flags->free_idcs == NULL || flags->free_idcs->count == 0) { index = flags->maxindex++; } else { node = pm_listhead (flags->free_idcs); index = (long int) pm_listgetdata (node); pm_listnode_delete (flags->free_idcs, (void *) index); index--; } return index; } void flags_free_index (struct flags *flags, long int index) { if (index + 1 == flags->maxindex) { flags->maxindex--; return; } if (flags->free_idcs == NULL) { flags->free_idcs = pm_list_new (); } pm_listnode_add (flags->free_idcs, (void *) (index + 1)); return; } int flags_any_set (u_int32_t * flags) { u_int32_t zero[ISIS_MAX_CIRCUITS]; memset (zero, 0x00, ISIS_MAX_CIRCUITS * 4); return bcmp (flags, zero, ISIS_MAX_CIRCUITS * 4); } pmacct-1.7.8/src/isis/isis_route.c0000644000175000017500000004213314354105275016104 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_route.c * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * based on ../ospf6d/ospf6_route.[ch] * by Yasuhiro Ohara * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "dict.h" #include "thread.h" #include "prefix.h" #include "table.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_constants.h" #include "isis_adjacency.h" #include "isis_flags.h" #include "isisd.h" #include "isis_csm.h" #include "isis_route.h" #include "isis_spf.h" extern struct isis *isis; extern struct thread_master *master; static struct isis_nexthop * isis_nexthop_create (struct in_addr *ip, unsigned int ifindex) { struct pm_listnode *node; struct isis_nexthop *nexthop; for (PM_ALL_LIST_ELEMENTS_RO (isis->nexthops, node, nexthop)) { if (nexthop->ifindex != ifindex) continue; if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0) continue; nexthop->lock++; return nexthop; } nexthop = calloc(1, sizeof (struct isis_nexthop)); if (!nexthop) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Rte: isis_nexthop_create: out of memory!\n", config.name); } if (nexthop) { nexthop->ifindex = ifindex; memcpy (&nexthop->ip, ip, sizeof (struct in_addr)); pm_listnode_add (isis->nexthops, nexthop); nexthop->lock++; } return nexthop; } static void isis_nexthop_delete (struct isis_nexthop *nexthop) { nexthop->lock--; if (nexthop->lock == 0) { pm_listnode_delete (isis->nexthops, nexthop); free(nexthop); } return; } static int nexthoplookup (struct pm_list *nexthops, struct in_addr *ip, unsigned int ifindex) { struct pm_listnode *node; struct isis_nexthop *nh; for (PM_ALL_LIST_ELEMENTS_RO (nexthops, node, nh)) { if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) && ifindex == nh->ifindex) return 1; } return 0; } static struct isis_nexthop6 * isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) { struct isis_nexthop6 *nexthop6; nexthop6 = calloc(1, sizeof (struct isis_nexthop6)); if (!nexthop6) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Rte: isis_nexthop_create6: out of memory!\n", config.name); } nexthop6->ifindex = ifindex; memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr)); nexthop6->lock++; return nexthop6; } static struct isis_nexthop6 * isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex) { struct pm_listnode *node; struct isis_nexthop6 *nexthop6; for (PM_ALL_LIST_ELEMENTS_RO (isis->nexthops6, node, nexthop6)) { if (nexthop6->ifindex != ifindex) continue; if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0) continue; nexthop6->lock++; return nexthop6; } nexthop6 = isis_nexthop6_new (ip6, ifindex); return nexthop6; } static void isis_nexthop6_delete (struct isis_nexthop6 *nexthop6) { nexthop6->lock--; if (nexthop6->lock == 0) { pm_listnode_delete (isis->nexthops6, nexthop6); free(nexthop6); } return; } static int nexthop6lookup (struct pm_list *nexthops6, struct in6_addr *ip6, unsigned int ifindex) { struct pm_listnode *node; struct isis_nexthop6 *nh6; for (PM_ALL_LIST_ELEMENTS_RO (nexthops6, node, nh6)) { if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) && ifindex == nh6->ifindex) return 1; } return 0; } static void adjinfo2nexthop (struct pm_list *nexthops, struct isis_adjacency *adj) { struct isis_nexthop *nh; struct pm_listnode *node; struct in_addr *ipv4_addr; if (adj->ipv4_addrs == NULL) return; for (PM_ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) { if (!nexthoplookup (nexthops, ipv4_addr, adj->circuit->interface->ifindex)) { nh = isis_nexthop_create (ipv4_addr, adj->circuit->interface->ifindex); pm_listnode_add (nexthops, nh); } } } static void adjinfo2nexthop6 (struct pm_list *nexthops6, struct isis_adjacency *adj) { struct pm_listnode *node; struct in6_addr *ipv6_addr; struct isis_nexthop6 *nh6; if (!adj->ipv6_addrs) return; for (PM_ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) { if (!nexthop6lookup (nexthops6, ipv6_addr, adj->circuit->interface->ifindex)) { nh6 = isis_nexthop6_create (ipv6_addr, adj->circuit->interface->ifindex); pm_listnode_add (nexthops6, nh6); } } } static struct isis_route_info * isis_route_info_new (uint32_t cost, uint32_t depth, u_char family, struct pm_list *adjacencies) { struct isis_route_info *rinfo; struct isis_adjacency *adj; struct pm_listnode *node; rinfo = calloc(1, sizeof (struct isis_route_info)); if (!rinfo) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Rte: isis_route_info_new: out of memory!\n", config.name); return NULL; } if (family == AF_INET) { rinfo->nexthops = pm_list_new (); for (PM_ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) adjinfo2nexthop (rinfo->nexthops, adj); } if (family == AF_INET6) { rinfo->nexthops6 = pm_list_new (); for (PM_ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) adjinfo2nexthop6 (rinfo->nexthops6, adj); } rinfo->cost = cost; rinfo->depth = depth; return rinfo; } static void isis_route_info_delete (struct isis_route_info *route_info) { if (route_info->nexthops) { route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete; pm_list_delete (route_info->nexthops); } if (route_info->nexthops6) { route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete; pm_list_delete (route_info->nexthops6); } free(route_info); } static int isis_route_info_same_attrib (struct isis_route_info *new, struct isis_route_info *old) { if (new->cost != old->cost) return 0; if (new->depth != old->depth) return 0; return 1; } static int isis_route_info_same (struct isis_route_info *new, struct isis_route_info *old, u_char family) { struct pm_listnode *node; struct isis_nexthop *nexthop; struct isis_nexthop6 *nexthop6; if (!isis_route_info_same_attrib (new, old)) return 0; if (family == AF_INET) { for (PM_ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop)) if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex) == 0) return 0; for (PM_ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop)) if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex) == 0) return 0; } else if (family == AF_INET6) { for (PM_ALL_LIST_ELEMENTS_RO (new->nexthops6, node, nexthop6)) if (nexthop6lookup (old->nexthops6, &nexthop6->ip6, nexthop6->ifindex) == 0) return 0; for (PM_ALL_LIST_ELEMENTS_RO (old->nexthops6, node, nexthop6)) if (nexthop6lookup (new->nexthops6, &nexthop6->ip6, nexthop6->ifindex) == 0) return 0; } return 1; } static void isis_nexthops_merge (struct pm_list *new, struct pm_list *old) { struct pm_listnode *node; struct isis_nexthop *nexthop; for (PM_ALL_LIST_ELEMENTS_RO (new, node, nexthop)) { if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex)) continue; pm_listnode_add (old, nexthop); nexthop->lock++; } } static void isis_nexthops6_merge (struct pm_list *new, struct pm_list *old) { struct pm_listnode *node; struct isis_nexthop6 *nexthop6; for (PM_ALL_LIST_ELEMENTS_RO (new, node, nexthop6)) { if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex)) continue; pm_listnode_add (old, nexthop6); nexthop6->lock++; } } static void isis_route_info_merge (struct isis_route_info *new, struct isis_route_info *old, u_char family) { if (family == AF_INET) isis_nexthops_merge (new->nexthops, old->nexthops); else if (family == AF_INET6) isis_nexthops6_merge (new->nexthops6, old->nexthops6); return; } static int isis_route_info_prefer_new (struct isis_route_info *new, struct isis_route_info *old) { if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE)) return 1; if (new->cost < old->cost) return 1; return 0; } struct isis_route_info * isis_route_create (struct isis_prefix *prefix, u_int32_t cost, u_int32_t depth, struct pm_list *adjacencies, struct isis_area *area, int level) { struct route_node *route_node; struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL; u_char buff[BUFSIZ]; u_char family; family = prefix->family; /* for debugs */ isis_prefix2str (prefix, (char *) buff, BUFSIZ); rinfo_new = isis_route_info_new (cost, depth, family, adjacencies); if (!rinfo_new) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Rte (%s): isis_route_create: out of memory!\n", config.name, area->area_tag); return NULL; } if (family == AF_INET) route_node = route_node_get (area->route_table[level - 1], prefix); else if (family == AF_INET6) route_node = route_node_get (area->route_table6[level - 1], prefix); else { if (rinfo_new) free(rinfo_new); return NULL; } rinfo_old = route_node->info; if (!rinfo_old) { if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route created: %s\n", config.name, area->area_tag, area->is_type, buff); SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE); route_node->info = rinfo_new; return rinfo_new; } if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route already exists: %s\n", config.name, area->area_tag, area->is_type, buff); if (isis_route_info_same (rinfo_new, rinfo_old, family)) { if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route unchanged: %s\n", config.name, area->area_tag, area->is_type, buff); isis_route_info_delete (rinfo_new); route_info = rinfo_old; } else if (isis_route_info_same_attrib (rinfo_new, rinfo_old)) { /* merge the nexthop lists */ if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route changed (same attribs): %s\n", config.name, area->area_tag, area->is_type, buff); isis_route_info_merge (rinfo_new, rinfo_old, family); isis_route_info_delete (rinfo_new); route_info = rinfo_old; UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC); } else { if (isis_route_info_prefer_new (rinfo_new, rinfo_old)) { if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route changed: %s\n", config.name, area->area_tag, area->is_type, buff); isis_route_info_delete (rinfo_old); route_info = rinfo_new; } else { if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u) route rejected: %s\n", config.name, area->area_tag, area->is_type, buff); isis_route_info_delete (rinfo_new); route_info = rinfo_old; } } SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE); route_node->info = route_info; return route_info; } static void isis_route_delete (struct isis_prefix *prefix, struct route_table *table) { struct route_node *rode; struct isis_route_info *rinfo; char buff[BUFSIZ]; /* for log */ isis_prefix2str (prefix, buff, BUFSIZ); rode = route_node_get (table, prefix); rinfo = rode->info; if (rinfo == NULL) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte: tried to delete non-existant route: %s\n", config.name, buff); return; } isis_route_info_delete (rinfo); rode->info = NULL; return; } /* Validating routes in particular table. */ void isis_route_validate_table (struct isis_area *area, struct route_table *table) { struct route_node *rnode, *drnode; struct isis_route_info *rinfo; u_char buff[BUFSIZ]; for (rnode = route_top (table); rnode; rnode = route_next (rnode)) { if (rnode->info == NULL) continue; rinfo = rnode->info; if (config.debug) { isis_prefix2str (&rnode->p, (char *) buff, BUFSIZ); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Rte (tag: %s, level: %u): route validate: %s %s\n", config.name, area->area_tag, area->is_type, (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ? "active" : "inactive"), buff); } if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) { /* Area is either L1 or L2 => we use level route tables directly for * validating => no problems with deleting routes. */ if (area->is_type != IS_LEVEL_1_AND_2) { isis_route_delete (&rnode->p, table); continue; } /* If area is L1L2, we work with merge table and therefore must * delete node from level tables as well before deleting route info. * FIXME: Is it performance problem? There has to be the better way. * Like not to deal with it here at all (see the next comment)? */ if (rnode->p.family == AF_INET) { drnode = route_node_get (area->route_table[0], &rnode->p); if (drnode->info == rnode->info) drnode->info = NULL; drnode = route_node_get (area->route_table[1], &rnode->p); if (drnode->info == rnode->info) drnode->info = NULL; } if (rnode->p.family == AF_INET6) { drnode = route_node_get (area->route_table6[0], &rnode->p); if (drnode->info == rnode->info) drnode->info = NULL; drnode = route_node_get (area->route_table6[1], &rnode->p); if (drnode->info == rnode->info) drnode->info = NULL; } isis_route_delete (&rnode->p, table); } } } /* Function to validate route tables for L1L2 areas. In this case we can't use * level route tables directly, we have to merge them at first. L1 routes are * preferred over the L2 ones. * * Merge algorithm is trivial (at least for now). All L1 paths are copied into * merge table at first, then L2 paths are added if L1 path for same prefix * doesn't already exists there. * * FIXME: Is it right place to do it at all? Maybe we should push both levels * to the RIB with different zebra route types and let RIB handle this? */ void isis_route_validate_merge (struct isis_area *area, int family) { struct route_table *table = NULL; struct route_table *merge; struct route_node *rnode, *mrnode; merge = route_table_init (); if (family == AF_INET) table = area->route_table[0]; else if (family == AF_INET6) table = area->route_table6[0]; for (rnode = route_top (table); rnode; rnode = route_next (rnode)) { if (rnode->info == NULL) continue; mrnode = route_node_get (merge, &rnode->p); mrnode->info = rnode->info; } if (family == AF_INET) table = area->route_table[1]; else if (family == AF_INET6) table = area->route_table6[1]; for (rnode = route_top (table); rnode; rnode = route_next (rnode)) { if (rnode->info == NULL) continue; mrnode = route_node_get (merge, &rnode->p); if (mrnode->info != NULL) continue; mrnode->info = rnode->info; } isis_route_validate_table (area, merge); route_table_finish (merge); } /* Walk through route tables and propagate necessary changes into RIB. In case * of L1L2 area, level tables have to be merged at first. */ int isis_route_validate (struct thread *thread) { struct isis_area *area; area = THREAD_ARG (thread); if (area->is_type == IS_LEVEL_1) { isis_route_validate_table (area, area->route_table[0]); goto validate_ipv6; } if (area->is_type == IS_LEVEL_2) { isis_route_validate_table (area, area->route_table[1]); goto validate_ipv6; } isis_route_validate_merge (area, AF_INET); validate_ipv6: if (area->is_type == IS_LEVEL_1) { isis_route_validate_table (area, area->route_table6[0]); return ISIS_OK; } if (area->is_type == IS_LEVEL_2) { isis_route_validate_table (area, area->route_table6[1]); return ISIS_OK; } isis_route_validate_merge (area, AF_INET6); return ISIS_OK; } pmacct-1.7.8/src/isis/isis_circuit.h0000644000175000017500000001346714354105275016425 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_circuit.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_CIRCUIT_H_ #define _ISIS_CIRCUIT_H_ #define CIRCUIT_MAX 255 struct password { struct password *next; int len; u_char *pass; }; struct metric { u_char metric_default; u_char metric_error; u_char metric_expense; u_char metric_delay; }; struct isis_bcast_info { u_char snpa[ETH_ALEN]; /* SNPA of this circuit */ char run_dr_elect[2]; /* Should we run dr election ? */ struct thread *t_run_dr[2]; /* DR election thread */ struct thread *t_send_lan_hello[2]; /* send LAN IIHs in this thread */ struct pm_list *adjdb[2]; /* adjacency dbs */ struct pm_list *lan_neighs[2]; /* list of lx neigh snpa */ char is_dr[2]; /* Are we level x DR ? */ u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */ u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */ struct thread *t_refresh_pseudo_lsp[2]; /* refresh pseudo-node LSPs */ int pad_hellos; /* add padding to Hello PDUs ? */ u_char priority[2]; /* l1/2 IS Priority */ }; struct isis_p2p_info { struct isis_adjacency *neighbor; struct thread *t_send_p2p_hello; /* send P2P IIHs in this thread */ }; struct interface { char name[SRVBUFLEN]; unsigned int ifindex; unsigned int mtu; }; struct isis_circuit { int state; u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ struct isis_area *area; /* back pointer to the area */ struct interface *interface; /* interface info from z */ int fd; /* IS-IS l1/2 socket */ int sap_length; /* SAP length for DLPI */ struct nlpids nlpids; /* * Threads */ struct thread *t_read; struct thread *t_send_csnp[2]; struct thread *t_send_psnp[2]; struct pm_list *lsp_queue; /* LSPs to be txed (both levels) */ /* there is no real point in two streams, just for programming kicker */ int (*rx) (struct isis_circuit * circuit, u_char * ssnpa); struct stream *rcv_stream; /* Stream for receiving */ int (*tx) (struct isis_circuit * circuit, int level); struct stream *snd_stream; /* Stream for sending */ int idx; /* idx in S[RM|SN] flags */ #define CIRCUIT_T_BROADCAST 0 #define CIRCUIT_T_P2P 1 #define CIRCUIT_T_STATIC_IN 2 #define CIRCUIT_T_STATIC_OUT 3 #define CIRCUIT_T_DA 4 int circ_type; /* type of the physical interface */ union { struct isis_bcast_info bc; struct isis_p2p_info p2p; } u; char ext_domain; /* externalDomain (boolean) */ /* * Configurables */ struct isis_passwd passwd; /* Circuit rx/tx password */ long lsp_interval; int manual_l2_only; /* manualL2OnlyMode (boolean) */ int circuit_is_type; /* circuit is type == level of circuit * diffrenciated from circuit type (media) */ u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ struct metric metrics[2]; /* l1XxxMetric */ u_int32_t te_metric[2]; struct password *c_rx_passwds; /* circuitReceivePasswords */ struct password *c_tc_passwd; /* circuitTransmitPassword */ int ip_router; /* Route IP ? */ struct pm_list *ip_addrs; /* our IP addresses */ int ipv6_router; /* Route IPv6 ? */ struct pm_list *ipv6_link; /* our link local IPv6 addresses */ struct pm_list *ipv6_non_link; /* our non-link local IPv6 addresses */ /* * RFC 2973 IS-IS Mesh Groups */ #define MESH_INACTIVE 0 #define MESH_BLOCKED 1 #define MESH_SET 2 int mesh_enabled; /* meshGroupEnabled */ u_int16_t mesh_group; /* meshGroup */ u_int16_t upadjcount[2]; /* * Counters as in 10589--11.2.5.9 */ u_int32_t adj_state_changes; /* changesInAdjacencyState */ u_int32_t init_failures; /* intialisationFailures */ u_int32_t ctrl_pdus_rxed; /* controlPDUsReceived */ u_int32_t ctrl_pdus_txed; /* controlPDUsSent */ u_int32_t desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */ u_int32_t rej_adjacencies; /* rejectedAdjacencies */ }; struct sockaddr_ll { unsigned short int sll_family; unsigned short int sll_protocol; int sll_ifindex; unsigned short int sll_hatype; unsigned char sll_pkttype; unsigned char sll_halen; unsigned char sll_addr[8]; }; extern struct isis_circuit *isis_circuit_new (); extern void isis_circuit_del (struct isis_circuit *); extern void isis_circuit_configure (struct isis_circuit *, struct isis_area *); extern void isis_circuit_up (struct isis_circuit *); extern void isis_circuit_deconfigure (struct isis_circuit *, struct isis_area *); extern int isis_circuit_destroy (struct isis_circuit *); extern void isis_circuit_if_add (struct isis_circuit *, struct interface *); extern void isis_circuit_if_del (struct isis_circuit *); extern void circuit_update_nlpids (struct isis_circuit *); extern void isis_circuit_update_params (struct isis_circuit *, struct interface *); extern void isis_circuit_down (struct isis_circuit *circuit); #endif /* _ISIS_CIRCUIT_H_ */ pmacct-1.7.8/src/isis/isis_circuit.c0000644000175000017500000001501414354105275016406 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_circuit.c * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #ifndef ETHER_ADDR_LEN #define ETHER_ADDR_LEN ETHERADDRL #endif #include "thread.h" #include "hash.h" #include "prefix.h" #include "stream.h" #include "dict.h" #include "iso.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_constants.h" #include "isis_adjacency.h" #include "isis_flags.h" #include "isisd.h" #include "isis_csm.h" #include "isis_events.h" extern struct thread_master *master; extern struct isis *isis; /* * Prototypes. */ void isis_circuit_down(struct isis_circuit *); struct isis_circuit * isis_circuit_new () { struct isis_circuit *circuit; int i; circuit = calloc(1, sizeof (struct isis_circuit)); if (circuit) { /* set default metrics for circuit */ for (i = 0; i < 2; i++) { circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRICS; circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED; circuit->metrics[i].metric_error = METRICS_UNSUPPORTED; circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED; circuit->te_metric[i] = DEFAULT_CIRCUIT_METRICS; } } else { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Can't calloc isis circuit\n", config.name); return NULL; } return circuit; } void isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area) { int i; circuit->area = area; /* * The level for the circuit is same as for the area, unless configured * otherwise. */ circuit->circuit_is_type = area->is_type; /* * Default values */ for (i = 0; i < 2; i++) { circuit->hello_interval[i] = HELLO_INTERVAL; circuit->hello_multiplier[i] = HELLO_MULTIPLIER; circuit->csnp_interval[i] = CSNP_INTERVAL; circuit->psnp_interval[i] = PSNP_INTERVAL; circuit->u.bc.priority[i] = DEFAULT_PRIORITY; } if (circuit->circ_type == CIRCUIT_T_BROADCAST) { circuit->u.bc.adjdb[0] = pm_list_new (); circuit->u.bc.adjdb[1] = pm_list_new (); circuit->u.bc.pad_hellos = 1; } circuit->lsp_interval = LSP_INTERVAL; /* * Add the circuit into area */ pm_listnode_add (area->circuit_list, circuit); circuit->idx = flags_get_index (&area->flags); circuit->lsp_queue = pm_list_new (); return; } void isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area) { /* destroy adjacencies */ if (circuit->u.bc.adjdb[0]) isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]); if (circuit->u.bc.adjdb[1]) isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]); /* Remove circuit from area */ pm_listnode_delete (area->circuit_list, circuit); /* Free the index of SRM and SSN flags */ flags_free_index (&area->flags, circuit->idx); return; } void isis_circuit_del (struct isis_circuit *circuit) { if (!circuit) return; if (circuit->circ_type == CIRCUIT_T_BROADCAST) { /* destroy adjacency databases */ if (circuit->u.bc.adjdb[0]) pm_list_delete (circuit->u.bc.adjdb[0]); if (circuit->u.bc.adjdb[1]) pm_list_delete (circuit->u.bc.adjdb[1]); /* destroy neighbour lists */ if (circuit->u.bc.lan_neighs[0]) pm_list_delete (circuit->u.bc.lan_neighs[0]); if (circuit->u.bc.lan_neighs[1]) pm_list_delete (circuit->u.bc.lan_neighs[1]); /* destroy addresses */ } if (circuit->ip_addrs) pm_list_delete (circuit->ip_addrs); if (circuit->ipv6_link) pm_list_delete (circuit->ipv6_link); if (circuit->ipv6_non_link) pm_list_delete (circuit->ipv6_non_link); /* and lastly the circuit itself */ free(circuit); return; } void isis_circuit_up (struct isis_circuit *circuit) { if (circuit->circ_type == CIRCUIT_T_P2P) { /* initializing the hello send threads * for a ptp IF */ thread_add_event (master, send_p2p_hello, circuit, 0); } /* if needed, initialize the circuit streams (most likely not) */ if (circuit->rcv_stream == NULL) circuit->rcv_stream = stream_new (ISO_MTU (circuit)); if (circuit->snd_stream == NULL) circuit->snd_stream = stream_new (ISO_MTU (circuit)); // isis_sock_init (circuit); // THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit, circuit->fd); } void isis_circuit_down (struct isis_circuit *circuit) { /* Cancel all active threads -- FIXME: wrong place */ /* HT: Read thread if GNU_LINUX, TIMER thread otherwise. */ THREAD_OFF (circuit->t_read); if (circuit->circ_type == CIRCUIT_T_BROADCAST) { THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]); THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]); THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]); THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]); } else if (circuit->circ_type == CIRCUIT_T_P2P) { THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello); } if (circuit->t_send_psnp[0]) { THREAD_TIMER_OFF (circuit->t_send_psnp[0]); } if (circuit->t_send_psnp[1]) { THREAD_TIMER_OFF (circuit->t_send_psnp[1]); } /* close the socket */ close (circuit->fd); return; } void circuit_update_nlpids (struct isis_circuit *circuit) { circuit->nlpids.count = 0; if (circuit->ip_router) { circuit->nlpids.nlpids[0] = NLPID_IP; circuit->nlpids.count++; } if (circuit->ipv6_router) { circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6; circuit->nlpids.count++; } return; } pmacct-1.7.8/src/isis/thread.c0000644000175000017500000005704714354105275015200 0ustar paolopaolo/* Thread management routine * Copyright (C) 1998, 2000 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "thread.h" #include "hash.h" /* Recent absolute time of day */ struct timeval recent_time; static struct timeval last_recent_time; /* Relative time, since startup */ static struct timeval relative_time; static struct timeval relative_time_base; /* init flag */ static unsigned short timers_inited; static struct hash *cpu_record = NULL; /* Struct timeval's tv_usec one second value. */ #define TIMER_SECOND_MICRO 1000000L /* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO). And change negative values to 0. */ static struct timeval timeval_adjust (struct timeval a) { while (a.tv_usec >= TIMER_SECOND_MICRO) { a.tv_usec -= TIMER_SECOND_MICRO; a.tv_sec++; } while (a.tv_usec < 0) { a.tv_usec += TIMER_SECOND_MICRO; a.tv_sec--; } if (a.tv_sec < 0) /* Change negative timeouts to 0. */ a.tv_sec = a.tv_usec = 0; return a; } static struct timeval timeval_subtract (struct timeval a, struct timeval b) { struct timeval ret; ret.tv_usec = a.tv_usec - b.tv_usec; ret.tv_sec = a.tv_sec - b.tv_sec; return timeval_adjust (ret); } static long isis_timeval_cmp (struct timeval a, struct timeval b) { return (a.tv_sec == b.tv_sec ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec); } static unsigned long timeval_elapsed (struct timeval a, struct timeval b) { return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) + (a.tv_usec - b.tv_usec)); } #ifndef HAVE_CLOCK_MONOTONIC static void quagga_gettimeofday_relative_adjust (void) { struct timeval diff; if (isis_timeval_cmp (recent_time, last_recent_time) < 0) { relative_time.tv_sec++; relative_time.tv_usec = 0; } else { diff = timeval_subtract (recent_time, last_recent_time); relative_time.tv_sec += diff.tv_sec; relative_time.tv_usec += diff.tv_usec; relative_time = timeval_adjust (relative_time); } last_recent_time = recent_time; } #endif /* !HAVE_CLOCK_MONOTONIC */ /* gettimeofday wrapper, to keep recent_time updated */ static int quagga_gettimeofday (struct timeval *tv) { int ret; assert (tv); if (!(ret = gettimeofday (&recent_time, NULL))) { /* init... */ if (!timers_inited) { relative_time_base = last_recent_time = recent_time; timers_inited = 1; } /* avoid copy if user passed recent_time pointer.. */ if (tv != &recent_time) *tv = recent_time; return 0; } return ret; } static int quagga_get_relative (struct timeval *tv) { int ret; #ifdef HAVE_CLOCK_MONOTONIC { struct timespec tp; if (!(ret = clock_gettime (CLOCK_MONOTONIC, &tp))) { relative_time.tv_sec = tp.tv_sec; relative_time.tv_usec = tp.tv_nsec / 1000; } } #else /* !HAVE_CLOCK_MONOTONIC */ if (!(ret = quagga_gettimeofday (&recent_time))) quagga_gettimeofday_relative_adjust(); #endif /* HAVE_CLOCK_MONOTONIC */ if (tv) *tv = relative_time; return ret; } /* Get absolute time stamp, but in terms of the internal timer * Could be wrong, but at least won't go back. */ static void quagga_real_stabilised (struct timeval *tv) { *tv = relative_time_base; tv->tv_sec += relative_time.tv_sec; tv->tv_usec += relative_time.tv_usec; *tv = timeval_adjust (*tv); } /* Exported Quagga timestamp function. * Modelled on POSIX clock_gettime. */ int quagga_gettime (enum quagga_clkid clkid, struct timeval *tv) { switch (clkid) { case QUAGGA_CLK_REALTIME: return quagga_gettimeofday (tv); case QUAGGA_CLK_MONOTONIC: return quagga_get_relative (tv); case QUAGGA_CLK_REALTIME_STABILISED: quagga_real_stabilised (tv); return 0; default: errno = EINVAL; return -1; } } /* time_t value in terms of stabilised absolute time. * replacement for POSIX time() */ time_t quagga_time (time_t *t) { struct timeval tv; quagga_real_stabilised (&tv); if (t) *t = tv.tv_sec; return tv.tv_sec; } /* Public export of recent_relative_time by value */ struct timeval recent_relative_time (void) { return relative_time; } static unsigned int cpu_record_hash_key (struct cpu_thread_history *a) { return (uintptr_t) a->func; } static int cpu_record_hash_cmp (const struct cpu_thread_history *a, const struct cpu_thread_history *b) { return a->func == b->func; } static void * cpu_record_hash_alloc (struct cpu_thread_history *a) { struct cpu_thread_history *new; new = calloc(1, sizeof (struct cpu_thread_history)); new->func = a->func; new->funcname = strdup(a->funcname); return new; } static void cpu_record_hash_free (void *a) { struct cpu_thread_history *hist = a; free(hist->funcname); free(hist); } /* Allocate new thread master. */ struct thread_master * thread_master_create () { if (cpu_record == NULL) cpu_record = isis_hash_create_size (1011, (unsigned int (*) (void *))cpu_record_hash_key, (int (*) (const void *, const void *))cpu_record_hash_cmp); return (struct thread_master *) calloc(1, sizeof (struct thread_master)); } /* Add a new thread to the list. */ static void thread_list_add (struct thread_list *list, struct thread *thread) { thread->next = NULL; thread->prev = list->tail; if (list->tail) list->tail->next = thread; else list->head = thread; list->tail = thread; list->count++; } /* Add a new thread just before the point. */ static void thread_list_add_before (struct thread_list *list, struct thread *point, struct thread *thread) { thread->next = point; thread->prev = point->prev; if (point->prev) point->prev->next = thread; else list->head = thread; point->prev = thread; list->count++; } /* Delete a thread from the list. */ static struct thread * thread_list_delete (struct thread_list *list, struct thread *thread) { if (thread->next) thread->next->prev = thread->prev; else list->tail = thread->prev; if (thread->prev) thread->prev->next = thread->next; else list->head = thread->next; thread->next = thread->prev = NULL; list->count--; return thread; } /* Move thread to unuse list. */ static void thread_add_unuse (struct thread_master *m, struct thread *thread) { assert (m != NULL && thread != NULL); assert (thread->next == NULL); assert (thread->prev == NULL); assert (thread->type == THREAD_UNUSED); thread_list_add (&m->unuse, thread); /* XXX: Should we deallocate funcname here? */ } /* Free all unused thread. */ static void thread_list_free (struct thread_master *m, struct thread_list *list) { struct thread *t; struct thread *next; for (t = list->head; t; t = next) { next = t->next; if (t->funcname) free(t->funcname); free(t); list->count--; m->alloc--; } } /* Stop thread scheduler. */ void thread_master_free (struct thread_master *m) { thread_list_free (m, &m->read); thread_list_free (m, &m->write); thread_list_free (m, &m->timer); thread_list_free (m, &m->event); thread_list_free (m, &m->ready); thread_list_free (m, &m->unuse); thread_list_free (m, &m->background); free(m); if (cpu_record) { isis_hash_clean (cpu_record, cpu_record_hash_free); isis_hash_free (cpu_record); cpu_record = NULL; } } /* Thread list is empty or not. */ static inline int thread_empty (struct thread_list *list) { return list->head ? 0 : 1; } /* Delete top of the list and return it. */ static struct thread * thread_trim_head (struct thread_list *list) { if (!thread_empty (list)) return thread_list_delete (list, list->head); return NULL; } /* Return remain time in second. */ unsigned long thread_timer_remain_second (struct thread *thread) { quagga_get_relative (NULL); if (thread->u.sands.tv_sec - relative_time.tv_sec > 0) return thread->u.sands.tv_sec - relative_time.tv_sec; else return 0; } /* Trim blankspace and "()"s */ static char * strip_funcname (const char *funcname) { char buff[100]; char tmp, *ret, *e, *b = buff; strncpy(buff, funcname, sizeof(buff)); buff[ sizeof(buff) -1] = '\0'; e = buff +strlen(buff) -1; /* Wont work for funcname == "Word (explanation)" */ while (*b == ' ' || *b == '(') ++b; while (*e == ' ' || *e == ')') --e; e++; tmp = *e; *e = '\0'; ret = strdup(b); *e = tmp; return ret; } /* Get new thread. */ static struct thread * thread_get (struct thread_master *m, u_char type, int (*func) (struct thread *), void *arg, const char* funcname) { struct thread *thread; if (!thread_empty (&m->unuse)) { thread = thread_trim_head (&m->unuse); if (thread->funcname) free(thread->funcname); } else { thread = calloc(1, sizeof (struct thread)); m->alloc++; } thread->type = type; thread->add_type = type; thread->master = m; thread->func = func; thread->arg = arg; thread->funcname = strip_funcname(funcname); return thread; } /* Add new read thread. */ struct thread * funcname_thread_add_read (struct thread_master *m, int (*func) (struct thread *), void *arg, int fd, const char* funcname) { struct thread *thread; assert (m != NULL); if (FD_ISSET (fd, &m->readfd)) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): There is already read fd [%d]\n", config.name, fd); return NULL; } thread = thread_get (m, THREAD_READ, func, arg, funcname); FD_SET (fd, &m->readfd); thread->u.fd = fd; thread_list_add (&m->read, thread); return thread; } /* Add new write thread. */ struct thread * funcname_thread_add_write (struct thread_master *m, int (*func) (struct thread *), void *arg, int fd, const char* funcname) { struct thread *thread; assert (m != NULL); if (FD_ISSET (fd, &m->writefd)) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): There is already write fd [%d]\n", config.name, fd); return NULL; } thread = thread_get (m, THREAD_WRITE, func, arg, funcname); FD_SET (fd, &m->writefd); thread->u.fd = fd; thread_list_add (&m->write, thread); return thread; } static struct thread * funcname_thread_add_timer_timeval (struct thread_master *m, int (*func) (struct thread *), int type, void *arg, struct timeval *time_relative, const char* funcname) { struct thread *thread; struct thread_list *list; struct timeval alarm_time; struct thread *tt; assert (m != NULL); assert (type == THREAD_TIMER || type == THREAD_BACKGROUND); assert (time_relative); list = ((type == THREAD_TIMER) ? &m->timer : &m->background); thread = thread_get (m, type, func, arg, funcname); /* Do we need jitter here? */ quagga_get_relative (NULL); alarm_time.tv_sec = relative_time.tv_sec + time_relative->tv_sec; alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec; thread->u.sands = timeval_adjust(alarm_time); /* Sort by timeval. */ for (tt = list->head; tt; tt = tt->next) if (isis_timeval_cmp (thread->u.sands, tt->u.sands) <= 0) break; if (tt) thread_list_add_before (list, tt, thread); else thread_list_add (list, thread); return thread; } /* Add timer event thread. */ struct thread * funcname_thread_add_timer (struct thread_master *m, int (*func) (struct thread *), void *arg, long timer, const char* funcname) { struct timeval trel; assert (m != NULL); trel.tv_sec = timer; trel.tv_usec = 0; return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, funcname); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_msec (struct thread_master *m, int (*func) (struct thread *), void *arg, long timer, const char* funcname) { struct timeval trel; assert (m != NULL); trel.tv_sec = timer / 1000; trel.tv_usec = 1000*(timer % 1000); return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, funcname); } /* Add a background thread, with an optional millisec delay */ struct thread * funcname_thread_add_background (struct thread_master *m, int (*func) (struct thread *), void *arg, long delay, const char *funcname) { struct timeval trel; assert (m != NULL); if (delay) { trel.tv_sec = delay / 1000; trel.tv_usec = 1000*(delay % 1000); } else { trel.tv_sec = 0; trel.tv_usec = 0; } return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, arg, &trel, funcname); } /* Add simple event thread. */ struct thread * funcname_thread_add_event (struct thread_master *m, int (*func) (struct thread *), void *arg, int val, const char* funcname) { struct thread *thread; assert (m != NULL); thread = thread_get (m, THREAD_EVENT, func, arg, funcname); thread->u.val = val; thread_list_add (&m->event, thread); return thread; } /* Cancel thread from scheduler. */ void thread_cancel (struct thread *thread) { struct thread_list *list; switch (thread->type) { case THREAD_READ: assert (FD_ISSET (thread->u.fd, &thread->master->readfd)); FD_CLR (thread->u.fd, &thread->master->readfd); list = &thread->master->read; break; case THREAD_WRITE: assert (FD_ISSET (thread->u.fd, &thread->master->writefd)); FD_CLR (thread->u.fd, &thread->master->writefd); list = &thread->master->write; break; case THREAD_TIMER: list = &thread->master->timer; break; case THREAD_EVENT: list = &thread->master->event; break; case THREAD_READY: list = &thread->master->ready; break; case THREAD_BACKGROUND: list = &thread->master->background; break; default: return; break; } thread_list_delete (list, thread); thread->type = THREAD_UNUSED; thread_add_unuse (thread->master, thread); } /* Delete all events which has argument value arg. */ unsigned int thread_cancel_event (struct thread_master *m, void *arg) { unsigned int ret = 0; struct thread *thread; thread = m->event.head; while (thread) { struct thread *t; t = thread; thread = t->next; if (t->arg == arg) { ret++; thread_list_delete (&m->event, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } return ret; } static struct timeval * thread_timer_wait (struct thread_list *tlist, struct timeval *timer_val) { if (!thread_empty (tlist)) { *timer_val = timeval_subtract (tlist->head->u.sands, relative_time); return timer_val; } return NULL; } static struct thread * thread_run (struct thread_master *m, struct thread *thread, struct thread *fetch) { *fetch = *thread; thread->type = THREAD_UNUSED; thread->funcname = NULL; /* thread_call will free fetch's copied pointer */ thread_add_unuse (m, thread); return fetch; } static int thread_process_fd (struct thread_list *list, fd_set *fdset, fd_set *mfdset) { struct thread *thread; struct thread *next; int ready = 0; assert (list); for (thread = list->head; thread; thread = next) { next = thread->next; if (FD_ISSET (THREAD_FD (thread), fdset)) { assert (FD_ISSET (THREAD_FD (thread), mfdset)); FD_CLR(THREAD_FD (thread), mfdset); thread_list_delete (list, thread); thread_list_add (&thread->master->ready, thread); thread->type = THREAD_READY; ready++; } } return ready; } /* Add all timers that have popped to the ready list. */ static unsigned int thread_timer_process (struct thread_list *list, struct timeval *timenow) { struct thread *thread; unsigned int ready = 0; for (thread = list->head; thread; thread = thread->next) { if (isis_timeval_cmp (*timenow, thread->u.sands) < 0) return ready; thread_list_delete (list, thread); thread->type = THREAD_READY; thread_list_add (&thread->master->ready, thread); ready++; } return ready; } /* process a list en masse, e.g. for event thread lists */ static unsigned int thread_process (struct thread_list *list) { struct thread *thread; unsigned int ready = 0; for (thread = list->head; thread; thread = thread->next) { thread_list_delete (list, thread); thread->type = THREAD_READY; thread_list_add (&thread->master->ready, thread); ready++; } return ready; } /* Fetch next ready thread. */ struct thread * thread_fetch (struct thread_master *m, struct thread *fetch) { struct thread *thread; fd_set readfd; fd_set writefd; fd_set exceptfd; struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 }; struct timeval timer_val_bg; struct timeval *timer_wait = &timer_val; struct timeval *timer_wait_bg; while (1) { int num = 0; /* Signals pre-empt everything */ // quagga_sigevent_process (); /* Drain the ready queue of already scheduled jobs, before scheduling * more. */ if ((thread = thread_trim_head (&m->ready)) != NULL) return thread_run (m, thread, fetch); /* To be fair to all kinds of threads, and avoid starvation, we * need to be careful to consider all thread types for scheduling * in each quanta. I.e. we should not return early from here on. */ /* Normal event are the next highest priority. */ thread_process (&m->event); /* Structure copy. */ readfd = m->readfd; writefd = m->writefd; exceptfd = m->exceptfd; /* Calculate select wait timer if nothing else to do */ if (m->ready.count == 0) { quagga_get_relative (NULL); timer_wait = thread_timer_wait (&m->timer, &timer_val); timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg); if (timer_wait_bg && (!timer_wait || (isis_timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) timer_wait = timer_wait_bg; } num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait); /* Signals should get quick treatment */ if (num < 0) { if (errno == EINTR) continue; /* signal received - process it */ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): select() error: %s\n", config.name, strerror (errno)); return NULL; } /* Check foreground timers. Historically, they have had higher priority than I/O threads, so let's push them onto the ready list in front of the I/O threads. */ quagga_get_relative (NULL); thread_timer_process (&m->timer, &relative_time); /* Got IO, process it */ if (num > 0) { /* Normal priority read thead. */ thread_process_fd (&m->read, &readfd, &m->readfd); /* Write thead. */ thread_process_fd (&m->write, &writefd, &m->writefd); } #if 0 /* If any threads were made ready above (I/O or foreground timer), perhaps we should avoid adding background timers to the ready list at this time. If this is code is uncommented, then background timer threads will not run unless there is nothing else to do. */ if ((thread = thread_trim_head (&m->ready)) != NULL) return thread_run (m, thread, fetch); #endif /* Background timer/events, lowest priority */ thread_timer_process (&m->background, &relative_time); if ((thread = thread_trim_head (&m->ready)) != NULL) return thread_run (m, thread, fetch); } } unsigned long thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) { *cputime = 0; return timeval_elapsed (now->real, start->real); } /* We should aim to yield after THREAD_YIELD_TIME_SLOT milliseconds. Note: we are using real (wall clock) time for this calculation. It could be argued that CPU time may make more sense in certain contexts. The things to consider are whether the thread may have blocked (in which case wall time increases, but CPU time does not), or whether the system is heavily loaded with other processes competing for CPU time. On balance, wall clock time seems to make sense. Plus it has the added benefit that gettimeofday should be faster than calling getrusage. */ int thread_should_yield (struct thread *thread) { quagga_get_relative (NULL); return (timeval_elapsed(relative_time, thread->ru.real) > THREAD_YIELD_TIME_SLOT); } void thread_getrusage (RUSAGE_T *r) { quagga_get_relative (NULL); r->real = relative_time; #ifdef HAVE_CLOCK_MONOTONIC /* quagga_get_relative() only updates recent_time if gettimeofday * based, not when using CLOCK_MONOTONIC. As we export recent_time * and guarantee to update it before threads are run... */ quagga_gettimeofday(&recent_time); #endif /* HAVE_CLOCK_MONOTONIC */ } /* We check thread consumed time. If the system has getrusage, we'll use that to get in-depth stats on the performance of the thread in addition to wall clock time stats from gettimeofday. */ void thread_call (struct thread *thread) { unsigned long realtime, cputime; RUSAGE_T ru; /* Cache a pointer to the relevant cpu history thread, if the thread * does not have it yet. * * Callers submitting 'dummy threads' hence must take care that * thread->cpu is NULL */ if (!thread->hist) { struct cpu_thread_history tmp; tmp.func = thread->func; tmp.funcname = thread->funcname; thread->hist = isis_hash_get (cpu_record, &tmp, (void * (*) (void *))cpu_record_hash_alloc); } GETRUSAGE (&thread->ru); (*thread->func) (thread); GETRUSAGE (&ru); realtime = thread_consumed_time (&ru, &thread->ru, &cputime); thread->hist->real.total += realtime; if (thread->hist->real.max < realtime) thread->hist->real.max = realtime; ++(thread->hist->total_calls); thread->hist->types |= (1 << thread->add_type); free(thread->funcname); } /* Execute thread */ struct thread * funcname_thread_execute (struct thread_master *m, int (*func)(struct thread *), void *arg, int val, const char* funcname) { struct thread dummy; memset (&dummy, 0, sizeof (struct thread)); dummy.type = THREAD_EVENT; dummy.add_type = THREAD_EXECUTE; dummy.master = NULL; dummy.func = func; dummy.arg = arg; dummy.u.val = val; dummy.funcname = strip_funcname (funcname); thread_call (&dummy); free(dummy.funcname); return NULL; } pmacct-1.7.8/src/isis/isis_constants.h0000644000175000017500000001024114354105275016762 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_constants.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_CONSTANTS_H_ #define _ISIS_CONSTANTS_H_ /* * Architectural constant values from p. 35 of ISO/IEC 10589 */ #define MAX_LINK_METRIC 63 #define MAX_PATH_METRIC 1023 #define ISO_SAP 0xFE #define INTRADOMAIN_ROUTEING_SELECTOR 0 #define SEQUENCE_MODULUS 4294967296 #define RECEIVE_LSP_BUFFER_SIZE 1492 /* * implementation specific jitter values */ #define IIH_JITTER 25 /* % */ #define MAX_AGE_JITTER 5 /* % */ #define MAX_LSP_GEN_JITTER 5 /* % */ #define CSNP_JITTER 10 /* % */ #define PSNP_JITTER 10 /* % */ #define RANDOM_SPREAD 100000.0 /* * Default values * ISO - 10589 * Section 7.3.21 - Parameters */ #define MAX_AGE 1200 #define ZERO_AGE_LIFETIME 60 #define MAX_LSP_GEN_INTERVAL 900 #define MIN_LSP_GEN_INTERVAL 30 #define MIN_LSP_TRANS_INTERVAL 5 #define ISIS_MIN_LSP_LIFETIME 380 #define CSNP_INTERVAL 10 #define PSNP_INTERVAL 2 #define ISIS_MAX_PATH_SPLITS 3 #define ISIS_LEVELS 2 #define ISIS_LEVEL1 1 #define ISIS_LEVEL2 2 #define HELLO_INTERVAL 10 #define HELLO_MINIMAL HELLO_INTERVAL #define HELLO_MULTIPLIER 3 #define DEFAULT_PRIORITY 64 /* different vendors implement different values 5-10 on average */ #define LSP_GEN_INTERVAL_DEFAULT 10 #define LSP_INTERVAL 33 /* msecs */ #define DEFAULT_CIRCUIT_METRICS 10 #define METRICS_UNSUPPORTED 0x80 #define PERIODIC_SPF_INTERVAL 60 /* at the top of my head */ #define MINIMUM_SPF_INTERVAL 5 /* .. same here */ /* * NLPID values */ #define NLPID_IP 204 #define NLPID_IPV6 142 #define NLPID_SNAP 128 #define NLPID_CLNP 129 #define NLPID_ESIS 130 /* * Return values for functions */ #define ISIS_OK 0 #define ISIS_WARNING 1 #define ISIS_ERROR 2 #define ISIS_CRITICAL 3 /* * IS-IS Circuit Types */ #define IS_LEVEL_1 1 #define IS_LEVEL_2 2 #define IS_LEVEL_1_AND_2 3 #define SNPA_ADDRSTRLEN 18 #define ISIS_SYS_ID_LEN 6 #define SYSID_STRLEN 24 /* * LSP bit masks */ #define LSPBIT_P 0x80 #define LSPBIT_ATT 0x78 #define LSPBIT_OL 0x04 #define LSPBIT_IST 0x03 /* * LSP bit masking macros * taken from tcpdumps * print-isoclns.c */ #define ISIS_MASK_LSP_OL_BIT(x) ((x)&0x4) #define ISIS_MASK_LSP_IS_L1_BIT(x) ((x)&0x1) #define ISIS_MASK_LSP_IS_L2_BIT(x) ((x)&0x2) #define ISIS_MASK_LSP_PARTITION_BIT(x) ((x)&0x80) #define ISIS_MASK_LSP_ATT_BITS(x) ((x)&0x78) #define ISIS_MASK_LSP_ATT_ERROR_BIT(x) ((x)&0x40) #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) ((x)&0x20) #define ISIS_MASK_LSP_ATT_DELAY_BIT(x) ((x)&0x10) #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) ((x)&0x8) #define LLC_LEN 3 /* we need to be aware of the fact we are using ISO sized * packets, using isomtu = mtu - LLC_LEN */ #define ISO_MTU(C) \ (C->circ_type==CIRCUIT_T_BROADCAST) ? \ (C->interface->mtu - LLC_LEN) : (C->interface->mtu) #ifndef ETH_ALEN #define ETH_ALEN 6 #endif #endif /* _ISIS_CONSTANTS_H_ */ pmacct-1.7.8/src/isis/prefix.h0000644000175000017500000001214114354105275015215 0ustar paolopaolo/* * Prefix structure. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _PREFIX_H_ #define _PREFIX_H_ #include "sockunion.h" /* * A struct prefix contains an address family, a prefix length, and an * address. This can represent either a 'network prefix' as defined * by CIDR, where the 'host bits' of the prefix are 0 * (e.g. AF_INET:10.0.0.0/8), or an address and netmask * (e.g. AF_INET:10.0.0.9/8), such as might be configured on an * interface. */ /* IPv4 and IPv6 unified prefix structure. */ struct isis_prefix { u_char family; u_char prefixlen; union { u_char prefix; struct in_addr prefix4; struct in6_addr prefix6; u_char val[8]; } u __attribute__ ((aligned (8))); struct in_addr adv_router; }; #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif /* INET_ADDRSTRLEN */ #ifndef INET6_ADDRSTRLEN #define INET6_ADDRSTRLEN 46 #endif /* INET6_ADDRSTRLEN */ #ifndef INET6_BUFSIZ #define INET6_BUFSIZ 51 #endif /* INET6_BUFSIZ */ /* Max bit/byte length of IPv4 address. */ #define IPV4_MAX_BYTELEN 4 #define IPV4_MAX_BITLEN 32 #define IPV4_MAX_PREFIXLEN 32 #define IPV4_ADDR_CMP(D,S) memcmp ((D), (S), IPV4_MAX_BYTELEN) #define IPV4_ADDR_SAME(D,S) (memcmp ((D), (S), IPV4_MAX_BYTELEN) == 0) #define IPV4_ADDR_COPY(D,S) memcpy ((D), (S), IPV4_MAX_BYTELEN) #define IPV4_NET0(a) ((((u_int32_t) (a)) & 0xff000000) == 0x00000000) #define IPV4_NET127(a) ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000) #define IPV4_LINKLOCAL(a) ((((u_int32_t) (a)) & 0xffff0000) == 0xa9fe0000) /* Max bit/byte length of IPv6 address. */ #define IPV6_MAX_BYTELEN 16 #define IPV6_MAX_BITLEN 128 #define IPV6_MAX_PREFIXLEN 128 #define IPV6_ADDR_CMP(D,S) memcmp ((D), (S), IPV6_MAX_BYTELEN) #define IPV6_ADDR_SAME(D,S) (memcmp ((D), (S), IPV6_MAX_BYTELEN) == 0) #define IPV6_ADDR_COPY(D,S) memcpy ((D), (S), IPV6_MAX_BYTELEN) /* Count prefix size from mask length */ #define PSIZE(a) (((a) + 7) / (8)) /* Prefix's family member. */ #define PREFIX_FAMILY(p) ((p)->family) /* Check bit of the prefix. */ static inline unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen) { unsigned int offset = prefixlen / 8; unsigned int shift = 7 - (prefixlen % 8); return (prefix[offset] >> shift) & 1; } static inline unsigned int prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen) { return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen); } #define PREFIX_COPY_IPV4(DST, SRC) \ *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC)); #define PREFIX_COPY_IPV6(DST, SRC) \ *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC)); /* Prototypes. */ extern struct isis_prefix *isis_prefix_new (void); extern void isis_prefix_free (struct isis_prefix *); extern const char *isis_prefix_family_str (const struct isis_prefix *); extern int isis_prefix_blen (const struct isis_prefix *); extern int isis_str2prefix (const char *, struct isis_prefix *); extern int isis_prefix2str (const struct isis_prefix *, char *, int); extern int isis_prefix_match (const struct isis_prefix *, const struct isis_prefix *); extern int isis_prefix_same (const struct isis_prefix *, const struct isis_prefix *); extern int isis_prefix_cmp (const struct isis_prefix *, const struct isis_prefix *); extern void isis_prefix_copy (struct isis_prefix *, const struct isis_prefix *); extern void isis_apply_mask (struct isis_prefix *); extern struct isis_prefix *sockunion2prefix (const union sockunion *, const union sockunion *); extern struct isis_prefix *sockunion2hostprefix (const union sockunion *); extern struct prefix_ipv4 *isis_prefix_ipv4_new (void); extern int isis_str2prefix_ipv4 (const char *, struct prefix_ipv4 *); extern void isis_apply_mask_ipv4 (struct prefix_ipv4 *); extern u_char isis_ip_masklen (struct in_addr); extern void isis_masklen2ip (int, struct in_addr *); extern int netmask_isis_str2prefix_str (const char *, const char *, char *); extern struct prefix_ipv6 *prefix_ipv6_new (void); extern void isis_prefix_ipv6_free (struct prefix_ipv6 *); extern int isis_str2prefix_ipv6 (const char *, struct prefix_ipv6 *); extern void isis_apply_mask_ipv6 (struct prefix_ipv6 *); extern int isis_ip6_masklen (struct in6_addr); extern void isis_masklen2ip6 (int, struct in6_addr *); extern void isis_str2in6_addr (const char *, struct in6_addr *); extern const char *isis_inet6_ntoa (struct in6_addr); #endif /* _PREFIX_H_ */ pmacct-1.7.8/src/isis/isis_adjacency.c0000644000175000017500000001303114354105275016662 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_adjacency.c * handling of IS-IS adjacencies * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "hash.h" #include "dict.h" #include "thread.h" #include "isis_constants.h" #include "isis_common.h" #include "isisd.h" #include "isis_circuit.h" #include "isis_adjacency.h" #include "isis_misc.h" #include "isis_dynhn.h" #include "isis_pdu.h" extern struct isis *isis; static struct isis_adjacency * adj_alloc (u_char * id) { struct isis_adjacency *adj; adj = calloc(1, sizeof (struct isis_adjacency)); memcpy (adj->sysid, id, ISIS_SYS_ID_LEN); return adj; } struct isis_adjacency * isis_new_adj (u_char * id, u_char * snpa, int level, struct isis_circuit *circuit) { struct isis_adjacency *adj; adj = adj_alloc (id); /* P2P kludge */ if (adj == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): isis_new_adj() out of memory!\n", config.name); return NULL; } if (snpa) { memcpy (adj->snpa, snpa, 6); } else { memset (adj->snpa, ' ', 6); } adj->circuit = circuit; adj->level = level; adj->flaps = 0; adj->last_flap = time (NULL); return adj; } struct isis_adjacency * isis_adj_lookup (u_char * sysid, struct pm_list *adjdb) { struct isis_adjacency *adj; struct pm_listnode *node; for (PM_ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) return adj; return NULL; } struct isis_adjacency * isis_adj_lookup_snpa (u_char * ssnpa, struct pm_list *adjdb) { struct pm_listnode *node; struct isis_adjacency *adj; for (PM_ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0) return adj; return NULL; } void isis_delete_adj (struct isis_adjacency *adj, struct pm_list *adjdb) { if (!adj) return; /* When we recieve a NULL list, we will know its p2p. */ if (adjdb) pm_listnode_delete (adjdb, adj); memset(&adj->expire, 0, sizeof(struct timeval)); if (adj->ipv4_addrs) pm_list_delete (adj->ipv4_addrs); if (adj->ipv6_addrs) pm_list_delete (adj->ipv6_addrs); free(adj); return; } void isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, const char *reason) { int old_state; struct isis_circuit *circuit; old_state = adj->adj_state; adj->adj_state = state; circuit = adj->circuit; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Adj (%s): Adjacency state change %d->%d: %s\n", config.name, circuit->area->area_tag, old_state, state, reason ? reason : "unspecified"); if (state == ISIS_ADJ_UP) { /* update counter & timers for debugging purposes */ adj->last_flap = time (NULL); adj->flaps++; /* 7.3.17 - going up on P2P -> send CSNP */ send_csnp (circuit, 1); send_csnp (circuit, 2); } else if (state == ISIS_ADJ_DOWN) { /* p2p interface */ adj->circuit->u.p2p.neighbor = NULL; isis_delete_adj (adj, NULL); } return; } int isis_adj_expire (struct isis_adjacency *adj) { /* * Get the adjacency */ assert (adj); memset(&adj->expire, 0, sizeof(struct timeval)); /* trigger the adj expire event */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired"); return 0; } void isis_adjdb_iterate (struct pm_list *adjdb, void (*func) (struct isis_adjacency *, void *), void *arg) { struct pm_listnode *node, *nnode; struct isis_adjacency *adj; for (PM_ALL_LIST_ELEMENTS (adjdb, node, nnode, adj)) (*func) (adj, arg); } void isis_adj_build_neigh_list (struct pm_list *adjdb, struct pm_list *list) { struct isis_adjacency *adj; struct pm_listnode *node; if (!list) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_adj_build_neigh_list(): NULL list\n", config.name); return; } for (PM_ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) { if (!adj) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_adj_build_neigh_list(): NULL adj\n", config.name); return; } if ((adj->adj_state == ISIS_ADJ_UP || adj->adj_state == ISIS_ADJ_INITIALIZING)) pm_listnode_add (list, adj->snpa); } return; } void isis_adj_build_up_list (struct pm_list *adjdb, struct pm_list *list) { struct isis_adjacency *adj; struct pm_listnode *node; if (!list) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_adj_build_up_list(): NULL list\n", config.name); return; } for (PM_ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) { if (!adj) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_adj_build_up_list(): NULL adj\n", config.name); return; } if (adj->adj_state == ISIS_ADJ_UP) pm_listnode_add (list, adj); } return; } pmacct-1.7.8/src/isis/stream.c0000644000175000017500000004416714354105275015223 0ustar paolopaolo /* * Packet interface * Copyright (C) 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "stream.h" #include "prefix.h" /* Tests whether a position is valid */ #define GETP_VALID(S,G) \ ((G) <= (S)->endp) #define PUT_AT_VALID(S,G) GETP_VALID(S,G) #define ENDP_VALID(S,E) \ ((E) <= (S)->size) /* asserting sanity checks. Following must be true before * stream functions are called: * * Following must always be true of stream elements * before and after calls to stream functions: * * getp <= endp <= size * * Note that after a stream function is called following may be true: * if (getp == endp) then stream is no longer readable * if (endp == size) then stream is no longer writeable * * It is valid to put to anywhere within the size of the stream, but only * using stream_put..._at() functions. */ #define STREAM_WARN_OFFSETS(S) \ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): &(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \ config.name, (S), \ (unsigned long) (S)->size, \ (unsigned long) (S)->getp, \ (unsigned long) (S)->endp)\ #define STREAM_VERIFY_SANE(S) \ do { \ if ( !(GETP_VALID(S, (S)->getp)) && ENDP_VALID(S, (S)->endp) ) \ STREAM_WARN_OFFSETS(S); \ assert ( GETP_VALID(S, (S)->getp) ); \ assert ( ENDP_VALID(S, (S)->endp) ); \ } while (0) #define STREAM_BOUND_WARN(S, WHAT) \ do { \ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): %s: Attempt to %s out of bounds", config.name, \ __func__, (WHAT)); \ STREAM_WARN_OFFSETS(S); \ assert (0); \ } while (0) /* XXX: Deprecated macro: do not use */ #define CHECK_SIZE(S, Z) \ do { \ if (((S)->endp + (Z)) > (S)->size) \ { \ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): CHECK_SIZE: truncating requested size %lu\n", \ config.name, (unsigned long) (Z)); \ STREAM_WARN_OFFSETS(S); \ (Z) = (S)->size - (S)->endp; \ } \ } while (0); /* Make stream buffer. */ struct stream * stream_new (size_t size) { struct stream *s; assert (size > 0); if (size == 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): stream_new(): called with 0 size!\n", config.name); return NULL; } s = calloc(1, sizeof (struct stream)); if (s == NULL) return s; if ( (s->data = calloc(1, size)) == NULL) { free(s); return NULL; } s->size = size; return s; } /* Free it now. */ void stream_free (struct stream *s) { if (!s) return; free(s->data); free(s); } struct stream * stream_copy (struct stream *new, struct stream *src) { STREAM_VERIFY_SANE (src); assert (new != NULL); assert (STREAM_SIZE(new) >= src->endp); new->endp = src->endp; new->getp = src->getp; memcpy (new->data, src->data, src->endp); return new; } struct stream * stream_dup (struct stream *s) { struct stream *new; STREAM_VERIFY_SANE (s); if ( (new = stream_new (s->endp)) == NULL) return NULL; return (stream_copy (new, s)); } size_t stream_resize (struct stream *s, size_t newsize) { u_char *newdata; STREAM_VERIFY_SANE (s); newdata = realloc(s->data, newsize); if (newdata == NULL) return s->size; s->data = newdata; s->size = newsize; if (s->endp > s->size) s->endp = s->size; if (s->getp > s->endp) s->getp = s->endp; STREAM_VERIFY_SANE (s); return s->size; } size_t stream_get_getp (struct stream *s) { STREAM_VERIFY_SANE(s); return s->getp; } size_t stream_get_endp (struct stream *s) { STREAM_VERIFY_SANE(s); return s->endp; } size_t stream_get_size (struct stream *s) { STREAM_VERIFY_SANE(s); return s->size; } /* Stream structre' stream pointer related functions. */ void stream_set_getp (struct stream *s, size_t pos) { STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, pos)) { STREAM_BOUND_WARN (s, "set getp"); pos = s->endp; } s->getp = pos; } /* Forward pointer. */ void stream_forward_getp (struct stream *s, size_t size) { STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, s->getp + size)) { STREAM_BOUND_WARN (s, "seek getp"); return; } s->getp += size; } void stream_forward_endp (struct stream *s, size_t size) { STREAM_VERIFY_SANE(s); if (!ENDP_VALID (s, s->endp + size)) { STREAM_BOUND_WARN (s, "seek endp"); return; } s->endp += size; } /* Copy from stream to destination. */ void stream_get (void *dst, struct stream *s, size_t size) { STREAM_VERIFY_SANE(s); if (STREAM_READABLE(s) < size) { STREAM_BOUND_WARN (s, "get"); return; } memcpy (dst, s->data + s->getp, size); s->getp += size; } /* Get next character from the stream. */ u_char stream_getc (struct stream *s) { u_char c; STREAM_VERIFY_SANE (s); if (STREAM_READABLE(s) < sizeof (u_char)) { STREAM_BOUND_WARN (s, "get char"); return 0; } c = s->data[s->getp++]; return c; } /* Get next character from the stream. */ u_char stream_getc_from (struct stream *s, size_t from) { u_char c; STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, from + sizeof (u_char))) { STREAM_BOUND_WARN (s, "get char"); return 0; } c = s->data[from]; return c; } /* Get next word from the stream. */ u_int16_t stream_getw (struct stream *s) { u_int16_t w; STREAM_VERIFY_SANE (s); if (STREAM_READABLE (s) < sizeof (u_int16_t)) { STREAM_BOUND_WARN (s, "get "); return 0; } w = s->data[s->getp++] << 8; w |= s->data[s->getp++]; return w; } /* Get next word from the stream. */ u_int16_t stream_getw_from (struct stream *s, size_t from) { u_int16_t w; STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, from + sizeof (u_int16_t))) { STREAM_BOUND_WARN (s, "get "); return 0; } w = s->data[from++] << 8; w |= s->data[from]; return w; } /* Get next long word from the stream. */ u_int32_t stream_getl_from (struct stream *s, size_t from) { u_int32_t l; STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, from + sizeof (u_int32_t))) { STREAM_BOUND_WARN (s, "get long"); return 0; } l = s->data[from++] << 24; l |= s->data[from++] << 16; l |= s->data[from++] << 8; l |= s->data[from]; return l; } u_int32_t stream_getl (struct stream *s) { u_int32_t l; STREAM_VERIFY_SANE(s); if (STREAM_READABLE (s) < sizeof (u_int32_t)) { STREAM_BOUND_WARN (s, "get long"); return 0; } l = s->data[s->getp++] << 24; l |= s->data[s->getp++] << 16; l |= s->data[s->getp++] << 8; l |= s->data[s->getp++]; return l; } /* Get next quad word from the stream. */ uint64_t stream_getq_from (struct stream *s, size_t from) { uint64_t q; STREAM_VERIFY_SANE(s); if (!GETP_VALID (s, from + sizeof (uint64_t))) { STREAM_BOUND_WARN (s, "get quad"); return 0; } q = ((uint64_t) s->data[from++]) << 56; q |= ((uint64_t) s->data[from++]) << 48; q |= ((uint64_t) s->data[from++]) << 40; q |= ((uint64_t) s->data[from++]) << 32; q |= ((uint64_t) s->data[from++]) << 24; q |= ((uint64_t) s->data[from++]) << 16; q |= ((uint64_t) s->data[from++]) << 8; q |= ((uint64_t) s->data[from++]); return q; } uint64_t stream_getq (struct stream *s) { uint64_t q; STREAM_VERIFY_SANE(s); if (STREAM_READABLE (s) < sizeof (uint64_t)) { STREAM_BOUND_WARN (s, "get quad"); return 0; } q = ((uint64_t) s->data[s->getp++]) << 56; q |= ((uint64_t) s->data[s->getp++]) << 48; q |= ((uint64_t) s->data[s->getp++]) << 40; q |= ((uint64_t) s->data[s->getp++]) << 32; q |= ((uint64_t) s->data[s->getp++]) << 24; q |= ((uint64_t) s->data[s->getp++]) << 16; q |= ((uint64_t) s->data[s->getp++]) << 8; q |= ((uint64_t) s->data[s->getp++]); return q; } /* Get next long word from the stream. */ u_int32_t stream_get_ipv4 (struct stream *s) { u_int32_t l; STREAM_VERIFY_SANE(s); if (STREAM_READABLE (s) < sizeof(u_int32_t)) { STREAM_BOUND_WARN (s, "get ipv4"); return 0; } memcpy (&l, s->data + s->getp, sizeof(u_int32_t)); s->getp += sizeof(u_int32_t); return l; } /* Copy to source to stream. * * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap * around. This should be fixed once the stream updates are working. * * stream_write() is saner */ void stream_put (struct stream *s, const void *src, size_t size) { /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ CHECK_SIZE(s, size); STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); return; } if (src) memcpy (s->data + s->endp, src, size); else memset (s->data + s->endp, 0, size); s->endp += size; } /* Put character to the stream. */ int stream_putc (struct stream *s, u_char c) { STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < sizeof(u_char)) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[s->endp++] = c; return sizeof (u_char); } /* Put word to the stream. */ int stream_putw (struct stream *s, u_int16_t w) { STREAM_VERIFY_SANE (s); if (STREAM_WRITEABLE (s) < sizeof (u_int16_t)) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[s->endp++] = (u_char)(w >> 8); s->data[s->endp++] = (u_char) w; return 2; } /* Put long word to the stream. */ int stream_putl (struct stream *s, u_int32_t l) { STREAM_VERIFY_SANE (s); if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[s->endp++] = (u_char)(l >> 24); s->data[s->endp++] = (u_char)(l >> 16); s->data[s->endp++] = (u_char)(l >> 8); s->data[s->endp++] = (u_char)l; return 4; } /* Put quad word to the stream. */ int stream_putq (struct stream *s, uint64_t q) { STREAM_VERIFY_SANE (s); if (STREAM_WRITEABLE (s) < sizeof (uint64_t)) { STREAM_BOUND_WARN (s, "put quad"); return 0; } s->data[s->endp++] = (u_char)(q >> 56); s->data[s->endp++] = (u_char)(q >> 48); s->data[s->endp++] = (u_char)(q >> 40); s->data[s->endp++] = (u_char)(q >> 32); s->data[s->endp++] = (u_char)(q >> 24); s->data[s->endp++] = (u_char)(q >> 16); s->data[s->endp++] = (u_char)(q >> 8); s->data[s->endp++] = (u_char)q; return 8; } int stream_putc_at (struct stream *s, size_t putp, u_char c) { STREAM_VERIFY_SANE(s); if (!PUT_AT_VALID (s, putp + sizeof (u_char))) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[putp] = c; return 1; } int stream_putw_at (struct stream *s, size_t putp, u_int16_t w) { STREAM_VERIFY_SANE(s); if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t))) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[putp] = (u_char)(w >> 8); s->data[putp + 1] = (u_char) w; return 2; } int stream_putl_at (struct stream *s, size_t putp, u_int32_t l) { STREAM_VERIFY_SANE(s); if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t))) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[putp] = (u_char)(l >> 24); s->data[putp + 1] = (u_char)(l >> 16); s->data[putp + 2] = (u_char)(l >> 8); s->data[putp + 3] = (u_char)l; return 4; } int stream_putq_at (struct stream *s, size_t putp, uint64_t q) { STREAM_VERIFY_SANE(s); if (!PUT_AT_VALID (s, putp + sizeof (uint64_t))) { STREAM_BOUND_WARN (s, "put"); return 0; } s->data[putp] = (u_char)(q >> 56); s->data[putp + 1] = (u_char)(q >> 48); s->data[putp + 2] = (u_char)(q >> 40); s->data[putp + 3] = (u_char)(q >> 32); s->data[putp + 4] = (u_char)(q >> 24); s->data[putp + 5] = (u_char)(q >> 16); s->data[putp + 6] = (u_char)(q >> 8); s->data[putp + 7] = (u_char)q; return 8; } /* Put long word to the stream. */ int stream_put_ipv4 (struct stream *s, u_int32_t l) { STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) { STREAM_BOUND_WARN (s, "put"); return 0; } memcpy (s->data + s->endp, &l, sizeof (u_int32_t)); s->endp += sizeof (u_int32_t); return sizeof (u_int32_t); } /* Put long word to the stream. */ int stream_put_in_addr (struct stream *s, struct in_addr *addr) { STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) { STREAM_BOUND_WARN (s, "put"); return 0; } memcpy (s->data + s->endp, addr, sizeof (u_int32_t)); s->endp += sizeof (u_int32_t); return sizeof (u_int32_t); } /* Put prefix by nlri type format. */ int stream_put_prefix (struct stream *s, struct isis_prefix *p) { size_t psize; STREAM_VERIFY_SANE(s); psize = PSIZE (p->prefixlen); if (STREAM_WRITEABLE (s) < psize) { STREAM_BOUND_WARN (s, "put"); return 0; } stream_putc (s, p->prefixlen); memcpy (s->data + s->endp, &p->u.prefix, psize); s->endp += psize; return psize; } /* Read size from fd. */ int stream_read (struct stream *s, int fd, size_t size) { int nbytes; STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); return 0; } nbytes = readn (fd, s->data + s->endp, size); if (nbytes > 0) s->endp += nbytes; return nbytes; } /* Read size from fd. */ int stream_read_unblock (struct stream *s, int fd, size_t size) { int nbytes; int val; STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); return 0; } val = fcntl (fd, F_GETFL, 0); fcntl (fd, F_SETFL, val|O_NONBLOCK); nbytes = read (fd, s->data + s->endp, size); fcntl (fd, F_SETFL, val); if (nbytes > 0) s->endp += nbytes; return nbytes; } ssize_t stream_read_try(struct stream *s, int fd, size_t size) { ssize_t nbytes; STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE(s) < size) { STREAM_BOUND_WARN (s, "put"); /* Fatal (not transient) error, since retrying will not help (stream is too small to contain the desired data). */ return -1; } if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) { s->endp += nbytes; return nbytes; } /* Error: was it transient (return -2) or fatal (return -1)? */ if (ERRNO_IO_RETRY(errno)) return -2; Log(LOG_WARNING, "WARN ( %s/core/ISIS ): %s: read failed on fd %d: %s\n", config.name, __func__, fd, strerror(errno)); return -1; } /* Read up to size bytes into the stream from the fd, using recvmsgfrom * whose arguments match the remaining arguments to this function */ ssize_t stream_recvfrom (struct stream *s, int fd, size_t size, int flags, struct sockaddr *from, socklen_t *fromlen) { ssize_t nbytes; STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE(s) < size) { STREAM_BOUND_WARN (s, "put"); /* Fatal (not transient) error, since retrying will not help (stream is too small to contain the desired data). */ return -1; } if ((nbytes = recvfrom (fd, s->data + s->endp, size, flags, from, fromlen)) >= 0) { s->endp += nbytes; return nbytes; } /* Error: was it transient (return -2) or fatal (return -1)? */ if (ERRNO_IO_RETRY(errno)) return -2; Log(LOG_WARNING, "WARN ( %s/core/ISIS ): %s: read failed on fd %d: %s\n", config.name, __func__, fd, strerror(errno)); return -1; } /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting * from endp. * First iovec will be used to receive the data. * Stream need not be empty. */ ssize_t stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, size_t size) { int nbytes; struct iovec *iov; STREAM_VERIFY_SANE(s); assert (msgh->msg_iovlen > 0); if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); /* This is a logic error in the calling code: the stream is too small to hold the desired data! */ return -1; } iov = &(msgh->msg_iov[0]); iov->iov_base = (s->data + s->endp); iov->iov_len = size; nbytes = recvmsg (fd, msgh, flags); if (nbytes > 0) s->endp += nbytes; return nbytes; } /* Write data to buffer. */ size_t stream_write (struct stream *s, const void *ptr, size_t size) { CHECK_SIZE(s, size); STREAM_VERIFY_SANE(s); if (STREAM_WRITEABLE (s) < size) { STREAM_BOUND_WARN (s, "put"); return 0; } memcpy (s->data + s->endp, ptr, size); s->endp += size; return size; } /* Return current read pointer. * DEPRECATED! * Use stream_get_pnt_to if you must, but decoding streams properly * is preferred */ u_char * stream_pnt (struct stream *s) { STREAM_VERIFY_SANE(s); return s->data + s->getp; } /* Check does this stream empty? */ int stream_empty (struct stream *s) { STREAM_VERIFY_SANE(s); return (s->endp == 0); } /* Reset stream. */ void stream_reset (struct stream *s) { STREAM_VERIFY_SANE (s); s->getp = s->endp = 0; } /* Write stream contens to the file discriptor. */ int stream_flush (struct stream *s, int fd) { int nbytes; STREAM_VERIFY_SANE(s); nbytes = write (fd, s->data + s->getp, s->endp - s->getp); return nbytes; } /* Read nbytes from fd and store into ptr. */ int readn (int fd, u_char *ptr, int nbytes) { int nleft; int nread; nleft = nbytes; while (nleft > 0) { nread = read (fd, ptr, nleft); if (nread < 0) return (nread); else if (nread == 0) break; nleft -= nread; ptr += nread; } return nbytes - nleft; } pmacct-1.7.8/src/isis/isis_events.c0000644000175000017500000001521214354105275016250 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_events.c * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "dict.h" #include "thread.h" #include "prefix.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_constants.h" #include "isis_adjacency.h" #include "isis_flags.h" #include "isisd.h" #include "isis_csm.h" #include "isis_events.h" #include "isis_spf.h" extern struct thread_master *master; extern struct isis *isis; /* debug isis-spf spf-events 4w4d: ISIS-Spf (tlt): L2 SPF needed, new adjacency, from 0x609229F4 4w4d: ISIS-Spf (tlt): L2, 0000.0000.0042.01-00 TLV contents changed, code 0x2 4w4d: ISIS-Spf (tlt): L2, new LSP 0 DEAD.BEEF.0043.00-00 4w5d: ISIS-Spf (tlt): L1 SPF needed, periodic SPF, from 0x6091C844 4w5d: ISIS-Spf (tlt): L2 SPF needed, periodic SPF, from 0x6091C844 */ void isis_event_circuit_state_change (struct isis_circuit *circuit, int up) { struct isis_area *area; area = circuit->area; assert (area); area->circuit_state_changes++; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Evt (%s) circuit %s\n", config.name, circuit->area->area_tag, up ? "up" : "down"); /* * Regenerate LSPs this affects */ lsp_regenerate_schedule (area); return; } void isis_event_system_type_change (struct isis_area *area, int newtype) { struct pm_listnode *node; struct isis_circuit *circuit; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Evt (%s) system type change %s -> %s\n", config.name, area->area_tag, circuit_t2string (area->is_type), circuit_t2string (newtype)); if (area->is_type == newtype) return; /* No change */ switch (area->is_type) { case IS_LEVEL_1: if (area->lspdb[1] == NULL) area->lspdb[1] = lsp_db_init (); lsp_l2_generate (area); break; case IS_LEVEL_1_AND_2: if (newtype == IS_LEVEL_1) { lsp_db_destroy (area->lspdb[1]); } else { lsp_db_destroy (area->lspdb[0]); } break; case IS_LEVEL_2: if (area->lspdb[0] == NULL) area->lspdb[0] = lsp_db_init (); lsp_l1_generate (area); break; default: break; } area->is_type = newtype; for (PM_ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) isis_event_circuit_type_change (circuit, newtype); spftree_area_init (area); lsp_regenerate_schedule (area); return; } void isis_event_area_addr_change (struct isis_area *area) { } // XXX: send hello instead? static void circuit_commence_level (struct isis_circuit *circuit, int level) { if (level == 1) { // THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit, // isis_jitter (circuit->psnp_interval[0], PSNP_JITTER)); } else { // THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit, // isis_jitter (circuit->psnp_interval[1], PSNP_JITTER)); } return; } static void circuit_resign_level (struct isis_circuit *circuit, int level) { // THREAD_TIMER_OFF (circuit->t_send_csnp[idx]); // THREAD_TIMER_OFF (circuit->t_send_psnp[idx]); return; } void isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Evt (%s) circuit type change %s -> %s\n", config.name, circuit->area->area_tag, circuit_t2string (circuit->circuit_is_type), circuit_t2string (newtype)); if (circuit->circuit_is_type == newtype) return; /* No change */ if (!(newtype & circuit->area->is_type)) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Evt (%s) circuit type change - invalid level %s because area is %s\n", config.name, circuit->area->area_tag, circuit_t2string (newtype), circuit_t2string (circuit->area->is_type)); return; } switch (circuit->circuit_is_type) { case IS_LEVEL_1: if (newtype == IS_LEVEL_2) circuit_resign_level (circuit, 1); circuit_commence_level (circuit, 2); break; case IS_LEVEL_1_AND_2: if (newtype == IS_LEVEL_1) circuit_resign_level (circuit, 2); else circuit_resign_level (circuit, 1); break; case IS_LEVEL_2: if (newtype == IS_LEVEL_1) circuit_resign_level (circuit, 2); circuit_commence_level (circuit, 1); break; default: break; } circuit->circuit_is_type = newtype; lsp_regenerate_schedule (circuit->area); return; } /* 04/18/2002 by Gwak. */ /************************************************************************** * * EVENTS for LSP generation * * 1) an Adajacency or Circuit Up/Down event * 2) a chnage in Circuit metric * 3) a change in Reachable Address metric * 4) a change in manualAreaAddresses * 5) a change in systemID * 6) a change in DIS status * 7) a chnage in the waiting status * * *********************************************************************** * * current support event * * 1) Adjacency Up/Down event * 6) a change in DIS status * * ***********************************************************************/ void isis_event_adjacency_state_change (struct isis_adjacency *adj, int newstate) { /* adjacency state change event. * - the only proto-type was supported */ /* invalid arguments */ if (!adj || !adj->circuit || !adj->circuit->area) return; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Evt (%s) Adjacency State change\n", config.name, adj->circuit->area->area_tag); /* LSP generation again */ lsp_regenerate_schedule (adj->circuit->area); return; } /* events supporting code */ void isis_event_auth_failure (char *area_tag, const char *error_string, u_char *sysid) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Evt (%s) Authentication failure %s from %s\n", config.name, area_tag, error_string, sysid_print (sysid)); return; } pmacct-1.7.8/src/isis/checksum.h0000644000175000017500000000026414354105275015525 0ustar paolopaolo#ifndef _CHECKSUM_H_ #define _CHECKSUM_H_ extern int in_cksum(void *, int); extern u_int16_t fletcher_checksum(u_char *, const size_t, const uint16_t); #endif /* _CHECKSUM_H_ */ pmacct-1.7.8/src/isis/isis_tlv.c0000644000175000017500000007666114354105275015570 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_tlv.c * IS-IS TLV related routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "prefix.h" #include "dict.h" #include "stream.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isisd.h" #include "isis_dynhn.h" #include "isis_misc.h" #include "isis_pdu.h" #include "isis_lsp.h" extern struct isis *isis; /* * Prototypes. */ int add_tlv (u_char, u_char, u_char *, struct stream *); void free_tlv (void *val) { free(val); return; } /* * Called after parsing of a PDU. There shouldn't be any tlv's left, so this * is only a caution to avoid memory leaks */ void free_tlvs (struct tlvs *tlvs) { if (tlvs->area_addrs) pm_list_delete (tlvs->area_addrs); if (tlvs->is_neighs) pm_list_delete (tlvs->is_neighs); if (tlvs->te_is_neighs) pm_list_delete (tlvs->te_is_neighs); if (tlvs->es_neighs) pm_list_delete (tlvs->es_neighs); if (tlvs->lsp_entries) pm_list_delete (tlvs->lsp_entries); if (tlvs->lan_neighs) pm_list_delete (tlvs->lan_neighs); if (tlvs->prefix_neighs) pm_list_delete (tlvs->prefix_neighs); if (tlvs->ipv4_addrs) pm_list_delete (tlvs->ipv4_addrs); if (tlvs->ipv4_int_reachs) pm_list_delete (tlvs->ipv4_int_reachs); if (tlvs->ipv4_ext_reachs) pm_list_delete (tlvs->ipv4_ext_reachs); if (tlvs->te_ipv4_reachs) pm_list_delete (tlvs->te_ipv4_reachs); if (tlvs->ipv6_addrs) pm_list_delete (tlvs->ipv6_addrs); if (tlvs->ipv6_reachs) pm_list_delete (tlvs->ipv6_reachs); return; } /* * Parses the tlvs found in the variant length part of the PDU. * Caller tells with flags in "expected" which TLV's it is interested in. */ int parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, u_int32_t * found, struct tlvs *tlvs) { u_char type, length; struct lan_neigh *lan_nei; struct area_addr *area_addr; struct is_neigh *is_nei; struct te_is_neigh *te_is_nei; struct es_neigh *es_nei; struct lsp_entry *lsp_entry; struct in_addr *ipv4_addr; struct ipv4_reachability *ipv4_reach; struct te_ipv4_reachability *te_ipv4_reach; struct in6_addr *ipv6_addr; struct ipv6_reachability *ipv6_reach; int prefix_octets; int value_len, retval = ISIS_OK; u_char *pnt = stream; *found = 0; memset (tlvs, 0, sizeof (struct tlvs)); while (pnt < stream + size - 2) { type = *pnt; length = *(pnt + 1); pnt += 2; value_len = 0; if (pnt + length > stream + size) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet boundaries\n", config.name, areatag, type, length); retval = ISIS_WARNING; break; } switch (type) { case AREA_ADDRESSES: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Address Length | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Area Address | * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_AREA_ADDRS; if (*expected & TLVFLAG_AREA_ADDRS) { while (length > value_len) { area_addr = (struct area_addr *) pnt; value_len += area_addr->addr_len + 1; pnt += area_addr->addr_len + 1; if (!tlvs->area_addrs) tlvs->area_addrs = pm_list_new (); pm_listnode_add (tlvs->area_addrs, area_addr); } } else { pnt += length; } break; case IS_NEIGHBOURS: *found |= TLVFLAG_IS_NEIGHS; if (TLVFLAG_IS_NEIGHS & *expected) { /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Virtual Flag | * +-------+-------+-------+-------+-------+-------+-------+-------+ */ pnt++; value_len++; /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | 0 | I/E | Default Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Delay Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Expense Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Error Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Neighbour ID | * +---------------------------------------------------------------+ * : : */ while (length > value_len) { is_nei = (struct is_neigh *) pnt; value_len += 4 + ISIS_SYS_ID_LEN + 1; pnt += 4 + ISIS_SYS_ID_LEN + 1; if (!tlvs->is_neighs) tlvs->is_neighs = pm_list_new (); pm_listnode_add (tlvs->is_neighs, is_nei); } } else { pnt += length; } break; case TE_IS_NEIGHBOURS: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Neighbour ID | 7 * +---------------------------------------------------------------+ * | TE Metric | 3 * +---------------------------------------------------------------+ * | SubTLVs Length | 1 * +---------------------------------------------------------------+ * : : */ *found |= TLVFLAG_TE_IS_NEIGHS; if (TLVFLAG_TE_IS_NEIGHS & *expected) { while (length > value_len) { te_is_nei = (struct te_is_neigh *) pnt; value_len += 11; pnt += 11; /* FIXME - subtlvs are handled here, for now we skip */ value_len += te_is_nei->sub_tlvs_length; pnt += te_is_nei->sub_tlvs_length; if (!tlvs->te_is_neighs) tlvs->te_is_neighs = pm_list_new (); pm_listnode_add (tlvs->te_is_neighs, te_is_nei); } } else { pnt += length; } break; case ES_NEIGHBOURS: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | 0 | I/E | Default Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Delay Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Expense Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Error Metric | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Neighbour ID | * +---------------------------------------------------------------+ * | Neighbour ID | * +---------------------------------------------------------------+ * : : */ *found |= TLVFLAG_ES_NEIGHS; if (*expected & TLVFLAG_ES_NEIGHS) { es_nei = (struct es_neigh *) pnt; value_len += 4; pnt += 4; while (length > value_len) { /* FIXME FIXME FIXME - add to the list */ /* sys_id->id = pnt; */ value_len += ISIS_SYS_ID_LEN; pnt += ISIS_SYS_ID_LEN; /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */ } if (!tlvs->es_neighs) tlvs->es_neighs = pm_list_new (); pm_listnode_add (tlvs->es_neighs, es_nei); } else { pnt += length; } break; case LAN_NEIGHBOURS: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | LAN Address | * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_LAN_NEIGHS; if (TLVFLAG_LAN_NEIGHS & *expected) { while (length > value_len) { lan_nei = (struct lan_neigh *) pnt; if (!tlvs->lan_neighs) tlvs->lan_neighs = pm_list_new (); pm_listnode_add (tlvs->lan_neighs, lan_nei); value_len += ETH_ALEN; pnt += ETH_ALEN; } } else { pnt += length; } break; case PADDING: pnt += length; break; case LSP_ENTRIES: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Remaining Lifetime | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LSP ID | id+2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LSP Sequence Number | 4 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Checksum | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ *found |= TLVFLAG_LSP_ENTRIES; if (TLVFLAG_LSP_ENTRIES & *expected) { while (length > value_len) { lsp_entry = (struct lsp_entry *) pnt; value_len += 10 + ISIS_SYS_ID_LEN; pnt += 10 + ISIS_SYS_ID_LEN; if (!tlvs->lsp_entries) tlvs->lsp_entries = pm_list_new (); pm_listnode_add (tlvs->lsp_entries, lsp_entry); } } else { pnt += length; } break; case CHECKSUM: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | 16 bit fletcher CHECKSUM | * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_CHECKSUM; if (*expected & TLVFLAG_CHECKSUM) { tlvs->checksum = (struct checksum *) pnt; } pnt += length; break; case PROTOCOLS_SUPPORTED: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | NLPID | * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_NLPID; if (*expected & TLVFLAG_NLPID) { tlvs->nlpids = (struct nlpids *) (pnt - 1); } pnt += length; break; case IPV4_ADDR: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * + IP version 4 address + 4 * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_IPV4_ADDR; if (*expected & TLVFLAG_IPV4_ADDR) { while (length > value_len) { ipv4_addr = (struct in_addr *) pnt; if (!tlvs->ipv4_addrs) tlvs->ipv4_addrs = pm_list_new (); pm_listnode_add (tlvs->ipv4_addrs, ipv4_addr); value_len += 4; pnt += 4; } } else { pnt += length; } break; case AUTH_INFO: *found |= TLVFLAG_AUTH_INFO; if (*expected & TLVFLAG_AUTH_INFO) { tlvs->auth_info.type = *pnt; tlvs->auth_info.len = length-1; pnt++; memcpy (tlvs->auth_info.passwd, pnt, length - 1); pnt += length - 1; } else { pnt += length; } break; case DYNAMIC_HOSTNAME: *found |= TLVFLAG_DYN_HOSTNAME; if (*expected & TLVFLAG_DYN_HOSTNAME) { /* the length is also included in the pointed struct */ tlvs->hostname = (struct hostname *) (pnt - 1); } pnt += length; break; case TE_ROUTER_ID: /* +---------------------------------------------------------------+ * + Router ID + 4 * +---------------------------------------------------------------+ */ *found |= TLVFLAG_TE_ROUTER_ID; if (*expected & TLVFLAG_TE_ROUTER_ID) tlvs->router_id = (struct te_router_id *) (pnt); pnt += length; break; case IPV4_INT_REACHABILITY: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | 0 | I/E | Default Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Delay Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Expense Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Error Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | ip address | 4 * +---------------------------------------------------------------+ * | address mask | 4 * +---------------------------------------------------------------+ * : : */ *found |= TLVFLAG_IPV4_INT_REACHABILITY; if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) { while (length > value_len) { ipv4_reach = (struct ipv4_reachability *) pnt; if (!tlvs->ipv4_int_reachs) tlvs->ipv4_int_reachs = pm_list_new (); pm_listnode_add (tlvs->ipv4_int_reachs, ipv4_reach); value_len += 12; pnt += 12; } } else { pnt += length; } break; case IPV4_EXT_REACHABILITY: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | 0 | I/E | Default Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Delay Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Expense Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | S | I/E | Error Metric | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | ip address | 4 * +---------------------------------------------------------------+ * | address mask | 4 * +---------------------------------------------------------------+ * : : */ *found |= TLVFLAG_IPV4_EXT_REACHABILITY; if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY) { while (length > value_len) { ipv4_reach = (struct ipv4_reachability *) pnt; if (!tlvs->ipv4_ext_reachs) tlvs->ipv4_ext_reachs = pm_list_new (); pm_listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach); value_len += 12; pnt += 12; } } else { pnt += length; } break; case TE_IPV4_REACHABILITY: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | TE Metric | 4 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | U/D | sTLV? | Prefix Mask Len | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Prefix | 0-4 * +---------------------------------------------------------------+ * | sub tlvs | * +---------------------------------------------------------------+ * : : */ *found |= TLVFLAG_TE_IPV4_REACHABILITY; if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) { while (length > value_len) { te_ipv4_reach = (struct te_ipv4_reachability *) pnt; if (!tlvs->te_ipv4_reachs) tlvs->te_ipv4_reachs = pm_list_new (); pm_listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach); /* this trickery is permitable since no subtlvs are defined */ value_len += 5 + ((te_ipv4_reach->control & 0x3F) ? ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0); pnt += 5 + ((te_ipv4_reach->control & 0x3F) ? ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0); } } else { pnt += length; } break; case IPV6_ADDR: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * + IP version 6 address + 16 * +-------+-------+-------+-------+-------+-------+-------+-------+ * : : */ *found |= TLVFLAG_IPV6_ADDR; if (*expected & TLVFLAG_IPV6_ADDR) { while (length > value_len) { ipv6_addr = (struct in6_addr *) pnt; if (!tlvs->ipv6_addrs) tlvs->ipv6_addrs = pm_list_new (); pm_listnode_add (tlvs->ipv6_addrs, ipv6_addr); value_len += 16; pnt += 16; } } else { pnt += length; } break; case IPV6_REACHABILITY: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Default Metric | 4 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Control Informantion | * +---------------------------------------------------------------+ * | IPv6 Prefix Length |--+ * +---------------------------------------------------------------+ | * | IPv6 Prefix |<-+ * +---------------------------------------------------------------+ */ *found |= TLVFLAG_IPV6_REACHABILITY; if (*expected & TLVFLAG_IPV6_REACHABILITY) { while (length > value_len) { ipv6_reach = (struct ipv6_reachability *) pnt; prefix_octets = ((ipv6_reach->prefix_len + 7) / 8); value_len += prefix_octets + 6; pnt += prefix_octets + 6; /* FIXME: sub-tlvs */ if (!tlvs->ipv6_reachs) tlvs->ipv6_reachs = pm_list_new (); pm_listnode_add (tlvs->ipv6_reachs, ipv6_reach); } } else { pnt += length; } break; case WAY3_HELLO: /* +---------------------------------------------------------------+ * | Adjacency state | 1 * +---------------------------------------------------------------+ * | Extended Local Circuit ID | 4 * +---------------------------------------------------------------+ * | Neighbor System ID (If known) | 0-8 * (probably 6) * +---------------------------------------------------------------+ * | Neighbor Local Circuit ID (If known) | 4 * +---------------------------------------------------------------+ */ *found |= TLVFLAG_3WAY_HELLO; if (*expected & TLVFLAG_3WAY_HELLO) { while (length > value_len) { /* FIXME: make this work */ /* Adjacency State (one octet): 0 = Up 1 = Initializing 2 = Down Extended Local Circuit ID (four octets) Neighbor System ID if known (zero to eight octets) Neighbor Extended Local Circuit ID (four octets, if Neighbor System ID is present) */ pnt += length; } } else { pnt += length; } break; case GRACEFUL_RESTART: /* +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | SA | RA | RR | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Remaining Time | 2 * +---------------------------------------------------------------+ * | Restarting Neighbor ID (If known) | 0-8 * +---------------------------------------------------------------+ */ *found |= TLVFLAG_GRACEFUL_RESTART; if (*expected & TLVFLAG_GRACEFUL_RESTART) { /* FIXME: make this work */ } pnt += length; break; default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): ISIS-TLV (%s): unsupported TLV type %d, length %d\n", config.name, areatag, type, length); retval = ISIS_WARNING; pnt += length; break; } } return retval; } int add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream) { if (STREAM_SIZE (stream) - stream_get_endp (stream) < (unsigned) len + 2) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): No room for TLV of type %d\n", config.name, tag); return ISIS_WARNING; } stream_putc (stream, tag); /* TAG */ stream_putc (stream, len); /* LENGTH */ stream_put (stream, value, (int) len); /* VALUE */ return ISIS_OK; } int tlv_add_area_addrs (struct pm_list *area_addrs, struct stream *stream) { struct pm_listnode *node; struct area_addr *area_addr; u_char value[255]; u_char *pos = value; for (PM_ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr)) { if (pos - value + area_addr->addr_len > 255) goto err; *pos = area_addr->addr_len; pos++; memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len); pos += area_addr->addr_len; } return add_tlv (AREA_ADDRESSES, pos - value, value, stream); err: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): tlv_add_area_addrs(): TLV longer than 255\n", config.name); return ISIS_WARNING; } int tlv_add_is_neighs (struct pm_list *is_neighs, struct stream *stream) { struct pm_listnode *node; struct is_neigh *is_neigh; u_char value[255]; u_char *pos = value; int retval; *pos = 0; /*is_neigh->virtual; */ pos++; for (PM_ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh)) { if (pos - value + IS_NEIGHBOURS_LEN > 255) { retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *pos = is_neigh->metrics.metric_default; pos++; *pos = is_neigh->metrics.metric_delay; pos++; *pos = is_neigh->metrics.metric_expense; pos++; *pos = is_neigh->metrics.metric_error; pos++; memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); pos += ISIS_SYS_ID_LEN + 1; } return add_tlv (IS_NEIGHBOURS, pos - value, value, stream); } int tlv_add_te_is_neighs (struct pm_list *te_is_neighs, struct stream *stream) { struct pm_listnode *node; struct te_is_neigh *te_is_neigh; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh)) { /* FIXME: This will be wrong if we are going to add TE sub TLVs. */ if (pos - value + IS_NEIGHBOURS_LEN > 255) { retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); pos += ISIS_SYS_ID_LEN + 1; memcpy (pos, te_is_neigh->te_metric, 3); pos += 3; /* Sub TLVs length. */ *pos = 0; pos++; } return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream); } int tlv_add_lan_neighs (struct pm_list *lan_neighs, struct stream *stream) { struct pm_listnode *node; u_char *snpa; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa)) { if (pos - value + ETH_ALEN > 255) { retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } memcpy (pos, snpa, ETH_ALEN); pos += ETH_ALEN; } return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream); } int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream) { return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream); } int tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value, struct stream *stream) { u_char value[255]; u_char *pos = value; *pos++ = ISIS_PASSWD_TYPE_CLEARTXT; memcpy (pos, auth_value, auth_len); return add_tlv (AUTH_INFO, auth_len + 1, value, stream); } int tlv_add_checksum (struct checksum *checksum, struct stream *stream) { u_char value[255]; u_char *pos = value; return add_tlv (CHECKSUM, pos - value, value, stream); } int tlv_add_ip_addrs (struct pm_list *ip_addrs, struct stream *stream) { struct pm_listnode *node; struct prefix_ipv4 *ipv4; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4)) { if (pos - value + IPV4_MAX_BYTELEN > 255) { retval = add_tlv (IPV4_ADDR, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *(u_int32_t *) pos = ipv4->prefix.s_addr; pos += IPV4_MAX_BYTELEN; } return add_tlv (IPV4_ADDR, pos - value, value, stream); } /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV * (in case of LSP) or TE router ID TLV. */ int tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag) { u_char value[255]; u_char *pos = value; memcpy (pos, addr, IPV4_MAX_BYTELEN); pos += IPV4_MAX_BYTELEN; return add_tlv (tag, pos - value, value, stream); } int tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream) { return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name, stream); } int tlv_add_lsp_entries (struct pm_list *lsps, struct stream *stream) { struct pm_listnode *node; struct isis_lsp *lsp; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (lsps, node, lsp)) { if (pos - value + LSP_ENTRIES_LEN > 255) { retval = add_tlv (LSP_ENTRIES, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime; pos += 2; memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); pos += ISIS_SYS_ID_LEN + 2; *((u_int32_t *) pos) = lsp->lsp_header->seq_num; pos += 4; *((u_int16_t *) pos) = lsp->lsp_header->checksum; pos += 2; } return add_tlv (LSP_ENTRIES, pos - value, value, stream); } int tlv_add_ipv4_reachs (struct pm_list *ipv4_reachs, struct stream *stream) { struct pm_listnode *node; struct ipv4_reachability *reach; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach)) { if (pos - value + IPV4_REACH_LEN > 255) { retval = add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *pos = reach->metrics.metric_default; pos++; *pos = reach->metrics.metric_delay; pos++; *pos = reach->metrics.metric_expense; pos++; *pos = reach->metrics.metric_error; pos++; *(u_int32_t *) pos = reach->prefix.s_addr; pos += IPV4_MAX_BYTELEN; *(u_int32_t *) pos = reach->mask.s_addr; pos += IPV4_MAX_BYTELEN; } return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream); } int tlv_add_te_ipv4_reachs (struct pm_list *te_ipv4_reachs, struct stream *stream) { struct pm_listnode *node; struct te_ipv4_reachability *te_reach; u_char value[255]; u_char *pos = value; u_char prefix_size; int retval; for (PM_ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach)) { prefix_size = ((((te_reach->control & 0x3F) - 1) >> 3) + 1); if (pos - value + (5 + prefix_size) > 255) { retval = add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *(u_int32_t *) pos = te_reach->te_metric; pos += 4; *pos = te_reach->control; pos++; memcpy (pos, &te_reach->prefix_start, prefix_size); pos += prefix_size; } return add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream); } int tlv_add_ipv6_addrs (struct pm_list *ipv6_addrs, struct stream *stream) { struct pm_listnode *node; struct prefix_ipv6 *ipv6; u_char value[255]; u_char *pos = value; int retval; for (PM_ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6)) { if (pos - value + IPV6_MAX_BYTELEN > 255) { retval = add_tlv (IPV6_ADDR, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN); pos += IPV6_MAX_BYTELEN; } return add_tlv (IPV6_ADDR, pos - value, value, stream); } int tlv_add_ipv6_reachs (struct pm_list *ipv6_reachs, struct stream *stream) { struct pm_listnode *node; struct ipv6_reachability *ip6reach; u_char value[255]; u_char *pos = value; int retval, prefix_octets; for (PM_ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach)) { if (pos - value + IPV6_MAX_BYTELEN + 6 > 255) { retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream); if (retval != ISIS_OK) return retval; pos = value; } *(uint32_t *) pos = ip6reach->metric; pos += 4; *pos = ip6reach->control_info; pos++; prefix_octets = ((ip6reach->prefix_len + 7) / 8); *pos = ip6reach->prefix_len; pos++; memcpy (pos, ip6reach->prefix, prefix_octets); pos += prefix_octets; } return add_tlv (IPV6_REACHABILITY, pos - value, value, stream); } int tlv_add_padding (struct stream *stream) { int fullpads, i, left; /* * How many times can we add full padding ? */ fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257; for (i = 0; i < fullpads; i++) { if (!stream_putc (stream, (u_char) PADDING)) /* TAG */ goto err; if (!stream_putc (stream, (u_char) 255)) /* LENGHT */ goto err; stream_put (stream, NULL, 255); /* zero padding */ } left = STREAM_SIZE (stream) - stream_get_endp (stream); if (left < 2) return ISIS_OK; if (left == 2) { stream_putc (stream, PADDING); stream_putc (stream, 0); return ISIS_OK; } stream_putc (stream, PADDING); stream_putc (stream, left - 2); stream_put (stream, NULL, left-2); return ISIS_OK; err: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): tlv_add_padding(): no room for tlv\n", config.name); return ISIS_WARNING; } pmacct-1.7.8/src/isis/isis_pdu.c0000644000175000017500000014557214354105275015551 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_pdu.c * PDU processing * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "stream.h" #include "hash.h" #include "prefix.h" #include "checksum.h" #include "dict.h" #include "thread.h" #include "iso.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_adjacency.h" #include "isis_circuit.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_flags.h" #include "isis_tlv.h" #include "isisd.h" #include "isis_dynhn.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "iso_checksum.h" #include "isis_csm.h" #include "isis_events.h" #include "isis_lsp.h" extern struct thread_master *master; extern struct isis *isis; #define ISIS_MINIMUM_FIXED_HDR_LEN 15 #define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */ #ifndef PNBBY #define PNBBY 8 #endif /* PNBBY */ /* Utility mask array. */ static const u_char __attribute__((unused)) maskbit[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; /* * HELPER FUNCS */ /* * Compares two sets of area addresses */ static int area_match (struct pm_list *left, struct pm_list *right) { struct area_addr *addr1, *addr2; struct pm_listnode *node1, *node2; if (!left || !right) return 0; /* mismatch */ for (PM_ALL_LIST_ELEMENTS_RO (left, node1, addr1)) { for (PM_ALL_LIST_ELEMENTS_RO (right, node2, addr2)) { if (addr1->addr_len == addr2->addr_len && !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len)) return 1; /* match */ } } return 0; /* mismatch */ } /* * Checks whether we should accept a PDU of given level */ static int accept_level (int level, int circuit_t) { int retval = ((circuit_t & level) == level); /* simple approach */ return retval; } int authentication_check (struct isis_passwd *one, struct isis_passwd *theother) { if (one->type != theother->type) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Unsupported authentication type %d\n", config.name, theother->type); return 1; /* Auth fail (different authentication types) */ } switch (one->type) { case ISIS_PASSWD_TYPE_CLEARTXT: if (one->len != theother->len) return 1; /* Auth fail () - passwd len mismatch */ return memcmp (one->passwd, theother->passwd, one->len); break; default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Unsupported authentication type\n", config.name); break; } return 0; /* Auth pass */ } /* * Processing helper functions */ static void tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj) { int i; struct nlpids *tlv_nlpids; if (tlvs->nlpids) { tlv_nlpids = tlvs->nlpids; adj->nlpids.count = tlv_nlpids->count; for (i = 0; i < tlv_nlpids->count; i++) { adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i]; } } } static void del_ip_addr (void *val) { free(val); } static void tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) { struct pm_listnode *node; struct in_addr *ipv4_addr, *malloced; if (adj->ipv4_addrs) { adj->ipv4_addrs->del = del_ip_addr; pm_list_delete (adj->ipv4_addrs); } adj->ipv4_addrs = pm_list_new (); if (tlvs->ipv4_addrs) { for (PM_ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr)) { malloced = calloc(1, sizeof (struct in_addr)); memcpy (malloced, ipv4_addr, sizeof (struct in_addr)); pm_listnode_add (adj->ipv4_addrs, malloced); } } } static void tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) { struct pm_listnode *node; struct in6_addr *ipv6_addr, *malloced; if (adj->ipv6_addrs) { adj->ipv6_addrs->del = del_ip_addr; pm_list_delete (adj->ipv6_addrs); } adj->ipv6_addrs = pm_list_new (); if (tlvs->ipv6_addrs) { for (PM_ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr)) { malloced = calloc(1, sizeof (struct in6_addr)); memcpy (malloced, ipv6_addr, sizeof (struct in6_addr)); pm_listnode_add (adj->ipv6_addrs, malloced); } } } /* * RECEIVE SIDE */ /* * Process P2P IIH * ISO - 10589 * Section 8.2.5 - Receiving point-to-point IIH PDUs * */ static int process_p2p_hello (struct isis_circuit *circuit) { int retval = ISIS_OK; struct isis_p2p_hello_hdr *hdr; struct isis_adjacency *adj; u_int32_t expected = 0, found; struct tlvs tlvs; if ((stream_get_endp (circuit->rcv_stream) - stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Packet too short\n", config.name); return ISIS_WARNING; } /* 8.2.5.1 PDU acceptance tests */ /* 8.2.5.1 a) external domain untrue */ /* FIXME: not useful at all? */ /* 8.2.5.1 b) ID Length mismatch */ /* checked at the handle_pdu */ /* 8.2.5.2 IIH PDU Processing */ /* 8.2.5.2 a) 1) Maximum Area Addresses */ /* Already checked, and can also be ommited */ /* * Get the header */ hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream); circuit->rcv_stream->getp += ISIS_P2PHELLO_HDRLEN; /* hdr.circuit_t = stream_getc (stream); stream_get (hdr.source_id, stream, ISIS_SYS_ID_LEN); hdr.hold_time = stream_getw (stream); hdr.pdu_len = stream_getw (stream); hdr.local_id = stream_getc (stream); */ /* * My interpertation of the ISO, if no adj exists we will create one for * the circuit */ adj = circuit->u.p2p.neighbor; if (!adj) { adj = isis_new_adj (hdr->source_id, NULL, 0, circuit); if (adj == NULL) return ISIS_ERROR; circuit->u.p2p.neighbor = adj; isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); adj->sys_type = ISIS_SYSTYPE_UNKNOWN; } /* 8.2.6 Monitoring point-to-point adjacencies */ adj->hold_time = ntohs (hdr->hold_time); adj->last_upd = time (NULL); /* * Lets get the TLVS now */ expected |= TLVFLAG_AREA_ADDRS; expected |= TLVFLAG_AUTH_INFO; expected |= TLVFLAG_NLPID; expected |= TLVFLAG_IPV4_ADDR; expected |= TLVFLAG_IPV6_ADDR; retval = parse_tlvs (circuit->area->area_tag, STREAM_PNT (circuit->rcv_stream), ntohs (hdr->pdu_len) - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, &expected, &found, &tlvs); if (retval > ISIS_WARNING) { free_tlvs (&tlvs); return retval; }; /* 8.2.5.1 c) Authentication */ if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || authentication_check (&circuit->passwd, &tlvs.auth_info)) { isis_event_auth_failure (circuit->area->area_tag, "P2P hello authentication failure", hdr->source_id); return ISIS_OK; } } /* we do this now because the adj may not survive till the end... */ /* which protocol are spoken ??? */ if (found & TLVFLAG_NLPID) tlvs_to_adj_nlpids (&tlvs, adj); /* we need to copy addresses to the adj */ if (found & TLVFLAG_IPV4_ADDR) tlvs_to_adj_ipv4_addrs (&tlvs, adj); if (found & TLVFLAG_IPV6_ADDR) tlvs_to_adj_ipv6_addrs (&tlvs, adj); /* lets take care of the expiry */ adj->expire.tv_sec = isis_now.tv_sec + adj->hold_time; adj->expire.tv_usec = isis_now.tv_usec; /* 8.2.5.2 a) a match was detected */ if (area_match (circuit->area->area_addrs, tlvs.area_addrs)) { /* 8.2.5.2 a) 2) If the system is L1 - table 5 */ if (circuit->area->is_type == IS_LEVEL_1) { switch (hdr->circuit_t) { case IS_LEVEL_1: case IS_LEVEL_1_AND_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (4) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (5) adj usage level 1 */ adj->adj_usage = ISIS_ADJ_LEVEL1; } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { ; /* accept */ } break; case IS_LEVEL_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (7) reject - wrong system type event */ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): wrongSystemType\n", config.name); return ISIS_WARNING; /* Reject */ } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { /* (6) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } break; } } /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ if (circuit->area->is_type == IS_LEVEL_1_AND_2) { switch (hdr->circuit_t) { case IS_LEVEL_1: if (adj->adj_state != ISIS_ADJ_UP) { /* (6) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (7) adj usage level 1 */ adj->adj_usage = ISIS_ADJ_LEVEL1; } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { ; /* accept */ } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || (adj->adj_usage == ISIS_ADJ_LEVEL2)) { /* (8) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } break; case IS_LEVEL_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (6) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (9) adj usage level 2 */ adj->adj_usage = ISIS_ADJ_LEVEL2; } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) { /* (8) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { ; /* Accept */ } break; case IS_LEVEL_1_AND_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (6) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (10) adj usage level 1 */ adj->adj_usage = ISIS_ADJ_LEVEL1AND2; } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || (adj->adj_usage == ISIS_ADJ_LEVEL2)) { /* (8) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { ; /* Accept */ } break; } } /* 8.2.5.2 a) 4) If the system is L2 - table 7 */ if (circuit->area->is_type == IS_LEVEL_2) { switch (hdr->circuit_t) { case IS_LEVEL_1: if (adj->adj_state != ISIS_ADJ_UP) { /* (5) reject - wrong system type event */ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): wrongSystemType\n", config.name); return ISIS_WARNING; /* Reject */ } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || (adj->adj_usage == ISIS_ADJ_LEVEL2)) { /* (6) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } break; case IS_LEVEL_1_AND_2: case IS_LEVEL_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (7) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (8) adj usage level 2 */ adj->adj_usage = ISIS_ADJ_LEVEL2; } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { /* (6) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { ; /* Accept */ } break; } } } /* 8.2.5.2 b) if no match was detected */ else { if (circuit->area->is_type == IS_LEVEL_1) { /* 8.2.5.2 b) 1) is_type L1 and adj is not up */ if (adj->adj_state != ISIS_ADJ_UP) { isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); /* 8.2.5.2 b) 2)is_type L1 and adj is up */ } else { isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Down - Area Mismatch"); } } /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */ else { switch (hdr->circuit_t) { case IS_LEVEL_1: if (adj->adj_state != ISIS_ADJ_UP) { /* (6) reject - Area Mismatch event */ Log(LOG_WARNING, "WARN ( %s/core/ISIS ): AreaMismatch\n", config.name); return ISIS_WARNING; /* Reject */ } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { /* (7) down - area mismatch */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || (adj->adj_usage == ISIS_ADJ_LEVEL2)) { /* (7) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } break; case IS_LEVEL_1_AND_2: case IS_LEVEL_2: if (adj->adj_state != ISIS_ADJ_UP) { /* (8) adj state up */ isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); /* (9) adj usage level 2 */ adj->adj_usage = ISIS_ADJ_LEVEL2; } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { /* (7) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { if (hdr->circuit_t == IS_LEVEL_2) { /* (7) down - wrong system */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); } else { /* (7) down - area mismatch */ isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); } } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { ; /* Accept */ } break; } } } /* 8.2.5.2 c) if the action was up - comparing circuit IDs */ /* FIXME - Missing parts */ /* some of my own understanding of the ISO, why the heck does * it not say what should I change the system_type to... */ switch (adj->adj_usage) { case ISIS_ADJ_LEVEL1: adj->sys_type = ISIS_SYSTYPE_L1_IS; break; case ISIS_ADJ_LEVEL2: adj->sys_type = ISIS_SYSTYPE_L2_IS; break; case ISIS_ADJ_LEVEL1AND2: adj->sys_type = ISIS_SYSTYPE_L2_IS; break; case ISIS_ADJ_NONE: adj->sys_type = ISIS_SYSTYPE_UNKNOWN; break; } adj->circuit_t = hdr->circuit_t; adj->level = hdr->circuit_t; free_tlvs (&tlvs); return retval; } /* * Process Level 1/2 Link State * ISO - 10589 * Section 7.3.15.1 - Action on receipt of a link state PDU */ static int process_lsp (int level, struct isis_circuit *circuit, u_char * ssnpa) { struct isis_link_state_hdr *hdr; struct isis_adjacency *adj = NULL; struct isis_lsp *lsp, *lsp0 = NULL; int retval = ISIS_OK, comp = 0; u_char lspid[ISIS_SYS_ID_LEN + 2]; struct isis_passwd *passwd; /* Sanity check - FIXME: move to correct place */ if ((stream_get_endp (circuit->rcv_stream) - stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Packet too short\n", config.name); return ISIS_WARNING; } /* Reference the header */ hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream); assert (ntohs (hdr->pdu_len) > ISIS_LSP_HDR_LEN); /* Checksum sanity check - FIXME: move to correct place */ /* 12 = sysid+pdu+remtime */ /* if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4, ntohs (hdr->pdu_len) - 12, &hdr->checksum)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x\n", config.name, circuit->area->area_tag, rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum)); return ISIS_WARNING; } */ /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ if (circuit->ext_domain) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): LSP %s received at level %d over circuit with externalDomain = true\n", config.name, circuit->area->area_tag, rawlspid_print (hdr->lsp_id), level); return ISIS_WARNING; } /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ if (!accept_level (level, circuit->circuit_is_type)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): LSP %s received at level %d over circuit of type %s\n", config.name, circuit->area->area_tag, rawlspid_print (hdr->lsp_id), level, circuit_t2string (circuit->circuit_is_type)); return ISIS_WARNING; } /* 7.3.15.1 a) 4 - need to make sure IDLength matches */ /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */ /* 7.3.15.1 a) 7 - password check */ (level == ISIS_LEVEL1) ? (passwd = &circuit->area->area_passwd) : (passwd = &circuit->area->domain_passwd); if (passwd->type) { if (isis_lsp_authinfo_check (circuit->rcv_stream, circuit->area, ntohs (hdr->pdu_len), passwd)) { isis_event_auth_failure (circuit->area->area_tag, "LSP authentication failure", hdr->lsp_id); return ISIS_WARNING; } } /* Find the LSP in our database and compare it to this Link State header */ lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]); if (lsp) comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num, hdr->checksum, hdr->rem_lifetime); if (lsp && (lsp->own_lsp )) goto dontcheckadj; /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level */ /* for non broadcast, we just need to find same level adj */ if (circuit->circ_type == CIRCUIT_T_P2P) { /* If no adj, or no sharing of level */ if (!circuit->u.p2p.neighbor) { return ISIS_OK; /* Silently discard */ } else { if (((level == 1) && (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) || ((level == 2) && (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1))) return ISIS_WARNING; /* Silently discard */ else { adj = circuit->u.p2p.neighbor; } } } dontcheckadj: /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */ /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented */ /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */ /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ if (hdr->rem_lifetime == 0) { if (!lsp) { /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */ /* only needed on explicit update, eg - p2p */ if (circuit->circ_type == CIRCUIT_T_P2P) ack_lsp (hdr, circuit, level); return retval; /* FIXME: do we need a purge? */ } else { if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { /* LSP by some other system -> do 7.3.16.4 b) */ /* 7.3.16.4 b) 1) */ if (comp == LSP_NEWER) { lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area, level); /* ii */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); /* iii */ ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); /* v */ ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */ /* iv */ if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); } /* 7.3.16.4 b) 2) */ else if (comp == LSP_EQUAL) { /* i */ ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); /* ii */ if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); } /* 7.3.16.4 b) 3) */ else { ISIS_SET_FLAG (lsp->SRMflags, circuit); ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } else { /* our own LSP -> 7.3.16.4 c) */ if (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) != circuit->circuit_id || (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) == circuit->circuit_id && circuit->u.bc.is_dr[level - 1] == 1)) { lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): LSP LEN: %d\n", config.name, ntohs (lsp->lsp_header->pdu_len)); fletcher_checksum (STREAM_DATA (lsp->pdu) + 12, ntohs (lsp->lsp_header->pdu_len) - 12, 12); ISIS_FLAGS_SET_ALL (lsp->SRMflags); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08x\n", config.name, circuit->area->area_tag, rawlspid_print (hdr->lsp_id), ntohl (lsp->lsp_header->seq_num)); lsp->lsp_header->rem_lifetime = htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER)); } else { /* Got purge for own pseudo-lsp, and we are not DR */ lsp_purge_dr (lsp->lsp_header->lsp_id, circuit, level); } } } return retval; } /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a * purge */ if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { if (!lsp) { /* 7.3.16.4: initiate a purge */ lsp_purge_non_exist (hdr, circuit->area); return ISIS_OK; } /* 7.3.15.1 d) - If this is our own lsp and we have it */ /* In 7.3.16.1, If an Intermediate system R somewhere in the domain * has information that the current sequence number for source S is * "greater" than that held by S, ... */ else if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num)) { /* 7.3.16.1 */ lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1); fletcher_checksum (STREAM_DATA (lsp->pdu) + 12, ntohs (lsp->lsp_header->pdu_len) - 12, 12); ISIS_FLAGS_SET_ALL (lsp->SRMflags); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08x\n", config.name, circuit->area->area_tag, rawlspid_print (hdr->lsp_id), ntohl (lsp->lsp_header->seq_num)); lsp->lsp_header->rem_lifetime = htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER)); } } else { /* 7.3.15.1 e) - This lsp originated on another system */ /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ if ((!lsp || comp == LSP_NEWER)) { /* i */ if (lsp) { lsp_search_and_destroy (hdr->lsp_id, circuit->area->lspdb[level - 1]); /* exists, so we overwrite */ } /* * If this lsp is a frag, need to see if we have zero lsp present */ if (LSP_FRAGMENT (hdr->lsp_id) != 0) { memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT (lspid) = 0; lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]); if (!lsp0) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): Got lsp frag, while zero lsp not database\n", config.name); return ISIS_OK; } } lsp = lsp_new_from_stream_ptr (circuit->rcv_stream, ntohs (hdr->pdu_len), lsp0, circuit->area); lsp->level = level; lsp->adj = adj; lsp_insert (lsp, circuit->area->lspdb[level - 1]); /* ii */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); /* iii */ ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); /* iv */ if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); /* FIXME: v) */ } /* 7.3.15.1 e) 2) LSP equal to the one in db */ else if (comp == LSP_EQUAL) { ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area, level); if (circuit->circ_type != CIRCUIT_T_BROADCAST) { ISIS_SET_FLAG (lsp->SSNflags, circuit); } } /* 7.3.15.1 e) 3) LSP older than the one in db */ else { ISIS_SET_FLAG (lsp->SRMflags, circuit); ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } if (lsp) lsp->adj = adj; return retval; } /* * Process Sequence Numbers * ISO - 10589 * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU */ static int process_snp (int snp_type, int level, struct isis_circuit *circuit, u_char * ssnpa) { int retval = ISIS_OK; int cmp, own_lsp; int len; struct isis_complete_seqnum_hdr *chdr = NULL; struct isis_partial_seqnum_hdr *phdr = NULL; uint32_t found = 0, expected = 0; struct isis_lsp *lsp; struct lsp_entry *entry; struct pm_listnode *node, *nnode; struct pm_listnode *node2, *nnode2; struct tlvs tlvs; struct pm_list *lsp_list = NULL; struct isis_passwd *passwd; if (snp_type == ISIS_SNP_CSNP_FLAG) { /* getting the header info */ chdr = (struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); circuit->rcv_stream->getp += ISIS_CSNP_HDRLEN; len = ntohs (chdr->pdu_len); if (len < ISIS_CSNP_HDRLEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Received a CSNP with bogus length!\n", config.name); return ISIS_OK; } } else { phdr = (struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); circuit->rcv_stream->getp += ISIS_PSNP_HDRLEN; len = ntohs (phdr->pdu_len); if (len < ISIS_PSNP_HDRLEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Received a CSNP with bogus length!\n", config.name); return ISIS_OK; } } /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */ if (circuit->ext_domain) { return ISIS_OK; } /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ if (!accept_level (level, circuit->circuit_is_type)) { return ISIS_OK; } /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */ /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3 * - already checked */ /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level */ /* for broadcast circuits, snpa should be compared */ if (circuit->circ_type == CIRCUIT_T_P2P) { if (!circuit->u.p2p.neighbor) return ISIS_OK; /* Silently discard */ } /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */ /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */ memset (&tlvs, 0, sizeof (struct tlvs)); /* parse the SNP */ expected |= TLVFLAG_LSP_ENTRIES; expected |= TLVFLAG_AUTH_INFO; retval = parse_tlvs (circuit->area->area_tag, STREAM_PNT (circuit->rcv_stream), len - circuit->rcv_stream->getp, &expected, &found, &tlvs); if (retval > ISIS_WARNING) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): something went very wrong processing SNP\n", config.name); free_tlvs (&tlvs); return retval; } if (level == 1) passwd = &circuit->area->area_passwd; else passwd = &circuit->area->domain_passwd; if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) { if (passwd->type) { if (!(found & TLVFLAG_AUTH_INFO) || authentication_check (passwd, &tlvs.auth_info)) { isis_event_auth_failure (circuit->area->area_tag, "SNP authentication" " failure", phdr ? phdr->source_id : chdr->source_id); return ISIS_OK; } } } /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */ if (tlvs.lsp_entries) { for (PM_ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry)) { lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]); own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN); if (lsp) { /* 7.3.15.2 b) 1) is this LSP newer */ cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num, entry->checksum, entry->rem_lifetime); /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */ if (cmp == LSP_EQUAL) { if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */ } else if (cmp == LSP_OLDER) { ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); ISIS_SET_FLAG (lsp->SRMflags, circuit); } else { /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM * on p2p */ if (own_lsp) { lsp_inc_seqnum (lsp, ntohl (entry->seq_num)); ISIS_SET_FLAG (lsp->SRMflags, circuit); } else { ISIS_SET_FLAG (lsp->SSNflags, circuit); if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); } } } else { /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0, * insert it and set SSN on it */ if (entry->rem_lifetime && entry->checksum && entry->seq_num && memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime), 0, 0, entry->checksum, level); lsp_insert (lsp, circuit->area->lspdb[level - 1]); ISIS_SET_FLAG (lsp->SSNflags, circuit); } } } } /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */ if (snp_type == ISIS_SNP_CSNP_FLAG) { /* * Build a list from our own LSP db bounded with start_ and stop_lsp_id */ lsp_list = pm_list_new (); lsp_build_isis_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id, lsp_list, circuit->area->lspdb[level - 1]); /* Fixme: Find a better solution */ if (tlvs.lsp_entries) { for (PM_ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry)) { for (PM_ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp)) { if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0) { pm_list_delete_node (lsp_list, node2); break; } } } } /* on remaining LSPs we set SRM (neighbor knew not of) */ for (PM_ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp)) { ISIS_SET_FLAG (lsp->SRMflags, circuit); } /* lets free it */ pm_list_free (lsp_list); } free_tlvs (&tlvs); return retval; } static int process_csnp (int level, struct isis_circuit *circuit, u_char * ssnpa) { /* Sanity check - FIXME: move to correct place */ if ((stream_get_endp (circuit->rcv_stream) - stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Packet too short ( < %d)\n", config.name, ISIS_CSNP_HDRLEN); return ISIS_WARNING; } return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa); } static int process_psnp (int level, struct isis_circuit *circuit, u_char * ssnpa) { if ((stream_get_endp (circuit->rcv_stream) - stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Packet too short\n", config.name); return ISIS_WARNING; } return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa); } /* * Process ISH * ISO - 10589 * Section 8.2.2 - Receiving ISH PDUs by an intermediate system * FIXME: sample packet dump, need to figure 0x81 - looks like NLPid * 0x82 0x15 0x01 0x00 0x04 0x01 0x2c 0x59 * 0x38 0x08 0x47 0x00 0x01 0x00 0x02 0x00 * 0x03 0x00 0x81 0x01 0xcc */ static int process_is_hello (struct isis_circuit *circuit) { struct isis_adjacency *adj; int retval = ISIS_OK; u_char neigh_len; u_char *sysid; neigh_len = stream_getc (circuit->rcv_stream); sysid = STREAM_PNT (circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN; adj = circuit->u.p2p.neighbor; if (!adj) { /* 8.2.2 */ adj = isis_new_adj (sysid, NULL, 0, circuit); if (adj == NULL) return ISIS_ERROR; isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); adj->sys_type = ISIS_SYSTYPE_UNKNOWN; circuit->u.p2p.neighbor = adj; } /* 8.2.2 a) */ if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN)) { /* 8.2.2 a) 1) FIXME: adjStateChange(down) event */ /* 8.2.2 a) 2) delete the adj */ free(adj); /* 8.2.2 a) 3) create a new adj */ adj = isis_new_adj (sysid, NULL, 0, circuit); if (adj == NULL) return ISIS_ERROR; /* 8.2.2 a) 3) i */ isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); /* 8.2.2 a) 3) ii */ adj->sys_type = ISIS_SYSTYPE_UNKNOWN; /* 8.2.2 a) 4) quite meaningless */ } /* 8.2.2 b) ignore on condition */ if ((adj->adj_state == ISIS_ADJ_INITIALIZING) && (adj->sys_type == ISIS_SYSTYPE_IS)) { /* do nothing */ } else { /* 8.2.2 c) respond with a p2p IIH */ send_hello (circuit, 1); } /* 8.2.2 d) type is IS */ adj->sys_type = ISIS_SYSTYPE_IS; /* 8.2.2 e) FIXME: Circuit type of? */ return retval; } /* * PDU Dispatcher */ int isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa) { struct isis_fixed_hdr *hdr; struct esis_fixed_hdr *esis_hdr; int retval = ISIS_OK; /* * Let's first read data from stream to the header */ hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream); if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Not an IS-IS or ES-IS packet IDRP=%02x\n", config.name, hdr->idrp); return ISIS_ERROR; } /* now we need to know if this is an ISO 9542 packet and * take real good care of it, waaa! */ if (hdr->idrp == ISO9542_ESIS) { esis_hdr = (struct esis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream); stream_set_getp (circuit->rcv_stream, ESIS_FIXED_HDR_LEN); /* FIXME: Need to do some acceptence tests */ /* example length... */ switch (esis_hdr->pdu_type) { case ESH_PDU: /* FIXME */ break; case ISH_PDU: retval = process_is_hello (circuit); break; default: return ISIS_ERROR; } return retval; } else { stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN); } /* * and then process it */ if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Fixed header length = %d\n", config.name, hdr->length); return ISIS_ERROR; } if (hdr->version1 != 1) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Unsupported ISIS version %u\n", config.name, hdr->version1); return ISIS_WARNING; } /* either 6 or 0 */ if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): IDFieldLengthMismatch: ID Length field in a received PDU %u, while the parameter for this IS is %u\n", config.name, hdr->id_len, ISIS_SYS_ID_LEN); return ISIS_ERROR; } if (hdr->version2 != 1) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Unsupported ISIS version %u\n", config.name, hdr->version2); return ISIS_WARNING; } /* either 3 or 0 */ if ((hdr->max_area_addrs != 0) && (hdr->max_area_addrs != isis->max_area_addrs)) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %u while the parameter for this IS is %u\n", config.name, hdr->max_area_addrs, isis->max_area_addrs); return ISIS_ERROR; } switch (hdr->pdu_type) { case P2P_HELLO: retval = process_p2p_hello (circuit); if (retval <= ISIS_WARNING) send_hello(circuit, 1); break; case L1_LINK_STATE: retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa); break; case L2_LINK_STATE: retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa); break; case L1_COMPLETE_SEQ_NUM: retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa); break; case L2_COMPLETE_SEQ_NUM: retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa); break; case L1_PARTIAL_SEQ_NUM: retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa); break; case L2_PARTIAL_SEQ_NUM: retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa); break; default: return ISIS_ERROR; } return retval; } /* filling of the fixed isis header */ void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type) { memset (hdr, 0, sizeof (struct isis_fixed_hdr)); hdr->idrp = ISO10589_ISIS; switch (pdu_type) { case L1_LAN_HELLO: case L2_LAN_HELLO: hdr->length = ISIS_LANHELLO_HDRLEN; break; case P2P_HELLO: hdr->length = ISIS_P2PHELLO_HDRLEN; break; case L1_LINK_STATE: case L2_LINK_STATE: hdr->length = ISIS_LSP_HDR_LEN; break; case L1_COMPLETE_SEQ_NUM: case L2_COMPLETE_SEQ_NUM: hdr->length = ISIS_CSNP_HDRLEN; break; case L1_PARTIAL_SEQ_NUM: case L2_PARTIAL_SEQ_NUM: hdr->length = ISIS_PSNP_HDRLEN; break; default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): fill_fixed_hdr(): unknown pdu type %d\n", config.name, pdu_type); return; } hdr->length += ISIS_FIXED_HDR_LEN; hdr->pdu_type = pdu_type; hdr->version1 = 1; hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */ hdr->version2 = 1; hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */ } /* * SEND SIDE */ static void fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type, struct stream *stream) { fill_fixed_hdr (hdr, pdu_type); stream_putc (stream, hdr->idrp); stream_putc (stream, hdr->length); stream_putc (stream, hdr->version1); stream_putc (stream, hdr->id_len); stream_putc (stream, hdr->pdu_type); stream_putc (stream, hdr->version2); stream_putc (stream, hdr->reserved); stream_putc (stream, hdr->max_area_addrs); return; } int send_hello (struct isis_circuit *circuit, int level) { struct isis_fixed_hdr fixed_hdr; struct isis_lan_hello_hdr hello_hdr; struct isis_p2p_hello_hdr p2p_hello_hdr; u_int32_t interval; unsigned long len_pointer, length; int retval; if (circuit->interface->mtu == 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit has zero MTU\n", config.name); return ISIS_WARNING; } if (!circuit->snd_stream) circuit->snd_stream = stream_new ( ISO_MTU(circuit) ); else stream_reset (circuit->snd_stream); if (circuit->circ_type == CIRCUIT_T_P2P) fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream); /* * Fill LAN Level 1 or 2 Hello PDU header */ memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); interval = circuit->hello_multiplier[level - 1] * circuit->hello_interval[level - 1]; /* If we are the DIS then hello interval is divided by three, as is the hold-timer */ if (circuit->u.bc.is_dr[level - 1]) interval=interval/3; if (interval > USHRT_MAX) interval = USHRT_MAX; hello_hdr.circuit_t = circuit->circuit_is_type; memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN); hello_hdr.hold_time = htons ((u_int16_t) interval); hello_hdr.pdu_len = 0; /* Update the PDU Length later */ len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN; /* copy the shared part of the hello to the p2p hello if needed */ if (circuit->circ_type == CIRCUIT_T_P2P) { memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN); p2p_hello_hdr.local_id = circuit->circuit_id; /* FIXME: need better understanding */ stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN); } else { hello_hdr.prio = circuit->u.bc.priority[level - 1]; if (level == 1 /* && circuit->u.bc.l1_desig_is */) { memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); } else if (level == 2 /* && circuit->u.bc.l2_desig_is */) { memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); } stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN); } /* * Then the variable length part */ /* add circuit password */ if (circuit->passwd.type) if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, circuit->passwd.passwd, circuit->snd_stream)) return ISIS_WARNING; /* Area Addresses TLV */ assert (circuit->area); if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) return ISIS_WARNING; /* Protocols Supported TLV */ if (circuit->nlpids.count > 0) if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) return ISIS_WARNING; /* IP interface Address TLV */ if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) return ISIS_WARNING; /* IPv6 Interface Address TLV */ if (circuit->ipv6_router && circuit->ipv6_link && circuit->ipv6_link->count > 0) if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream)) return ISIS_WARNING; /* We should always pad hellos, even on p2p links */ /* if (circuit->u.bc.pad_hellos) */ if (tlv_add_padding (circuit->snd_stream)) return ISIS_WARNING; length = stream_get_endp (circuit->snd_stream); /* Update PDU length */ stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); retval = circuit->tx (circuit, level); if (retval) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): sending of LAN Level %d Hello failed\n", config.name, level); return retval; } int send_p2p_hello (struct thread *thread) { struct isis_circuit *circuit; circuit = THREAD_ARG (thread); assert (circuit); circuit->u.p2p.t_send_p2p_hello = NULL; send_hello (circuit, 1); /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello, circuit, isis_jitter (circuit->hello_interval[1], IIH_JITTER)); return ISIS_OK; } int ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, int level) { unsigned long lenp; int retval; u_int16_t length; struct isis_fixed_hdr fixed_hdr; if (!circuit->snd_stream) circuit->snd_stream = stream_new ( ISO_MTU(circuit) ); else stream_reset (circuit->snd_stream); // fill_llc_hdr (stream); if (level == 1) fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, circuit->snd_stream); else fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM, circuit->snd_stream); lenp = stream_get_endp (circuit->snd_stream); stream_putw (circuit->snd_stream, 0); /* PDU length */ stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); stream_putc (circuit->snd_stream, circuit->idx); stream_putc (circuit->snd_stream, 9); /* code */ stream_putc (circuit->snd_stream, 16); /* len */ stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime)); stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); stream_putl (circuit->snd_stream, ntohl (hdr->seq_num)); stream_putw (circuit->snd_stream, ntohs (hdr->checksum)); length = (u_int16_t) stream_get_endp (circuit->snd_stream); /* Update PDU length */ stream_putw_at (circuit->snd_stream, lenp, length); retval = circuit->tx (circuit, level); return retval; } int isis_send_pdu_p2p (struct isis_circuit *circuit, int level) { int written = 1; struct sockaddr_ll sa; stream_set_getp (circuit->snd_stream, 0); memset (&sa, 0, sizeof (struct sockaddr_ll)); sa.sll_family = 0; /* XXX: let's see how far we get with this */ sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); sa.sll_ifindex = if_nametoindex(config.nfacctd_isis_iface); sa.sll_halen = ETH_ALEN; if (level == 1) memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); else memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); /* lets try correcting the protocol */ sa.sll_protocol = htons (0x00FE); written = sendto (circuit->fd, circuit->snd_stream->data, stream_get_endp (circuit->snd_stream), 0, (struct sockaddr *) &sa, sizeof (struct sockaddr_ll)); (void)written; //TODO treat error? return ISIS_OK; } int build_psnp (int level, struct isis_circuit *circuit, struct pm_list *lsps) { struct isis_fixed_hdr fixed_hdr; unsigned long lenp; u_int16_t length; int retval = 0; struct isis_lsp *lsp; struct isis_passwd *passwd; struct pm_listnode *node; if (level == 1) fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, circuit->snd_stream); else fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM, circuit->snd_stream); /* * Fill Level 1 or 2 Partial Sequence Numbers header */ lenp = stream_get_endp (circuit->snd_stream); stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */ stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); stream_putc (circuit->snd_stream, circuit->idx); /* * And TLVs */ if (level == 1) passwd = &circuit->area->area_passwd; else passwd = &circuit->area->domain_passwd; if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) if (passwd->type) retval = tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, circuit->snd_stream); if (!retval && lsps) { retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); } if (config.nfacctd_isis_msglog) { for (PM_ALL_LIST_ELEMENTS_RO (lsps, node, lsp)) { if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): PSNP entry %s, seq 0x%08x," " cksum 0x%04x, lifetime %us\n", config.name, circuit->area->area_tag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); } } length = (u_int16_t) stream_get_endp (circuit->snd_stream); assert (length >= ISIS_PSNP_HDRLEN); /* Update PDU length */ stream_putw_at (circuit->snd_stream, lenp, length); return ISIS_OK; } /* * 7.3.15.4 action on expiration of partial SNP interval * level 1 */ /* XXX: debugs in this function should be a-la bgp_daemon_msglog */ int send_psnp (int level, struct isis_circuit *circuit) { int retval = ISIS_OK; struct isis_lsp *lsp; struct pm_list *list = NULL; struct pm_listnode *node; if ((circuit->circ_type == CIRCUIT_T_BROADCAST && !circuit->u.bc.is_dr[level - 1]) || circuit->circ_type != CIRCUIT_T_BROADCAST) { if (circuit->area->lspdb[level - 1] && dict_count (circuit->area->lspdb[level - 1]) > 0) { list = pm_list_new (); lsp_build_isis_list_ssn (circuit, list, circuit->area->lspdb[level - 1]); if (pm_listcount (list) > 0) { if (circuit->snd_stream == NULL) circuit->snd_stream = stream_new (ISO_MTU (circuit)); else stream_reset (circuit->snd_stream); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld\n", config.name, circuit->area->area_tag, level, circuit->interface->name, /* FIXME: use %z when we stop supporting old * compilers. */ (unsigned long) STREAM_SIZE (circuit->snd_stream)); retval = build_psnp (level, circuit, list); if (retval == ISIS_OK) retval = circuit->tx (circuit, level); if (retval == ISIS_OK) { /* * sending succeeded, we can clear SSN flags of this circuit * for the LSPs in list */ for (PM_ALL_LIST_ELEMENTS_RO (list, node, lsp)) ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } pm_list_delete (list); } } return retval; } /* XXX: debugs in this function should be a-la bgp_daemon_msglog */ int build_csnp (int level, u_char * start, u_char * stop, struct pm_list *lsps, struct isis_circuit *circuit) { struct isis_fixed_hdr fixed_hdr; struct isis_passwd *passwd; int retval = ISIS_OK; unsigned long lenp; u_int16_t length; if (level == 1) fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, circuit->snd_stream); else fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM, circuit->snd_stream); /* * Fill Level 1 or 2 Complete Sequence Numbers header */ lenp = stream_get_endp (circuit->snd_stream); stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */ /* no need to send the source here, it is always us if we csnp */ stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); /* with zero circuit id - ref 9.10, 9.11 */ stream_putc (circuit->snd_stream, 0x00); stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2); stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2); /* * And TLVs */ if (level == 1) passwd = &circuit->area->area_passwd; else passwd = &circuit->area->domain_passwd; if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) if (passwd->type) retval = tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, circuit->snd_stream); if (!retval && lsps) { retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); } length = (u_int16_t) stream_get_endp (circuit->snd_stream); assert (length >= ISIS_CSNP_HDRLEN); /* Update PU length */ stream_putw_at (circuit->snd_stream, lenp, length); return retval; } /* * FIXME: support multiple CSNPs */ /* XXX: debugs in this function should be a-la bgp_daemon_msglog */ int send_csnp (struct isis_circuit *circuit, int level) { int retval = ISIS_OK; u_char start[ISIS_SYS_ID_LEN + 2]; u_char stop[ISIS_SYS_ID_LEN + 2]; struct pm_list *list = NULL; struct pm_listnode *node; struct isis_lsp *lsp; memset (start, 0x00, ISIS_SYS_ID_LEN + 2); memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); if (circuit->area->lspdb[level - 1] && dict_count (circuit->area->lspdb[level - 1]) > 0) { list = pm_list_new (); lsp_build_list (start, stop, list, circuit->area->lspdb[level - 1]); if (circuit->snd_stream == NULL) circuit->snd_stream = stream_new (ISO_MTU (circuit)); else stream_reset (circuit->snd_stream); retval = build_csnp (level, start, stop, list, circuit); if (config.nfacctd_isis_msglog) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld\n", config.name, circuit->area->area_tag, level, circuit->interface->name, /* FIXME: use %z when we stop supporting old compilers. */ (unsigned long) STREAM_SIZE (circuit->snd_stream)); for (PM_ALL_LIST_ELEMENTS_RO (list, node, lsp)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Snp (%s): CSNP entry %s, seq 0x%08x," " cksum 0x%04x, lifetime %us\n", config.name, circuit->area->area_tag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (lsp->lsp_header->seq_num), ntohs (lsp->lsp_header->checksum), ntohs (lsp->lsp_header->rem_lifetime)); } } pm_list_delete (list); if (retval == ISIS_OK) retval = circuit->tx (circuit, level); } return retval; } pmacct-1.7.8/src/isis/isis_lsp.h0000644000175000017500000001121014354105275015541 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_lsp.h * LSP processing * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_LSP_H_ #define _ISIS_LSP_H_ /* The grand plan is to support 1024 circuits so we have 32*32 bit flags * the support will be achived using the newest drafts */ #define ISIS_MAX_CIRCUITS 32 /* = 1024 - FIXME:defined in flags.h as well */ /* Structure for isis_lsp, this structure will only support the fixed * System ID (Currently 6) (atleast for now). In order to support more * We will have to split the header into two parts, and for readability * sake it should better be avoided */ struct isis_lsp { struct isis_fixed_hdr *isis_header; /* normally equals pdu */ struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */ struct stream *pdu; /* full pdu lsp */ union { struct pm_list *frags; struct isis_lsp *zero_lsp; } lspu; u_int32_t SRMflags[ISIS_MAX_CIRCUITS]; u_int32_t SSNflags[ISIS_MAX_CIRCUITS]; u_int32_t rexmit_queue[ISIS_MAX_CIRCUITS]; int level; /* L1 or L2? */ int purged; /* have purged this one */ int scheduled; /* scheduled for sending */ time_t installed; time_t last_generated; time_t last_sent; int own_lsp; #ifdef TOPOLOGY_GENERATE int from_topology; struct thread *t_lsp_top_ref; #endif /* used for 60 second counting when rem_lifetime is zero */ int age_out; struct isis_adjacency *adj; /* FIXME: For now only topology LSP's use this. Is it helpful for others? */ struct isis_area *area; struct tlvs tlv_data; /* Simplifies TLV access */ }; #define LSP_EQUAL 1 #define LSP_NEWER 2 #define LSP_OLDER 3 #define LSP_PSEUDO_ID(I) ((I)[ISIS_SYS_ID_LEN]) #define LSP_FRAGMENT(I) ((I)[ISIS_SYS_ID_LEN + 1]) #define OWNLSPID(I) \ memcpy ((I), isis->sysid, ISIS_SYS_ID_LEN);\ (I)[ISIS_SYS_ID_LEN] = 0;\ (I)[ISIS_SYS_ID_LEN + 1] = 0 extern dict_t *lsp_db_init (); extern void lsp_db_destroy (dict_t *); extern int lsp_l1_generate (struct isis_area *); extern int lsp_l2_generate (struct isis_area *); extern int lsp_refresh_l1 (struct thread *); extern int lsp_refresh_l2 (struct thread *); extern int lsp_regenerate_schedule (struct isis_area *); extern int lsp_l1_pseudo_generate (struct isis_circuit *); extern int lsp_l2_pseudo_generate (struct isis_circuit *); extern int lsp_l1_refresh_pseudo (struct thread *); extern int lsp_l2_refresh_pseudo (struct thread *); extern int isis_lsp_authinfo_check (struct stream *, struct isis_area *, int, struct isis_passwd *); extern struct isis_lsp *lsp_new (u_char *, u_int16_t, u_int32_t, u_int8_t, u_int16_t, int); extern struct isis_lsp *lsp_new_from_stream_ptr (struct stream *, u_int16_t, struct isis_lsp *, struct isis_area *); extern void lsp_insert (struct isis_lsp *, dict_t *); extern struct isis_lsp *lsp_search (u_char *, dict_t *); extern void lsp_build_list (u_char *, u_char *, struct pm_list *, dict_t *); extern void lsp_build_list_nonzero_ht (u_char *, u_char *, struct pm_list *, dict_t *); extern void lsp_build_list_ssn (struct isis_circuit *, struct pm_list *, dict_t *); extern void lsp_build_isis_list_nonzero_ht (u_char *, u_char *, struct pm_list *, dict_t *); extern void lsp_build_isis_list_ssn (struct isis_circuit *, struct pm_list *, dict_t *); extern void lsp_search_and_destroy (u_char *, dict_t *); extern void lsp_purge_dr (u_char *, struct isis_circuit *, int); extern void lsp_purge_non_exist (struct isis_link_state_hdr *, struct isis_area *); extern int lsp_id_cmp (u_char *, u_char *); extern int lsp_compare (char *, struct isis_lsp *, u_int32_t, u_int16_t, u_int16_t); extern void lsp_update (struct isis_lsp *, struct isis_link_state_hdr *, struct stream *, struct isis_area *, int); extern void lsp_inc_seqnum (struct isis_lsp *, u_int32_t); extern const char *lsp_bits2string (u_char *); #endif /* ISIS_LSP */ pmacct-1.7.8/src/isis/isis_flags.h0000644000175000017500000000370314354105275016047 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_flags.h * Routines for manipulation of SSN and SRM flags * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_FLAGS_H_ #define _ISIS_FLAGS_H_ /* The grand plan is to support 1024 circuits so we have 32*32 bit flags * the support will be achived using the newest drafts */ #define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well */ extern void flags_initialize (struct flags *); extern struct flags *new_flags (int); extern long int flags_get_index (struct flags *); extern void flags_free_index (struct flags *, long int); extern int flags_any_set (u_int32_t *); #define ISIS_SET_FLAG(F,C) \ F[C->idx>>5] |= (1<<(C->idx & 0x1F)); #define ISIS_CLEAR_FLAG(F,C) \ F[C->idx>>5] &= ~(1<<(C->idx & 0x1F)); #define ISIS_CHECK_FLAG(F, C) F[(C)->idx>>5] & (1<<(C->idx & 0x1F)) /* sets all u_32int_t flags to 1 */ #define ISIS_FLAGS_SET_ALL(FLAGS) \ memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4); #define ISIS_FLAGS_CLEAR_ALL(FLAGS) \ memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4); #endif /* _ISIS_FLAGS_H_ */ pmacct-1.7.8/src/isis/isis_csm.c0000644000175000017500000001230314354105275015524 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_csm.c * IS-IS circuit state machine * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "hash.h" #include "prefix.h" #include "dict.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_constants.h" #include "isis_adjacency.h" #include "isis_flags.h" #include "isisd.h" #include "isis_csm.h" #include "isis_events.h" extern struct isis *isis; static const char *csm_statestr[] = { "C_STATE_NA", "C_STATE_INIT", "C_STATE_CONF", "C_STATE_UP" }; #define STATE2STR(S) csm_statestr[S] static const char *csm_eventstr[] = { "NO_STATE", "ISIS_ENABLE", "IF_UP_FROM_Z", "ISIS_DISABLE", "IF_DOWN_FROM_Z", }; #define EVENT2STR(E) csm_eventstr[E] // XXX: isis_circuit_if_add() and isis_circuit_if_del commented out struct isis_circuit * isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) { int old_state; old_state = circuit ? circuit->state : C_STATE_NA; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): CSM_EVENT: %s\n", config.name, EVENT2STR (event)); switch (old_state) { case C_STATE_NA: if (circuit) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Non-null circuit while state C_STATE_NA\n", config.name); switch (event) { case ISIS_ENABLE: circuit = isis_circuit_new (); isis_circuit_configure (circuit, (struct isis_area *) arg); circuit->state = C_STATE_CONF; break; case IF_UP_FROM_Z: circuit = isis_circuit_new (); // isis_circuit_if_add (circuit, (struct interface *) arg); pm_listnode_add (isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; case ISIS_DISABLE: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already disabled\n", config.name); case IF_DOWN_FROM_Z: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already disconnected\n", config.name); break; } break; case C_STATE_INIT: switch (event) { case ISIS_ENABLE: isis_circuit_configure (circuit, (struct isis_area *) arg); isis_circuit_up (circuit); circuit->state = C_STATE_UP; isis_event_circuit_state_change (circuit, 1); pm_listnode_delete (isis->init_circ_list, circuit); break; case IF_UP_FROM_Z: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already connected\n", config.name); break; case ISIS_DISABLE: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already disabled\n", config.name); break; case IF_DOWN_FROM_Z: // isis_circuit_if_del (circuit); pm_listnode_delete (isis->init_circ_list, circuit); isis_circuit_del (circuit); circuit = NULL; break; } break; case C_STATE_CONF: switch (event) { case ISIS_ENABLE: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already enabled\n", config.name); break; case IF_UP_FROM_Z: // isis_circuit_if_add (circuit, (struct interface *) arg); isis_circuit_up (circuit); circuit->state = C_STATE_UP; isis_event_circuit_state_change (circuit, 1); break; case ISIS_DISABLE: isis_circuit_deconfigure (circuit, (struct isis_area *) arg); isis_circuit_del (circuit); circuit = NULL; break; case IF_DOWN_FROM_Z: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already disconnected\n", config.name); break; } break; case C_STATE_UP: switch (event) { case ISIS_ENABLE: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already configured\n", config.name); break; case IF_UP_FROM_Z: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): circuit already connected\n", config.name); break; case ISIS_DISABLE: isis_circuit_deconfigure (circuit, (struct isis_area *) arg); pm_listnode_add (isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; isis_event_circuit_state_change (circuit, 0); break; case IF_DOWN_FROM_Z: // isis_circuit_if_del (circuit); circuit->state = C_STATE_CONF; isis_event_circuit_state_change (circuit, 0); break; } break; default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Invalid circuit state %d\n", config.name, old_state); } Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): CSM_STATE_CHANGE: %s -> %s \n", config.name, STATE2STR (old_state), circuit ? STATE2STR (circuit->state) : STATE2STR (C_STATE_NA)); return circuit; } pmacct-1.7.8/src/isis/isis_adjacency.h0000644000175000017500000000734314354105275016700 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_adjacency.h * IS-IS adjacency handling * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_ADJACENCY_H_ #define _ISIS_ADJACENCY_H_ enum isis_adj_usage { ISIS_ADJ_NONE, ISIS_ADJ_LEVEL1, ISIS_ADJ_LEVEL2, ISIS_ADJ_LEVEL1AND2 }; enum isis_system_type { ISIS_SYSTYPE_UNKNOWN, ISIS_SYSTYPE_ES, ISIS_SYSTYPE_IS, ISIS_SYSTYPE_L1_IS, ISIS_SYSTYPE_L2_IS }; enum isis_adj_state { ISIS_ADJ_INITIALIZING, ISIS_ADJ_UP, ISIS_ADJ_DOWN }; /* * we use the following codes to give an indication _why_ * a specific adjacency is up or down */ enum isis_adj_updown_reason { ISIS_ADJ_REASON_SEENSELF, ISIS_ADJ_REASON_AREA_MISMATCH, ISIS_ADJ_REASON_HOLDTIMER_EXPIRED, ISIS_ADJ_REASON_AUTH_FAILED, ISIS_ADJ_REASON_CHECKSUM_FAILED }; #define DIS_RECORDS 8 /* keep the last 8 DIS state changes on record */ struct isis_dis_record { int dis; /* is our neighbor the DIS ? */ time_t last_dis_change; /* timestamp for last dis change */ }; struct isis_adjacency { u_char snpa[ETH_ALEN]; /* NeighbourSNPAAddress */ u_char sysid[ISIS_SYS_ID_LEN]; /* neighbourSystemIdentifier */ u_char lanid[ISIS_SYS_ID_LEN + 1]; /* LAN id on bcast circuits */ int dischanges[ISIS_LEVELS]; /* how many DIS changes ? */ /* an array of N levels for M records */ struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS]; enum isis_adj_state adj_state; /* adjacencyState */ enum isis_adj_usage adj_usage; /* adjacencyUsage */ struct pm_list *area_addrs; /* areaAdressesOfNeighbour */ struct nlpids nlpids; /* protocols spoken ... */ struct pm_list *ipv4_addrs; struct pm_list *ipv6_addrs; u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */ int circuit_t; /* from hello PDU hdr */ int level; /* level (1 or 2) */ enum isis_system_type sys_type; /* neighbourSystemType */ u_int16_t hold_time; /* entryRemainingTime */ u_int32_t last_upd; u_int32_t last_flap; /* last time the adj flapped */ int flaps; /* number of adjacency flaps */ struct timeval expire; /* expiration timestamp */ struct isis_circuit *circuit; /* back pointer */ }; extern struct isis_adjacency *isis_adj_lookup (u_char *, struct pm_list *); extern struct isis_adjacency *isis_adj_lookup_snpa (u_char *, struct pm_list *); extern struct isis_adjacency *isis_new_adj (u_char *, u_char *, int, struct isis_circuit *); extern void isis_delete_adj (struct isis_adjacency *, struct pm_list *); extern void isis_adj_state_change (struct isis_adjacency *, enum isis_adj_state, const char *); extern int isis_adj_expire (struct isis_adjacency *); extern void isis_adj_build_neigh_list (struct pm_list *, struct pm_list *); extern void isis_adj_build_up_list (struct pm_list *, struct pm_list *); extern void isis_adjdb_iterate (struct pm_list *, void (*func) (struct isis_adjacency *, void *), void *); #endif /* _ISIS_ADJACENCY_H_ */ pmacct-1.7.8/src/isis/isis_route.h0000644000175000017500000000353014354105275016107 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_route.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * based on ../ospf6d/ospf6_route.[ch] * by Yasuhiro Ohara * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_ROUTE_H_ #define _ISIS_ROUTE_H_ struct isis_nexthop6 { unsigned int ifindex; struct in6_addr ip6; unsigned int lock; }; struct isis_nexthop { unsigned int ifindex; struct in_addr ip; unsigned int lock; }; struct isis_route_info { #define ISIS_ROUTE_FLAG_ZEBRA_SYNC 0x01 #define ISIS_ROUTE_FLAG_ACTIVE 0x02 u_char flag; u_int32_t cost; u_int32_t depth; struct pm_list *nexthops; struct pm_list *nexthops6; }; extern struct isis_route_info *isis_route_create (struct isis_prefix *, u_int32_t, u_int32_t, struct pm_list *, struct isis_area *, int); extern void isis_route_validate_table (struct isis_area *, struct route_table *); extern void isis_route_validate_merge (struct isis_area *, int); #endif /* _ISIS_ROUTE_H_ */ pmacct-1.7.8/src/isis/dict.h0000644000175000017500000001057314354105275014652 0ustar paolopaolo/* * Dictionary Abstract Data Type * Copyright (C) 1997 Kaz Kylheku * * Free Software License: * * All rights are reserved by the author, with the following exceptions: * Permission is granted to freely reproduce and distribute this software, * possibly in exchange for a fee, provided that this copyright notice appears * intact. Permission is also granted to adapt this software to produce * derivative works, as long as the modified versions carry this copyright * notice and additional notices stating that the work has been modified. * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. * * $Id$ * $Name$ */ #ifndef _DICT_H_ #define _DICT_H_ #include #ifdef KAZLIB_SIDEEFFECT_DEBUG #include "sfx.h" #endif typedef unsigned long dictcount_t; #define DICTCOUNT_T_MAX ULONG_MAX /* * The dictionary is implemented as a red-black tree */ typedef enum { dnode_red, dnode_black } dnode_color_t; typedef struct dnode_t { #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) struct dnode_t *dict_left; struct dnode_t *dict_right; struct dnode_t *dict_parent; dnode_color_t dict_color; const void *dict_key; void *dict_data; #else int dict_dummy; #endif } dnode_t; typedef int (*dict_comp_t)(const void *, const void *); typedef dnode_t *(*dnode_alloc_t)(void *); typedef void (*dnode_free_t)(dnode_t *, void *); typedef struct dict_t { #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) dnode_t dict_nilnode; dictcount_t dict_nodecount; dictcount_t dict_maxcount; dict_comp_t dict_compare; dnode_alloc_t dict_allocnode; dnode_free_t dict_freenode; void *dict_context; int dict_dupes; #else int dict_dummmy; #endif } dict_t; typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); typedef struct dict_load_t { #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) dict_t *dict_dictptr; dnode_t dict_nilnode; #else int dict_dummmy; #endif } dict_load_t; extern dict_t *dict_create(dictcount_t, dict_comp_t); extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *); extern void dict_destroy(dict_t *); extern void dict_free_nodes(dict_t *); extern void dict_free(dict_t *); extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t); extern void dict_init_like(dict_t *, const dict_t *); extern int dict_verify(dict_t *); extern int dict_similar(const dict_t *, const dict_t *); extern dnode_t *dict_lookup(dict_t *, const void *); extern dnode_t *dict_lower_bound(dict_t *, const void *); extern dnode_t *dict_upper_bound(dict_t *, const void *); extern void dict_insert(dict_t *, dnode_t *, const void *); extern dnode_t *dict_delete(dict_t *, dnode_t *); extern int dict_alloc_insert(dict_t *, const void *, void *); extern void dict_delete_free(dict_t *, dnode_t *); extern dnode_t *dict_first(dict_t *); extern dnode_t *dict_last(dict_t *); extern dnode_t *dict_next(dict_t *, dnode_t *); extern dnode_t *dict_prev(dict_t *, dnode_t *); extern dictcount_t dict_count(dict_t *); extern int dict_isempty(dict_t *); extern int dict_isfull(dict_t *); extern int dict_contains(dict_t *, dnode_t *); extern void dict_allow_dupes(dict_t *); extern int dnode_is_in_a_dict(dnode_t *); extern dnode_t *dnode_create(void *); extern dnode_t *dnode_init(dnode_t *, void *); extern void dnode_destroy(dnode_t *); extern void *dnode_get(dnode_t *); extern const void *dnode_getkey(dnode_t *); extern void dnode_put(dnode_t *, void *); extern void dict_process(dict_t *, void *, dnode_process_t); extern void dict_load_begin(dict_load_t *, dict_t *); extern void dict_load_next(dict_load_t *, dnode_t *, const void *); extern void dict_load_end(dict_load_t *); extern void dict_merge(dict_t *, dict_t *); #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) #ifdef KAZLIB_SIDEEFFECT_DEBUG #define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount) #else #define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount) #endif #define dict_count(D) ((D)->dict_nodecount) #define dict_isempty(D) ((D)->dict_nodecount == 0) #define dnode_get(N) ((N)->dict_data) #define dnode_getkey(N) ((N)->dict_key) #define dnode_put(N, X) ((N)->dict_data = (X)) #endif #endif pmacct-1.7.8/src/isis/isis_common.h0000644000175000017500000000346514354105275016250 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_common.h * some common data structures * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_COMMON_H_ #define _ISIS_COMMON_H_ /* * Area Address */ struct area_addr { u_char addr_len; u_char area_addr[20]; }; struct isis_passwd { u_char len; #define ISIS_PASSWD_TYPE_UNUSED 0 #define ISIS_PASSWD_TYPE_CLEARTXT 1 #define ISIS_PASSWD_TYPE_PRIVATE 255 u_char type; /* Authenticate SNPs? */ #define SNP_AUTH_SEND 0x01 #define SNP_AUTH_RECV 0x02 u_char snp_auth; u_char passwd[255]; }; /* * (Dynamic) Hostname * one struct for cache list * one struct for LSP TLV */ struct hostname { u_char namelen; u_char name[255]; }; /* * Supported Protocol IDs */ struct nlpids { u_char count; u_char nlpids[4]; /* FIXME: enough ? */ }; /* * Flags structure for SSN and SRM flags */ struct flags { int maxindex; struct pm_list *free_idcs; }; #endif /* _ISIS_COMMON_H_ */ pmacct-1.7.8/src/isis/sockunion.h0000644000175000017500000000664714354105275015746 0ustar paolopaolo/* * Socket union header. * Copyright (c) 1997 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _SOCKUNION_H_ #define _SOCKUNION_H_ #if 0 union sockunion { struct sockinet { u_char si_len; u_char si_family; u_short si_port; } su_si; struct sockaddr_in su_sin; struct sockaddr_in6 su_sin6; }; #define su_len su_si.si_len #define su_family su_si.si_family #define su_port su_si.si_port #endif /* 0 */ union sockunion { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; }; enum connect_result { connect_error, connect_success, connect_in_progress }; /* Default address family. */ #define AF_INET_UNION AF_INET6 /* Sockunion address string length. Same as INET6_ADDRSTRLEN. */ #define SU_ADDRSTRLEN 46 /* Macro to set link local index to the IPv6 address. For KAME IPv6 stack. */ #ifdef KAME #define IN6_LINKLOCAL_IFINDEX(a) ((a).s6_addr[2] << 8 | (a).s6_addr[3]) #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ do { \ (a).s6_addr[2] = ((i) >> 8) & 0xff; \ (a).s6_addr[3] = (i) & 0xff; \ } while (0) #else #define IN6_LINKLOCAL_IFINDEX(a) #define SET_IN6_LINKLOCAL_IFINDEX(a, i) #endif /* KAME */ /* shortcut macro to specify address field of struct sockaddr */ #define sock2ip(X) (((struct sockaddr_in *)(X))->sin_addr.s_addr) #define sock2ip6(X) (((struct sockaddr_in6 *)(X))->sin6_addr.s6_addr) #define sockunion_family(X) (X)->sa.sa_family /* Prototypes. */ extern int str2sockunion (const char *, union sockunion *); extern const char *sockunion2str (union sockunion *, char *, size_t); extern int sockunion_cmp (union sockunion *, union sockunion *); extern int sockunion_same (union sockunion *, union sockunion *); extern char *sockunion_su2str (union sockunion *); extern union sockunion *sockunion_str2su (const char *); extern struct in_addr sockunion_get_in_addr (union sockunion *); extern int sockunion_accept (int sock, union sockunion *); extern int sockunion_stream_socket (union sockunion *); extern int sockopt_reuseaddr (int); extern int sockopt_reuseport (int); extern int sockunion_bind (int sock, union sockunion *, unsigned short, union sockunion *); extern int sockopt_ttl (int, int, int); extern int sockopt_minttl (int, int, int); extern int sockopt_cork (int, int); extern int sockunion_socket (union sockunion *); extern const char *inet_sutop (union sockunion *, char *); extern enum connect_result sockunion_connect (int, union sockunion *, unsigned short, unsigned int); extern union sockunion *sockunion_getsockname (int); extern union sockunion *sockunion_getpeername (int); extern union sockunion *sockunion_dup (union sockunion *); extern void sockunion_free (union sockunion *); #endif /* _SOCKUNION_H_ */ pmacct-1.7.8/src/isis/isis_pdu.h0000644000175000017500000002341314354105275015543 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_pdu.h * PDU processing * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_PDU_H_ #define _ISIS_PDU_H_ /* * ISO 9542 - 7.5,7.6 * * ES to IS Fixed Header * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Intradomain Routeing Protocol Discriminator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Length Indicator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Version/Protocol ID extension | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved = 0 | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | 0 | 0 | 0 | PDU Type | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Holding Time | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Checksum | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct esis_fixed_hdr { u_char idrp; u_char length; u_char version; u_char id_len; u_char pdu_type; u_int16_t holdtime; u_int16_t checksum; } __attribute__ ((packed)); #define ESIS_FIXED_HDR_LEN 9 #define ESH_PDU 2 #define ISH_PDU 4 #define RD_PDU 5 /* * IS to IS Fixed Header * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Intradomain Routeing Protocol Discriminator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Length Indicator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Version/Protocol ID extension | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | R | R | R | PDU Type | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Version | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Maximum Area Addresses | * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct isis_fixed_hdr { u_char idrp; u_char length; u_char version1; u_char id_len; u_char pdu_type; u_char version2; u_char reserved; u_char max_area_addrs; }; #define ISIS_FIXED_HDR_LEN 8 /* * IS-IS PDU types. */ #define L1_LAN_HELLO 15 #define L2_LAN_HELLO 16 /* * L1 and L2 LAN IS to IS Hello PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | Circuit Type | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Source ID + id_len * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Holding Time | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | PDU Lenght | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | R | Priority | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LAN ID | id_len + 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct isis_lan_hello_hdr { u_char circuit_t; u_char source_id[ISIS_SYS_ID_LEN]; u_int16_t hold_time; u_int16_t pdu_len; u_char prio; u_char lan_id[ISIS_SYS_ID_LEN + 1]; } __attribute__ ((packed)); #define ISIS_LANHELLO_HDRLEN 19 #define P2P_HELLO 17 /* * Point-to-point IS to IS hello PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | Circuit Type | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Source ID + id_len * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Holding Time + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + PDU Lenght + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Local Circuit ID | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct isis_p2p_hello_hdr { u_char circuit_t; u_char source_id[ISIS_SYS_ID_LEN]; u_int16_t hold_time; u_int16_t pdu_len; u_char local_id; } __attribute__ ((packed)); #define ISIS_P2PHELLO_HDRLEN 12 #define L1_LINK_STATE 18 #define L2_LINK_STATE 20 /* * L1 and L2 IS to IS link state PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ * + PDU Length + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Remaining Lifetime + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LSP ID | id_len + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Sequence Number + 4 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Checksum + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | P | ATT |LSPDBOL| ISTYPE | * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct isis_link_state_hdr { u_int16_t pdu_len; u_int16_t rem_lifetime; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; u_int32_t seq_num; u_int16_t checksum; u_int8_t lsp_bits; } __attribute__ ((packed)); #define ISIS_LSP_HDR_LEN 19 #define L1_COMPLETE_SEQ_NUM 24 #define L2_COMPLETE_SEQ_NUM 25 /* * L1 and L2 IS to IS complete sequence numbers PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ * + PDU Lenght + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Source ID + id_len + 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Start LSP ID + id_len + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + End LSP ID + id_len + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ struct isis_complete_seqnum_hdr { u_int16_t pdu_len; u_char source_id[ISIS_SYS_ID_LEN + 1]; u_char start_lsp_id[ISIS_SYS_ID_LEN + 2]; u_char stop_lsp_id[ISIS_SYS_ID_LEN + 2]; }; #define ISIS_CSNP_HDRLEN 25 #define L1_PARTIAL_SEQ_NUM 26 #define L2_PARTIAL_SEQ_NUM 27 /* * L1 and L2 IS to IS partial sequence numbers PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ * + PDU Length + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Source ID + id_len + 1 * +---------------------------------------------------------------+ */ struct isis_partial_seqnum_hdr { u_int16_t pdu_len; u_char source_id[ISIS_SYS_ID_LEN + 1]; }; #define ISIS_PSNP_HDRLEN 9 /* * calling arguments for snp_process () */ #define ISIS_SNP_PSNP_FLAG 0 #define ISIS_SNP_CSNP_FLAG 1 extern int send_p2p_hello (struct thread *); extern int ack_lsp (struct isis_link_state_hdr *, struct isis_circuit *, int); extern void fill_fixed_hdr (struct isis_fixed_hdr *, u_char); extern int send_hello (struct isis_circuit *, int); extern int authentication_check (struct isis_passwd *, struct isis_passwd *); extern int isis_handle_pdu (struct isis_circuit *, u_char *); extern int isis_send_pdu_p2p (struct isis_circuit *, int); extern int build_psnp (int, struct isis_circuit *, struct pm_list *); extern int send_psnp (int, struct isis_circuit *); extern int build_csnp (int, u_char *, u_char *, struct pm_list *, struct isis_circuit *); extern int send_csnp (struct isis_circuit *, int); #endif /* _ISIS_PDU_H_ */ pmacct-1.7.8/src/isis/isis_misc.h0000644000175000017500000000530514354105275015706 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_misc.h * Miscellanous routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_MISC_H_ #define _ISIS_MISC_H_ /* includes */ #include /* defines */ /* Host configuration variable */ struct host { /* Host name of this router. */ char *name; /* Password for vty interface. */ char *password; char *password_encrypt; /* Enable password */ char *enable; char *enable_encrypt; /* System wide terminal lines. */ int lines; /* Log filename. */ char *logfile; /* config file name of this host */ char *config; /* Flags for services */ int advanced; int encrypt; /* Banner configuration. */ const char *motd; char *motdfile; }; /* prototypes */ extern const char *circuit_t2string (int); extern const char *syst2string (int); extern struct in_addr newprefix2inaddr (u_char *, u_char); extern int dotformat2buff (char *, const char *); extern int sysid2buff (char *, const char *); extern const char *isonet_print (u_char *, int); extern const char *sysid_print (u_char *); extern const char *snpa_print (u_char *); extern const char *rawlspid_print (u_char *); extern const char *time2string (u_int32_t); extern char *nlpid2string (struct nlpids *); extern int speaks (struct nlpids *, int); extern unsigned long isis_jitter (unsigned long, unsigned long); extern const char *unix_hostname (void); /* * macros */ #define GETSYSID(A,L) (A->area_addr + (A->addr_len - (L + 1))) /* used for calculating nice string representation instead of plain seconds */ #define SECS_PER_MINUTE 60 #define SECS_PER_HOUR 3600 #define SECS_PER_DAY 86400 #define SECS_PER_WEEK 604800 #define SECS_PER_MONTH 2628000 #define SECS_PER_YEAR 31536000 enum { ISIS_UI_LEVEL_BRIEF, ISIS_UI_LEVEL_DETAIL, ISIS_UI_LEVEL_EXTENSIVE, }; #endif /* _ISIS_MISC_H_ */ pmacct-1.7.8/src/isis/isis_spf.c0000644000175000017500000007455414354105275015552 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_spf.c * The SPT algorithm * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "prefix.h" #include "hash.h" #include "table.h" #include "isis_constants.h" #include "isis_common.h" #include "dict.h" #include "thread.h" #include "isisd.h" #include "isis_misc.h" #include "isis_adjacency.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_dynhn.h" #include "isis_spf.h" #include "isis_route.h" #include "isis_csm.h" extern struct isis *isis; extern struct thread_master *master; extern struct host host; int isis_run_spf_l1 (struct thread *thread); int isis_run_spf_l2 (struct thread *thread); char * vtype2string (enum vertextype vtype) { switch (vtype) { case VTYPE_PSEUDO_IS: return "pseudo_IS"; break; case VTYPE_PSEUDO_TE_IS: return "pseudo_TE-IS"; break; case VTYPE_NONPSEUDO_IS: return "IS"; break; case VTYPE_NONPSEUDO_TE_IS: return "TE-IS"; break; case VTYPE_ES: return "ES"; break; case VTYPE_IPREACH_INTERNAL: return "IP internal"; break; case VTYPE_IPREACH_EXTERNAL: return "IP external"; break; case VTYPE_IPREACH_TE: return "IP TE"; break; case VTYPE_IP6REACH_INTERNAL: return "IP6 internal"; break; case VTYPE_IP6REACH_EXTERNAL: return "IP6 external"; break; default: return "UNKNOWN"; } return NULL; /* Not reached */ } const char * vid2string (struct isis_vertex *vertex, u_char * buff) { switch (vertex->type) { case VTYPE_PSEUDO_IS: case VTYPE_PSEUDO_TE_IS: return rawlspid_print (vertex->N.id); break; case VTYPE_NONPSEUDO_IS: case VTYPE_NONPSEUDO_TE_IS: case VTYPE_ES: return sysid_print (vertex->N.id); break; case VTYPE_IPREACH_INTERNAL: case VTYPE_IPREACH_EXTERNAL: case VTYPE_IPREACH_TE: case VTYPE_IP6REACH_INTERNAL: case VTYPE_IP6REACH_EXTERNAL: isis_prefix2str ((struct isis_prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ); break; default: return "UNKNOWN"; } return (char *) buff; } /* 7.2.7 */ static void remove_excess_adjs (struct pm_list *adjs) { struct pm_listnode *node, *excess = NULL; struct isis_adjacency *adj, *candidate = NULL; int comp; for (PM_ALL_LIST_ELEMENTS_RO (adjs, node, adj)) { if (excess == NULL) excess = node; candidate = pm_listgetdata (excess); if (candidate->sys_type < adj->sys_type) { excess = node; candidate = adj; continue; } if (candidate->sys_type > adj->sys_type) continue; comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN); if (comp > 0) { excess = node; candidate = adj; continue; } if (comp < 0) continue; if (candidate->circuit->circuit_id > adj->circuit->circuit_id) { excess = node; candidate = adj; continue; } if (candidate->circuit->circuit_id < adj->circuit->circuit_id) continue; comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN); if (comp > 0) { excess = node; candidate = adj; continue; } } pm_list_delete_node (adjs, excess); return; } static struct isis_spftree * isis_spftree_new () { struct isis_spftree *tree; tree = calloc(1, sizeof (struct isis_spftree)); if (tree == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): ISIS-Spf: isis_spftree_new Out of memory!\n", config.name); return NULL; } tree->tents = pm_list_new (); tree->paths = pm_list_new (); return tree; } static void isis_vertex_del (struct isis_vertex *vertex) { pm_list_delete (vertex->Adj_N); free(vertex); return; } #if 0 /* HT: Not used yet. */ static void isis_spftree_del (struct isis_spftree *spftree) { spftree->tents->del = (void (*)(void *)) isis_vertex_del; pm_list_delete (spftree->tents); spftree->paths->del = (void (*)(void *)) isis_vertex_del; pm_list_delete (spftree->paths); free(spftree); return; } #endif void spftree_area_init (struct isis_area *area) { if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL) { area->spftree[0] = isis_spftree_new (); area->spftree6[0] = isis_spftree_new (); /* thread_add_timer (master, isis_run_spf_l1, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */ } if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL) { area->spftree[1] = isis_spftree_new (); area->spftree6[1] = isis_spftree_new (); /* thread_add_timer (master, isis_run_spf_l2, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */ } return; } static struct isis_vertex * isis_vertex_new (void *id, enum vertextype vtype) { struct isis_vertex *vertex; vertex = calloc(1, sizeof (struct isis_vertex)); if (vertex == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): isis_vertex_new Out of memory!\n", config.name); return NULL; } vertex->type = vtype; switch (vtype) { case VTYPE_ES: case VTYPE_NONPSEUDO_IS: case VTYPE_NONPSEUDO_TE_IS: memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN); break; case VTYPE_PSEUDO_IS: case VTYPE_PSEUDO_TE_IS: memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1); break; case VTYPE_IPREACH_INTERNAL: case VTYPE_IPREACH_EXTERNAL: case VTYPE_IPREACH_TE: case VTYPE_IP6REACH_INTERNAL: case VTYPE_IP6REACH_EXTERNAL: memcpy (&vertex->N.prefix, (struct isis_prefix *) id, sizeof (struct isis_prefix)); break; default: Log(LOG_ERR, "ERROR ( %s/core/ISIS ): WTF!\n", config.name); } vertex->Adj_N = pm_list_new (); return vertex; } /* * Add this IS to the root of SPT */ static void isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area, int level) { struct isis_vertex *vertex; struct isis_lsp *lsp; u_char lspid[ISIS_SYS_ID_LEN + 2]; memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (lspid) = 0; LSP_FRAGMENT (lspid) = 0; lsp = lsp_search (lspid, area->lspdb[level - 1]); if (lsp == NULL) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): ISIS-Spf: could not find own l%d LSP!\n", config.name, level); if (!area->oldmetric) vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS); else vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS); vertex->lsp = lsp; pm_listnode_add (spftree->paths, vertex); return; } static struct isis_vertex * isis_find_vertex (struct pm_list *list, void *id, enum vertextype vtype) { struct pm_listnode *node; struct isis_vertex *vertex; struct isis_prefix *p1, *p2; for (PM_ALL_LIST_ELEMENTS_RO (list, node, vertex)) { if (vertex->type != vtype) continue; switch (vtype) { case VTYPE_ES: case VTYPE_NONPSEUDO_IS: case VTYPE_NONPSEUDO_TE_IS: if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0) return vertex; break; case VTYPE_PSEUDO_IS: case VTYPE_PSEUDO_TE_IS: if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0) return vertex; break; case VTYPE_IPREACH_INTERNAL: case VTYPE_IPREACH_EXTERNAL: case VTYPE_IPREACH_TE: case VTYPE_IP6REACH_INTERNAL: case VTYPE_IP6REACH_EXTERNAL: p1 = (struct isis_prefix *) id; p2 = (struct isis_prefix *) &vertex->N.id; if (p1->family == p2->family && p1->prefixlen == p2->prefixlen && memcmp (&p1->u.prefix, &p2->u.prefix, PSIZE (p1->prefixlen)) == 0) return vertex; break; } } return NULL; } /* * Add a vertex to TENT sorted by cost and by vertextype on tie break situation */ static struct isis_vertex * isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, void *id, struct isis_adjacency *adj, u_int32_t cost, int depth, int family) { struct isis_vertex *vertex, *v; struct pm_listnode *node; u_char buff[BUFSIZ]; vertex = isis_vertex_new (id, vtype); vertex->d_N = cost; vertex->depth = depth; if (adj) pm_listnode_add (vertex->Adj_N, adj); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf: add to TENT %s %s depth %d dist %d\n", config.name, vtype2string (vertex->type), vid2string (vertex, buff), vertex->depth, vertex->d_N); pm_listnode_add (spftree->tents, vertex); if (pm_list_isempty (spftree->tents)) { pm_listnode_add (spftree->tents, vertex); return vertex; } /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */ for (node = pm_listhead (spftree->tents); node; node = pm_listnextnode (node)) { v = pm_listgetdata (node); if (v->d_N > vertex->d_N) { pm_list_add_node_prev (spftree->tents, node, vertex); break; } else if (v->d_N == vertex->d_N) { /* Tie break, add according to type */ while (v && v->d_N == vertex->d_N && v->type > vertex->type) { if (v->type > vertex->type) { break; } /* XXX: this seems dubious, node is the loop iterator */ node = pm_listnextnode (node); (node) ? (v = pm_listgetdata (node)) : (v = NULL); } pm_list_add_node_prev (spftree->tents, node, vertex); break; } else if (node->next == NULL) { pm_list_add_node_next (spftree->tents, node, vertex); break; } } return vertex; } static struct isis_vertex * isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype, void *id, struct isis_adjacency *adj, u_int32_t cost, int family) { struct isis_vertex *vertex; vertex = isis_find_vertex (spftree->tents, id, vtype); if (vertex) { /* C.2.5 c) */ if (vertex->d_N == cost) { if (adj) pm_listnode_add (vertex->Adj_N, adj); /* d) */ if (pm_listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) remove_excess_adjs (vertex->Adj_N); } /* f) */ else if (vertex->d_N > cost) { pm_listnode_delete (spftree->tents, vertex); goto add2tent; } /* e) do nothing */ return vertex; } add2tent: return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family); } static void process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj, int family) { struct isis_vertex *vertex; /* C.2.6 b) */ if (dist > MAX_PATH_METRIC) return; /* c) */ vertex = isis_find_vertex (spftree->paths, id, vtype); if (vertex) { assert (dist >= vertex->d_N); return; } vertex = isis_find_vertex (spftree->tents, id, vtype); /* d) */ if (vertex) { /* 1) */ if (vertex->d_N == dist) { if (adj) pm_listnode_add (vertex->Adj_N, adj); /* 2) */ if (pm_listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) remove_excess_adjs (vertex->Adj_N); /* 3) */ return; } else if (vertex->d_N < dist) { return; /* 4) */ } else { pm_listnode_delete (spftree->tents, vertex); } } isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family); return; } /* * C.2.6 Step 1 */ static int isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint32_t cost, uint16_t depth, int family) { struct pm_listnode *node, *fragnode = NULL; u_int16_t dist; struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; struct ipv4_reachability *ipreach; struct te_ipv4_reachability *te_ipv4_reach; enum vertextype vtype; struct isis_prefix prefix; struct ipv6_reachability *ip6reach; if (!lsp->adj) return ISIS_WARNING; if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) return ISIS_OK; lspfragloop: if (lsp->lsp_header->seq_num == 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_spf_process_lsp(): lsp with 0 seq_num - do not process\n", config.name); return ISIS_WARNING; } if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) { if (lsp->tlv_data.is_neighs) { for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) { /* C.2.6 a) */ /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; dist = cost + is_neigh->metrics.metric_default; vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (lsp->tlv_data.te_is_neighs) { for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) { uint32_t metric; if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; memcpy (&metric, te_is_neigh->te_metric, 3); dist = cost + ntohl (metric << 8); vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) { prefix.family = AF_INET; for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_INTERNAL; prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = isis_ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) { prefix.family = AF_INET; for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_EXTERNAL; /* Set advertising router to the first IP address */ if (lsp->tlv_data.ipv4_addrs) { memcpy(&prefix.adv_router, pm_listnode_head(lsp->tlv_data.ipv4_addrs), sizeof(struct in_addr)); } prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = isis_ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs) { prefix.family = AF_INET; for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs, node, te_ipv4_reach)) { dist = cost + ntohl (te_ipv4_reach->te_metric); vtype = VTYPE_IPREACH_TE; /* Set advertising router to the first IP address */ if (lsp->tlv_data.ipv4_addrs) { memcpy(&prefix.adv_router, pm_listnode_head(lsp->tlv_data.ipv4_addrs), sizeof(struct in_addr)); } prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start, te_ipv4_reach->control); prefix.prefixlen = (te_ipv4_reach->control & 0x3F); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs) { prefix.family = AF_INET6; for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach)) { dist = cost + ip6reach->metric; vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ? VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL; prefix.prefixlen = ip6reach->prefix_len; memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, PSIZE (ip6reach->prefix_len)); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } } if (fragnode == NULL) fragnode = pm_listhead (lsp->lspu.frags); else fragnode = pm_listnextnode (fragnode); if (fragnode) { lsp = pm_listgetdata (fragnode); goto lspfragloop; } return ISIS_OK; } static int isis_spf_process_pseudo_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint16_t cost, uint16_t depth, int family) { struct pm_listnode *node, *fragnode = NULL; struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; enum vertextype vtype; pseudofragloop: if (lsp->lsp_header->seq_num == 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_spf_process_pseudo_lsp(): lsp with 0 seq_num - do not process\n", config.name); return ISIS_WARNING; } if (lsp->tlv_data.is_neighs) for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) { vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; if (isis_find_vertex (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj, cost, depth, family); } } if (lsp->tlv_data.te_is_neighs) for (PM_ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) { vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; /* Two way connectivity */ if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; if (isis_find_vertex (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj, cost, depth, family); } } if (fragnode == NULL) fragnode = pm_listhead (lsp->lspu.frags); else fragnode = pm_listnextnode (fragnode); if (fragnode) { lsp = pm_listgetdata (fragnode); goto pseudofragloop; } return ISIS_OK; } static int isis_spf_preload_tent (struct isis_spftree *spftree, struct isis_area *area, int level, int family) { struct isis_circuit *circuit; struct pm_listnode *cnode, *ipnode; struct isis_adjacency *adj; struct prefix_ipv4 *ipv4; struct isis_prefix prefix; int retval = ISIS_OK; struct prefix_ipv6 *ipv6; for (PM_ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) { if (circuit->state != C_STATE_UP) continue; if (!(circuit->circuit_is_type & level)) continue; if (family == AF_INET && !circuit->ip_router) continue; if (family == AF_INET6 && !circuit->ipv6_router) continue; /* * Add IP(v6) addresses of this circuit */ if (family == AF_INET) { prefix.family = AF_INET; for (PM_ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) { prefix.u.prefix4 = ipv4->prefix; prefix.prefixlen = ipv4->prefixlen; isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix, NULL, 0, family); } } if (family == AF_INET6) { prefix.family = AF_INET6; for (PM_ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6)) { prefix.prefixlen = ipv6->prefixlen; prefix.u.prefix6 = ipv6->prefix; isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL, &prefix, NULL, 0, family); } } if (circuit->circ_type == CIRCUIT_T_P2P) { adj = circuit->u.p2p.neighbor; if (!adj) continue; switch (adj->sys_type) { case ISIS_SYSTYPE_ES: isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, circuit->te_metric[level - 1], family); break; case ISIS_SYSTYPE_IS: case ISIS_SYSTYPE_L1_IS: case ISIS_SYSTYPE_L2_IS: if (speaks (&adj->nlpids, family)) isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid, adj, circuit->te_metric[level - 1], family); break; case ISIS_SYSTYPE_UNKNOWN: default: Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_spf_preload_tent unknow adj type\n", config.name); break; } } else { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_spf_preload_tent unsupported media\n", config.name); retval = ISIS_WARNING; } } return retval; } /* * The parent(s) for vertex is set when added to TENT list * now we just put the child pointer(s) in place */ static void add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex, struct isis_area *area, int level) { pm_listnode_add (spftree->paths, vertex); if (vertex->type > VTYPE_ES) { if (pm_listcount (vertex->Adj_N) > 0) { isis_route_create ((struct isis_prefix *) &vertex->N.prefix, vertex->d_N, vertex->depth, vertex->Adj_N, area, level); if (config.nfacctd_isis_msglog) { char prefix[BUFSIZ]; isis_prefix2str (&vertex->N.prefix, prefix, BUFSIZ); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (tag: %s, level: %u): route installed: %s\n", config.name, area->area_tag, area->is_type, prefix); } } else { if (config.nfacctd_isis_msglog) { char prefix[BUFSIZ]; isis_prefix2str (&vertex->N.prefix, prefix, BUFSIZ); if (config.nfacctd_isis_msglog) Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (tag: %s, level: %u): no adjacencies do not install route: %s\n", config.name, area->area_tag, area->is_type, prefix); } } } return; } static void init_spt (struct isis_spftree *spftree) { spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del; pm_list_delete_all_node (spftree->tents); pm_list_delete_all_node (spftree->paths); spftree->tents->del = spftree->paths->del = NULL; return; } int isis_run_spf (struct isis_area *area, int level, int family) { int retval = ISIS_OK; struct pm_listnode *node; struct isis_vertex *vertex; struct isis_spftree *spftree = NULL; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; struct isis_lsp *lsp; struct route_table *table = NULL; struct route_node *rode; struct isis_route_info *rinfo; if (family == AF_INET) spftree = area->spftree[level - 1]; else if (family == AF_INET6) spftree = area->spftree6[level - 1]; assert (spftree); /* Make all routes in current route table inactive. */ if (family == AF_INET) table = area->route_table[level - 1]; else if (family == AF_INET6) table = area->route_table6[level - 1]; for (rode = route_top (table); rode; rode = route_next (rode)) { if (rode->info == NULL) continue; rinfo = rode->info; UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); } /* * C.2.5 Step 0 */ init_spt (spftree); /* a) */ isis_spf_add_self (spftree, area, level); /* b) */ retval = isis_spf_preload_tent (spftree, area, level, family); /* * C.2.7 Step 2 */ if (pm_listcount (spftree->tents) == 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): ISIS-Spf: TENT is empty\n", config.name); goto out; } while (pm_listcount (spftree->tents) > 0) { node = pm_listhead (spftree->tents); vertex = pm_listgetdata (node); /* Remove from tent list */ pm_list_delete_node (spftree->tents, node); if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) continue; add_to_paths (spftree, vertex, area, level); if (vertex->type == VTYPE_PSEUDO_IS || vertex->type == VTYPE_NONPSEUDO_IS || vertex->type == VTYPE_PSEUDO_TE_IS || vertex->type == VTYPE_NONPSEUDO_TE_IS) { memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT (lsp_id) = 0; lsp = lsp_search (lsp_id, area->lspdb[level - 1]); if (lsp) { if (LSP_PSEUDO_ID (lsp_id)) { isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, vertex->depth, family); } else { isis_spf_process_lsp (spftree, lsp, vertex->d_N, vertex->depth, family); } } else { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): ISIS-Spf: No LSP found for %s\n", config.name, rawlspid_print (lsp_id)); } } } out: // thread_add_event (master, isis_route_validate, area, 0); spftree->lastrun = time (NULL); spftree->pending = 0; Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (tag: %s, level: %u): SPF algorithm run\n", config.name, area->area_tag, area->is_type); return retval; } int isis_run_spf_l1 (struct thread *thread) { struct isis_area *area; int retval = ISIS_OK; area = THREAD_ARG (thread); assert (area); area->spftree[0]->t_spf = NULL; if (!(area->is_type & IS_LEVEL_1)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-SPF (%s) area does not share level\n", config.name, area->area_tag); return ISIS_WARNING; } Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (%s) L1 SPF needed, periodic SPF\n", config.name, area->area_tag); if (area->ip_circuits) retval = isis_run_spf (area, 1, AF_INET); THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); return retval; } int isis_run_spf_l2 (struct thread *thread) { struct isis_area *area; int retval = ISIS_OK; area = THREAD_ARG (thread); assert (area); area->spftree[1]->t_spf = NULL; if (!(area->is_type & IS_LEVEL_2)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-SPF (%s) area does not share level\n", config.name, area->area_tag); return ISIS_WARNING; } Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (%s) L2 SPF needed, periodic SPF\n", config.name, area->area_tag); if (area->ip_circuits) retval = isis_run_spf (area, 2, AF_INET); THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); return retval; } int isis_spf_schedule (struct isis_area *area, int level) { int retval = ISIS_OK; struct isis_spftree *spftree = area->spftree[level - 1]; time_t diff, now = time (NULL); if (spftree->pending) return retval; diff = now - spftree->lastrun; /* FIXME: let's wait a minute before doing the SPF */ if (now - isis->uptime < 60 || isis->uptime == 0) { if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60); spftree->pending = 1; return retval; } THREAD_TIMER_OFF (spftree->t_spf); if (diff < MINIMUM_SPF_INTERVAL) { if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, MINIMUM_SPF_INTERVAL - diff); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, MINIMUM_SPF_INTERVAL - diff); spftree->pending = 1; } else { spftree->pending = 0; retval = isis_run_spf (area, level, AF_INET); if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); } return retval; } static int isis_run_spf6_l1 (struct thread *thread) { struct isis_area *area; int retval = ISIS_OK; area = THREAD_ARG (thread); assert (area); area->spftree6[0]->t_spf = NULL; if (!(area->is_type & IS_LEVEL_1)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-SPF (%s) area does not share level\n", config.name, area->area_tag); return ISIS_WARNING; } Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (%s) L1 SPF needed, periodic SPF\n", config.name, area->area_tag); if (area->ipv6_circuits) retval = isis_run_spf (area, 1, AF_INET6); THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); return retval; } static int isis_run_spf6_l2 (struct thread *thread) { struct isis_area *area; int retval = ISIS_OK; area = THREAD_ARG (thread); assert (area); area->spftree6[1]->t_spf = NULL; if (!(area->is_type & IS_LEVEL_2)) { Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-SPF (%s) area does not share level\n", config.name, area->area_tag); return ISIS_WARNING; } Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): ISIS-Spf (%s) L2 SPF needed, periodic SPF\n", config.name, area->area_tag); if (area->ipv6_circuits) retval = isis_run_spf (area, 2, AF_INET6); THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); return retval; } int isis_spf_schedule6 (struct isis_area *area, int level) { int retval = ISIS_OK; struct isis_spftree *spftree = area->spftree6[level - 1]; time_t diff, now = time (NULL); if (spftree->pending) return retval; diff = now - spftree->lastrun; /* FIXME: let's wait a minute before doing the SPF */ if (now - isis->uptime < 60 || isis->uptime == 0) { if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60); spftree->pending = 1; return retval; } THREAD_TIMER_OFF (spftree->t_spf); if (diff < MINIMUM_SPF_INTERVAL) { if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, MINIMUM_SPF_INTERVAL - diff); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, MINIMUM_SPF_INTERVAL - diff); spftree->pending = 1; } else { spftree->pending = 0; retval = isis_run_spf (area, level, AF_INET6); if (level == 1) THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); else THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, isis_jitter (PERIODIC_SPF_INTERVAL, 10)); } return retval; } pmacct-1.7.8/src/isis/isis_dynhn.c0000644000175000017500000000533514354105275016071 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_dynhn.c * Dynamic hostname cache * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "dict.h" #include "thread.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" #include "isis_circuit.h" #include "isisd.h" #include "isis_dynhn.h" #include "isis_misc.h" #include "isis_constants.h" struct pm_list *dyn_cache; extern struct host host; void dyn_cache_init (void) { dyn_cache = NULL; dyn_cache = pm_list_new (); } int dyn_cache_cleanup () { struct pm_listnode *node, *nnode; struct isis_dynhn *dyn; time_t now = time (NULL); isis->t_dync_clean = NULL; for (PM_ALL_LIST_ELEMENTS (dyn_cache, node, nnode, dyn)) { if ((now - dyn->refresh) < (MAX_AGE + 120)) continue; pm_list_delete_node (dyn_cache, node); free(dyn); } return ISIS_OK; } struct isis_dynhn * dynhn_find_by_id (u_char * id) { struct pm_listnode *node = NULL; struct isis_dynhn *dyn = NULL; for (PM_ALL_LIST_ELEMENTS_RO (dyn_cache, node, dyn)) if (memcmp (dyn->id, id, ISIS_SYS_ID_LEN) == 0) return dyn; return NULL; } void isis_dynhn_insert (u_char * id, struct hostname *hostname, int level) { struct isis_dynhn *dyn; dyn = dynhn_find_by_id (id); if (dyn) { memcpy (&dyn->name, hostname, hostname->namelen + 1); memcpy (dyn->id, id, ISIS_SYS_ID_LEN); dyn->refresh = time (NULL); return; } dyn = calloc(1, sizeof (struct isis_dynhn)); if (!dyn) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): isis_dynhn_insert(): out of memory!\n", config.name); return; } /* we also copy the length */ memcpy (&dyn->name, hostname, hostname->namelen + 1); memcpy (dyn->id, id, ISIS_SYS_ID_LEN); dyn->refresh = time (NULL); dyn->level = level; pm_listnode_add (dyn_cache, dyn); return; } pmacct-1.7.8/src/isis/table.h0000644000175000017500000000446714354105275015023 0ustar paolopaolo/* * Routing Table * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _TABLE_H_ #define _TABLE_H_ /* Routing table top structure. */ struct route_table { struct route_node *top; }; /* Each routing entry. */ struct route_node { /* Actual prefix of this radix. */ struct isis_prefix p; /* Tree link. */ struct route_table *table; struct route_node *parent; struct route_node *link[2]; #define l_left link[0] #define l_right link[1] /* Lock of this radix */ unsigned int lock; /* Each node of route. */ void *info; /* Aggregation. */ void *aggregate; }; /* Prototypes. */ extern struct route_table *route_table_init (void); extern void route_table_finish (struct route_table *); extern void route_unlock_node (struct route_node *); extern void route_node_delete (struct route_node *); extern struct route_node *route_top (struct route_table *); extern struct route_node *route_next (struct route_node *); extern struct route_node *route_next_until (struct route_node *, struct route_node *); extern struct route_node *route_node_get (struct route_table *, struct isis_prefix *); extern struct route_node *route_node_lookup (struct route_table *, struct isis_prefix *); extern struct route_node *route_lock_node (struct route_node *); extern struct route_node *route_node_match (const struct route_table *, const struct isis_prefix *); extern struct route_node *route_node_match_ipv4 (const struct route_table *, const struct in_addr *); extern struct route_node *route_node_match_ipv6 (const struct route_table *, const struct in6_addr *); #endif /* _TABLE_H_ */ pmacct-1.7.8/src/isis/isis_events.h0000644000175000017500000000303414354105275016254 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_events.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_EVENTS_H_ #define _ISIS_EVENTS_H_ #define AUTH_ERROR_TYPE_LSP 3 #define AUTH_ERROR_TYPE_SNP 2 #define AUTH_ERROR_TYPE_HELLO 1 extern void isis_event_system_type_change (struct isis_area *, int); extern void isis_event_area_addr_change (struct isis_area *); extern void isis_event_circuit_state_change (struct isis_circuit *, int); extern void isis_event_circuit_type_change (struct isis_circuit *, int); extern void isis_event_adjacency_state_change (struct isis_adjacency *, int); extern void isis_event_auth_failure (char *, const char *, u_char *); #endif /* _ISIS_EVENTS_H_ */ pmacct-1.7.8/src/isis/sockunion.c0000644000175000017500000003331414354105275015730 0ustar paolopaolo/* Socket union related function. * Copyright (c) 1997, 98 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "prefix.h" #include "sockunion.h" const char * inet_sutop (union sockunion *su, char *str) { switch (su->sa.sa_family) { case AF_INET: inet_ntop (AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN); break; case AF_INET6: inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN); break; } return str; } int str2sockunion (const char *str, union sockunion *su) { int ret; memset (su, 0, sizeof (union sockunion)); ret = inet_pton (AF_INET, str, &su->sin.sin_addr); if (ret > 0) /* Valid IPv4 address format. */ { su->sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN su->sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return 0; } ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr); if (ret > 0) /* Valid IPv6 address format. */ { su->sin6.sin6_family = AF_INET6; #ifdef SIN6_LEN su->sin6.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ return 0; } return -1; } const char * sockunion2str (union sockunion *su, char *buf, size_t len) { if (su->sa.sa_family == AF_INET) return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len); else if (su->sa.sa_family == AF_INET6) return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len); return NULL; } union sockunion * sockunion_str2su (const char *str) { int ret; union sockunion *su; su = calloc(1, sizeof (union sockunion)); ret = inet_pton (AF_INET, str, &su->sin.sin_addr); if (ret > 0) /* Valid IPv4 address format. */ { su->sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN su->sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ return su; } ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr); if (ret > 0) /* Valid IPv6 address format. */ { su->sin6.sin6_family = AF_INET6; #ifdef SIN6_LEN su->sin6.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ return su; } free(su); return NULL; } char * sockunion_su2str (union sockunion *su) { char str[SU_ADDRSTRLEN]; switch (su->sa.sa_family) { case AF_INET: inet_ntop (AF_INET, &su->sin.sin_addr, str, sizeof (str)); break; case AF_INET6: inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, sizeof (str)); break; } return strdup(str); } /* Convert IPv4 compatible IPv6 address to IPv4 address. */ static void sockunion_normalise_mapped (union sockunion *su) { struct sockaddr_in sin; if (su->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr)) { memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = su->sin6.sin6_port; memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4); memcpy (su, &sin, sizeof (struct sockaddr_in)); } } /* Return socket of sockunion. */ int sockunion_socket (union sockunion *su) { int sock; sock = socket (su->sa.sa_family, SOCK_STREAM, 0); if (sock < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't make socket : %s\n", config.name, strerror (errno)); return -1; } return sock; } /* Return accepted new socket file descriptor. */ int sockunion_accept (int sock, union sockunion *su) { socklen_t len; int client_sock; len = sizeof (union sockunion); client_sock = accept (sock, (struct sockaddr *) su, &len); sockunion_normalise_mapped (su); return client_sock; } /* Return sizeof union sockunion. */ static int sockunion_sizeof (union sockunion *su) { int ret; ret = 0; switch (su->sa.sa_family) { case AF_INET: ret = sizeof (struct sockaddr_in); break; case AF_INET6: ret = sizeof (struct sockaddr_in6); break; } return ret; } /* return sockunion structure : this function should be revised. */ static char * sockunion_log (union sockunion *su) { static char buf[SU_ADDRSTRLEN]; switch (su->sa.sa_family) { case AF_INET: snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr)); break; case AF_INET6: snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN)); break; default: snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family); break; } return (strdup(buf)); } /* sockunion_connect returns -1 : error occured 0 : connect success 1 : connect is in progress */ enum connect_result sockunion_connect (int fd, union sockunion *peersu, unsigned short port, unsigned int ifindex) { int ret; int val; union sockunion su; memcpy (&su, peersu, sizeof (union sockunion)); switch (su.sa.sa_family) { case AF_INET: su.sin.sin_port = port; break; case AF_INET6: su.sin6.sin6_port = port; break; } /* Make socket non-block. */ val = fcntl (fd, F_GETFL, 0); fcntl (fd, F_SETFL, val|O_NONBLOCK); /* Call connect function. */ ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su)); /* Immediate success */ if (ret == 0) { fcntl (fd, F_SETFL, val); return connect_success; } /* If connect is in progress then return 1 else it's real error. */ if (ret < 0) { if (errno != EINPROGRESS) { Log(LOG_INFO, "INFO ( %s/core/ISIS ): can't connect to %s fd %d : %s\n", config.name, sockunion_log (&su), fd, strerror (errno)); return connect_error; } } fcntl (fd, F_SETFL, val); return connect_in_progress; } /* Make socket from sockunion union. */ int sockunion_stream_socket (union sockunion *su) { int sock; if (su->sa.sa_family == 0) su->sa.sa_family = AF_INET_UNION; sock = socket (su->sa.sa_family, SOCK_STREAM, 0); if (sock < 0) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't make socket sockunion_stream_socket\n", config.name); return sock; } /* Bind socket to specified address. */ int sockunion_bind (int sock, union sockunion *su, unsigned short port, union sockunion *su_addr) { int size = 0; int ret; if (su->sa.sa_family == AF_INET) { size = sizeof (struct sockaddr_in); su->sin.sin_port = htons (port); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN su->sin.sin_len = size; #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ if (su_addr == NULL) su->sin.sin_addr.s_addr = htonl (INADDR_ANY); } else if (su->sa.sa_family == AF_INET6) { size = sizeof (struct sockaddr_in6); su->sin6.sin6_port = htons (port); #ifdef SIN6_LEN su->sin6.sin6_len = size; #endif /* SIN6_LEN */ if (su_addr == NULL) { #if defined(LINUX_IPV6) || defined(NRL) memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr)); #else su->sin6.sin6_addr = in6addr_any; #endif /* LINUX_IPV6 */ } } ret = bind (sock, (struct sockaddr *)su, size); if (ret < 0) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't bind socket : %s\n", config.name, strerror (errno)); return ret; } int sockopt_reuseaddr (int sock) { int ret; int on = 1; ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof (on)); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt SO_REUSEADDR to socket %d\n", config.name, sock); return -1; } return 0; } #if defined (HAVE_SO_REUSEPORT) int sockopt_reuseport (int sock) { int ret; int on = 1; ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof (on)); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt SO_REUSEPORT to socket %d\n", config.name, sock); return -1; } return 0; } #else int sockopt_reuseport (int sock) { return 0; } #endif /* 0 */ int sockopt_ttl (int family, int sock, int ttl) { int ret; #ifdef IP_TTL if (family == AF_INET) { ret = setsockopt (sock, IPPROTO_IP, IP_TTL, (void *) &ttl, sizeof (int)); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt IP_TTL %d to socket %d\n", config.name, ttl, sock); return -1; } return 0; } #endif /* IP_TTL */ if (family == AF_INET6) { ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (void *) &ttl, sizeof (int)); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt IPV6_UNICAST_HOPS %d to socket %d\n", config.name, ttl, sock); return -1; } return 0; } return 0; } int sockopt_cork (int sock, int onoff) { #ifdef TCP_CORK return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff)); #else return 0; #endif } int sockopt_minttl (int family, int sock, int minttl) { #ifdef IP_MINTTL if (family == AF_INET) { int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); if (ret < 0) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt IP_MINTTL to %d on socket %d: %s\n", config.name, minttl, sock, strerror (errno)); return ret; } #endif /* IP_MINTTL */ #ifdef IPV6_MINHOPCNT if (family == AF_INET6) { int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl)); if (ret < 0) Log(LOG_WARNING, "WARN ( %s/core/ISIS ): can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s\n", config.name, minttl, sock, strerror (errno)); return ret; } #endif errno = EOPNOTSUPP; return -1; } /* If same family and same prefix return 1. */ int sockunion_same (union sockunion *su1, union sockunion *su2) { int ret = 0; if (su1->sa.sa_family != su2->sa.sa_family) return 0; switch (su1->sa.sa_family) { case AF_INET: ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr, sizeof (struct in_addr)); break; case AF_INET6: ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr, sizeof (struct in6_addr)); break; } if (ret == 0) return 1; else return 0; } /* After TCP connection is established. Get local address and port. */ union sockunion * sockunion_getsockname (int fd) { int ret; socklen_t len; union { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; char tmp_buffer[128]; } name; union sockunion *su; memset (&name, 0, sizeof name); len = sizeof name; ret = getsockname (fd, (struct sockaddr *)&name, &len); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't get local address and port by getsockname: %s\n", config.name, strerror (errno)); return NULL; } if (name.sa.sa_family == AF_INET) { su = calloc(1, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in)); return su; } if (name.sa.sa_family == AF_INET6) { su = calloc(1, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in6)); sockunion_normalise_mapped (su); return su; } return NULL; } /* After TCP connection is established. Get remote address and port. */ union sockunion * sockunion_getpeername (int fd) { int ret; socklen_t len; union { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; char tmp_buffer[128]; } name; union sockunion *su; memset (&name, 0, sizeof name); len = sizeof name; ret = getpeername (fd, (struct sockaddr *)&name, &len); if (ret < 0) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Can't get remote address and port: %s\n", config.name, strerror (errno)); return NULL; } if (name.sa.sa_family == AF_INET) { su = calloc(1, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in)); return su; } if (name.sa.sa_family == AF_INET6) { su = calloc(1, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in6)); sockunion_normalise_mapped (su); return su; } return NULL; } static int in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2) { unsigned int i; u_char *p1, *p2; p1 = (u_char *)addr1; p2 = (u_char *)addr2; for (i = 0; i < sizeof (struct in6_addr); i++) { if (p1[i] > p2[i]) return 1; else if (p1[i] < p2[i]) return -1; } return 0; } int sockunion_cmp (union sockunion *su1, union sockunion *su2) { if (su1->sa.sa_family > su2->sa.sa_family) return 1; if (su1->sa.sa_family < su2->sa.sa_family) return -1; if (su1->sa.sa_family == AF_INET) { if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr)) return 0; if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr)) return 1; else return -1; } if (su1->sa.sa_family == AF_INET6) return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr); return 0; } /* Duplicate sockunion. */ union sockunion * sockunion_dup (union sockunion *su) { union sockunion *dup = calloc(1, sizeof (union sockunion)); memcpy (dup, su, sizeof (union sockunion)); return dup; } void sockunion_free (union sockunion *su) { free(su); } pmacct-1.7.8/src/isis/isis_spf.h0000644000175000017500000000421614354105275015543 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_spf.h * IS-IS Shortest Path First algorithm * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_SPF_H_ #define _ISIS_SPF_H_ enum vertextype { VTYPE_PSEUDO_IS = 1, VTYPE_PSEUDO_TE_IS, VTYPE_NONPSEUDO_IS, VTYPE_NONPSEUDO_TE_IS, VTYPE_ES, VTYPE_IPREACH_INTERNAL, VTYPE_IPREACH_EXTERNAL, VTYPE_IPREACH_TE, VTYPE_IP6REACH_INTERNAL, VTYPE_IP6REACH_EXTERNAL }; /* * Triple */ struct isis_vertex { enum vertextype type; union { u_char id[ISIS_SYS_ID_LEN + 1]; struct isis_prefix prefix; } N; struct isis_lsp *lsp; u_int32_t d_N; /* d(N) Distance from this IS */ u_int16_t depth; /* The depth in the imaginary tree */ struct pm_list *Adj_N; /* {Adj(N)} */ }; struct isis_spftree { struct thread *t_spf; /* spf threads */ time_t lastrun; /* for scheduling */ int pending; /* already scheduled */ struct pm_list *paths; /* the SPT */ struct pm_list *tents; /* TENT */ u_int32_t timerun; /* statistics */ }; extern void spftree_area_init (struct isis_area *); extern int isis_spf_schedule (struct isis_area *, int); extern int isis_run_spf (struct isis_area *, int, int); extern int isis_spf_schedule6 (struct isis_area *, int); #endif /* _ISIS_SPF_H_ */ pmacct-1.7.8/src/isis/isis_csm.h0000644000175000017500000000274614354105275015543 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_csm.h * IS-IS circuit state machine * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_CSM_H_ #define _ISIS_CSM_H_ /* * Circuit states */ #define C_STATE_NA 0 #define C_STATE_INIT 1 /* Connected to interface */ #define C_STATE_CONF 2 /* Configured for ISIS */ #define C_STATE_UP 3 /* CONN | CONF */ /* * Circuit events */ #define ISIS_ENABLE 1 #define IF_UP_FROM_Z 2 #define ISIS_DISABLE 3 #define IF_DOWN_FROM_Z 4 extern struct isis_circuit *isis_csm_state_change (int, struct isis_circuit *, void *); #endif /* _ISIS_CSM_H_ */ pmacct-1.7.8/src/isis/isis_dynhn.h0000644000175000017500000000261614354105275016075 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_dynhn.h * Dynamic hostname cache * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_DYNHN_H_ #define _ISIS_DYNHN_H_ struct isis_dynhn { u_char id[ISIS_SYS_ID_LEN]; struct hostname name; time_t refresh; int level; }; extern void dyn_cache_init (); extern void isis_dynhn_insert (u_char * id, struct hostname *, int); extern struct isis_dynhn *dynhn_find_by_id (u_char *); extern int dyn_cache_cleanup (); extern struct pm_list *dyn_cache; #endif /* _ISIS_DYNHN_H_ */ pmacct-1.7.8/src/isis/iso_checksum.h0000644000175000017500000000217414354105275016401 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - iso_checksum.c * ISO checksum related routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISO_CSUM_H_ #define _ISO_CSUM_H_ extern int iso_csum_verify (u_char *, int, uint16_t *); #endif /* _ISO_CSUM_H_ */ pmacct-1.7.8/src/isis/isis_misc.c0000644000175000017500000002146114354105275015702 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_misc.c * Miscellanous routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "hash.h" #include "dict.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_circuit.h" #include "isisd.h" #include "isis_misc.h" #include "isis_tlv.h" #include "isis_lsp.h" #include "isis_constants.h" #include "isis_adjacency.h" /* staticly assigned vars for printing purposes */ struct in_addr new_prefix; /* len of xxxx.xxxx.xxxx + place for #0 termination */ char sysid[15]; /* len of xxxx.xxxx.xxxx + place for #0 termination */ char snpa[15]; /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */ char isonet[51]; /* + place for #0 termination */ /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */ char lspid[21]; /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */ char datestring[20]; char nlpidstring[30]; /* * This converts the isonet to its printable format */ const char * isonet_print (u_char * from, int len) { int i = 0; char *pos = isonet; if (!from) return "unknown"; while (i < len) { if (i & 1) { sprintf (pos, "%02x", *(from + i)); pos += 2; } else { if (i == (len - 1)) { /* No dot at the end of address */ sprintf (pos, "%02x", *(from + i)); pos += 2; } else { sprintf (pos, "%02x.", *(from + i)); pos += 3; } } i++; } *(pos) = '\0'; return isonet; } /* * Returns 0 on error, length of buff on ok * extract dot from the dotted str, and insert all the number in a buff */ int dotformat2buff (char * buff, const char * dotted) { int dotlen, len = 0; const char *pos = dotted; u_char number[3]; int nextdotpos = 2; number[2] = '\0'; dotlen = strlen(dotted); if (dotlen > 50) { /* this can't be an iso net, its too long */ return 0; } while ((pos - dotted) < dotlen && len < 20) { if (*pos == '.') { /* we expect the . at 2, and than every 5 */ if ((pos - dotted) != nextdotpos) { len = 0; break; } nextdotpos += 5; pos++; continue; } /* we must have at least two chars left here */ if (dotlen - (pos - dotted) < 2) { len = 0; break; } if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1)))) { memcpy (number, pos, 2); pos += 2; } else { len = 0; break; } *(buff + len) = (char) strtol ((char *)number, NULL, 16); len++; } return len; } /* * conversion of XXXX.XXXX.XXXX to memory */ int sysid2buff (char * buff, const char * dotted) { int len = 0; const char *pos = dotted; u_char number[3]; number[2] = '\0'; // surely not a sysid_string if not 14 length if (strlen (dotted) != 14) { return 0; } while (len < ISIS_SYS_ID_LEN) { if (*pos == '.') { /* the . is not positioned correctly */ if (((pos - dotted) != 4) && ((pos - dotted) != 9)) { len = 0; break; } pos++; continue; } if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1)))) { memcpy (number, pos, 2); pos += 2; } else { len = 0; break; } *(buff + len) = (char) strtol ((char *)number, NULL, 16); len++; } return len; } /* * converts the nlpids struct (filled by TLV #129) * into a string */ char * nlpid2string (struct nlpids *nlpids) { char *pos = nlpidstring; int i; for (i = 0; i < nlpids->count; i++) { switch (nlpids->nlpids[i]) { case NLPID_IP: pos += sprintf (pos, "IPv4"); break; case NLPID_IPV6: pos += sprintf (pos, "IPv6"); break; case NLPID_SNAP: pos += sprintf (pos, "SNAP"); break; case NLPID_CLNP: pos += sprintf (pos, "CLNP"); break; case NLPID_ESIS: pos += sprintf (pos, "ES-IS"); break; default: pos += sprintf (pos, "unknown"); break; } if (nlpids->count - i > 1) pos += sprintf (pos, ", "); } *(pos) = '\0'; return nlpidstring; } /* * supports the given af ? */ int speaks (struct nlpids *nlpids, int family) { int i, speaks = 0; if (nlpids == (struct nlpids *) NULL) return speaks; for (i = 0; i < nlpids->count; i++) { if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP) speaks = 1; if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6) speaks = 1; } return speaks; } const char * circuit_t2string (int circuit_t) { switch (circuit_t) { case IS_LEVEL_1: return "L1"; case IS_LEVEL_2: return "L2"; case IS_LEVEL_1_AND_2: return "L1L2"; default: return "??"; } return NULL; /* not reached */ } const char * syst2string (int type) { switch (type) { case ISIS_SYSTYPE_ES: return "ES"; case ISIS_SYSTYPE_IS: return "IS"; case ISIS_SYSTYPE_L1_IS: return "1"; case ISIS_SYSTYPE_L2_IS: return "2"; default: return "??"; } return NULL; /* not reached */ } /* * Print functions - we print to static vars */ const char * snpa_print (u_char * from) { int i = 0; u_char *pos = (u_char *)snpa; if (!from) return "unknown"; while (i < ETH_ALEN - 1) { if (i & 1) { sprintf ((char *)pos, "%02x.", *(from + i)); pos += 3; } else { sprintf ((char *)pos, "%02x", *(from + i)); pos += 2; } i++; } sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); pos += 2; *(pos) = '\0'; return snpa; } const char * sysid_print (u_char * from) { int i = 0; char *pos = sysid; if (!from) return "unknown"; while (i < ISIS_SYS_ID_LEN - 1) { if (i & 1) { sprintf (pos, "%02x.", *(from + i)); pos += 3; } else { sprintf (pos, "%02x", *(from + i)); pos += 2; } i++; } sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); pos += 2; *(pos) = '\0'; return sysid; } const char * rawlspid_print (u_char * from) { char *pos = lspid; if (!from) return "unknown"; memcpy (pos, sysid_print (from), 15); pos += 14; sprintf (pos, ".%02x", LSP_PSEUDO_ID (from)); pos += 3; sprintf (pos, "-%02x", LSP_FRAGMENT (from)); pos += 3; *(pos) = '\0'; return lspid; } const char * time2string (u_int32_t time) { char *pos = datestring; u_int32_t rest; if (time == 0) return "-"; if (time / SECS_PER_YEAR) pos += sprintf (pos, "%uY", time / SECS_PER_YEAR); rest = time % SECS_PER_YEAR; if (rest / SECS_PER_MONTH) pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH); rest = rest % SECS_PER_MONTH; if (rest / SECS_PER_WEEK) pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK); rest = rest % SECS_PER_WEEK; if (rest / SECS_PER_DAY) pos += sprintf (pos, "%ud", rest / SECS_PER_DAY); rest = rest % SECS_PER_DAY; if (rest / SECS_PER_HOUR) pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR); rest = rest % SECS_PER_HOUR; if (rest / SECS_PER_MINUTE) pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE); rest = rest % SECS_PER_MINUTE; if (rest) pos += sprintf (pos, "%us", rest); *(pos) = 0; return datestring; } /* * routine to decrement a timer by a random * number * * first argument is the timer and the second is * the jitter */ unsigned long isis_jitter (unsigned long timer, unsigned long jitter) { int j, k; if (jitter >= 100) return timer; if (timer == 1) return timer; /* * randomizing just the percent value provides * no good random numbers - hence the spread * to RANDOM_SPREAD (100000), which is ok as * most IS-IS timers are no longer than 16 bit */ j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0)); k = timer - (timer * (100 - jitter)) / 100; timer = timer - (k * j / RANDOM_SPREAD); return timer; } struct in_addr newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen) { memset (&new_prefix, 0, sizeof (new_prefix)); memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ? ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0); return new_prefix; } pmacct-1.7.8/src/isis/isis.h0000644000175000017500000000737314354105275014702 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_H_ #define _ISIS_H_ /* includes */ #include "isis_ll.h" #include "prefix.h" #include "isis_constants.h" /* defines */ #define MAX_IGP_MAP_ELEM 64 #define MAX_IGP_MAP_NODES 4096 /* Flag manipulation macros. */ #define CHECK_FLAG(V,F) ((V) & (F)) #define SET_FLAG(V,F) (V) |= (F) #define UNSET_FLAG(V,F) (V) &= ~(F) /* Does the I/O error indicate that the operation should be retried later? */ #define ERRNO_IO_RETRY(EN) (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR)) /* structures */ static struct _devices_struct __attribute__((unused)) _isis_devices[] = { #if defined DLT_LINUX_SLL {isis_sll_handler, DLT_LINUX_SLL}, #endif {NULL, -1}, }; struct pm_pcap_isis_callback_data { struct pm_pcap_device *device; struct isis_circuit *circuit; }; struct igp_map_metric { struct isis_prefix prefix; u_int32_t metric; }; struct igp_map_entry { struct host_addr node; u_int16_t area_id; struct igp_map_metric adj_metric[MAX_IGP_MAP_ELEM]; struct igp_map_metric reach_metric[MAX_IGP_MAP_ELEM]; struct igp_map_metric reach6_metric[MAX_IGP_MAP_ELEM]; u_int8_t adj_metric_num; u_int8_t reach_metric_num; u_int8_t reach6_metric_num; }; struct sysid_fragment { u_char sysid[ISIS_SYS_ID_LEN]; u_char frag_num; u_char valid; }; /* prototypes */ extern void nfacctd_isis_wrapper(); extern int skinny_isis_daemon(); extern void isis_pdu_runner(u_char *, const struct pcap_pkthdr *, const u_char *); extern int iso_handler(register struct packet_ptrs *); extern int igp_daemon_map_node_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int igp_daemon_map_area_id_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int igp_daemon_map_adj_metric_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int igp_daemon_map_reach_metric_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern int igp_daemon_map_reach6_metric_handler(char *, struct id_entry *, char *, struct plugin_requests *, int); extern void igp_daemon_map_validate(char *, struct plugin_requests *); extern void igp_daemon_map_initialize(char *, struct plugin_requests *); extern void igp_daemon_map_finalize(char *, struct plugin_requests *); extern int igp_daemon_map_handle_len(int *, int, struct plugin_requests *, char *); extern int igp_daemon_map_handle_lsp_id(u_char *, struct host_addr *); extern void isis_srcdst_lookup(struct packet_ptrs *); /* global variables */ extern struct thread_master *master; extern struct isis *isis; extern struct in_addr router_id_zebra; /* XXX: do something with this eventually */ extern struct timeval isis_now, isis_spf_deadline, isis_psnp_deadline; extern struct igp_map_entry ime; extern pcap_dumper_t *idmm_fd; /* igp_daemon_map : file descriptor for igp_daemon_map_msglog */ extern u_int32_t glob_isis_seq_num; extern struct sysid_fragment sysid_fragment_table[MAX_IGP_MAP_NODES]; #endif pmacct-1.7.8/src/isis/Makefile.in0000644000175000017500000014554014354105416015623 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/isis ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmisis_la_LIBADD = am_libpmisis_la_OBJECTS = libpmisis_la-isis.lo \ libpmisis_la-checksum.lo libpmisis_la-dict.lo \ libpmisis_la-table.lo libpmisis_la-prefix.lo \ libpmisis_la-sockunion.lo libpmisis_la-hash.lo \ libpmisis_la-stream.lo libpmisis_la-thread.lo \ libpmisis_la-isis_circuit.lo libpmisis_la-isis_events.lo \ libpmisis_la-isis_route.lo libpmisis_la-isis_tlv.lo \ libpmisis_la-isis_csm.lo libpmisis_la-isis_flags.lo \ libpmisis_la-isis_misc.lo libpmisis_la-isisd.lo \ libpmisis_la-isis_adjacency.lo libpmisis_la-isis_dynhn.lo \ libpmisis_la-isis_spf.lo libpmisis_la-iso_checksum.lo \ libpmisis_la-isis_lsp.lo libpmisis_la-isis_pdu.lo \ libpmisis_la-isis-globals.lo libpmisis_la_OBJECTS = $(am_libpmisis_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmisis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpmisis_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmisis_la-checksum.Plo \ ./$(DEPDIR)/libpmisis_la-dict.Plo \ ./$(DEPDIR)/libpmisis_la-hash.Plo \ ./$(DEPDIR)/libpmisis_la-isis-globals.Plo \ ./$(DEPDIR)/libpmisis_la-isis.Plo \ ./$(DEPDIR)/libpmisis_la-isis_adjacency.Plo \ ./$(DEPDIR)/libpmisis_la-isis_circuit.Plo \ ./$(DEPDIR)/libpmisis_la-isis_csm.Plo \ ./$(DEPDIR)/libpmisis_la-isis_dynhn.Plo \ ./$(DEPDIR)/libpmisis_la-isis_events.Plo \ ./$(DEPDIR)/libpmisis_la-isis_flags.Plo \ ./$(DEPDIR)/libpmisis_la-isis_lsp.Plo \ ./$(DEPDIR)/libpmisis_la-isis_misc.Plo \ ./$(DEPDIR)/libpmisis_la-isis_pdu.Plo \ ./$(DEPDIR)/libpmisis_la-isis_route.Plo \ ./$(DEPDIR)/libpmisis_la-isis_spf.Plo \ ./$(DEPDIR)/libpmisis_la-isis_tlv.Plo \ ./$(DEPDIR)/libpmisis_la-isisd.Plo \ ./$(DEPDIR)/libpmisis_la-iso_checksum.Plo \ ./$(DEPDIR)/libpmisis_la-prefix.Plo \ ./$(DEPDIR)/libpmisis_la-sockunion.Plo \ ./$(DEPDIR)/libpmisis_la-stream.Plo \ ./$(DEPDIR)/libpmisis_la-table.Plo \ ./$(DEPDIR)/libpmisis_la-thread.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmisis_la_SOURCES) DIST_SOURCES = $(libpmisis_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmisis.la libpmisis_la_SOURCES = isis.c checksum.c dict.c table.c prefix.c \ sockunion.c hash.c stream.c thread.c \ isis_circuit.c isis_events.c isis_route.c isis_tlv.c \ isis_csm.c isis_flags.c isis_misc.c isisd.c isis_adjacency.c \ isis_dynhn.c isis_spf.c iso_checksum.c isis_lsp.c isis_pdu.c \ checksum.h dict.h hash.h isis_adjacency.h isis_circuit.h \ isis_common.h isis_constants.h isis_csm.h isis-data.h isisd.h \ isis_dynhn.h isis_events.h isis_flags.h isis.h isis_ll.h \ isis_lsp.h isis_misc.h isis_network.h isis_pdu.h isis_route.h \ isis_spf.h isis_tlv.h iso_checksum.h iso.h \ prefix.h sockunion.h stream.h table.h thread.h isis-globals.c libpmisis_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) -Wno-error=pointer-sign all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/isis/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/isis/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmisis.la: $(libpmisis_la_OBJECTS) $(libpmisis_la_DEPENDENCIES) $(EXTRA_libpmisis_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmisis_la_LINK) $(libpmisis_la_OBJECTS) $(libpmisis_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-checksum.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-dict.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-hash.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis-globals.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_adjacency.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_circuit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_csm.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_dynhn.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_events.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_flags.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_lsp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_misc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_pdu.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_route.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_spf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isis_tlv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-isisd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-iso_checksum.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-prefix.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-sockunion.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-stream.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-table.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmisis_la-thread.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmisis_la-isis.lo: isis.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis.Tpo -c -o libpmisis_la-isis.lo `test -f 'isis.c' || echo '$(srcdir)/'`isis.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis.Tpo $(DEPDIR)/libpmisis_la-isis.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis.c' object='libpmisis_la-isis.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis.lo `test -f 'isis.c' || echo '$(srcdir)/'`isis.c libpmisis_la-checksum.lo: checksum.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-checksum.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-checksum.Tpo -c -o libpmisis_la-checksum.lo `test -f 'checksum.c' || echo '$(srcdir)/'`checksum.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-checksum.Tpo $(DEPDIR)/libpmisis_la-checksum.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='checksum.c' object='libpmisis_la-checksum.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-checksum.lo `test -f 'checksum.c' || echo '$(srcdir)/'`checksum.c libpmisis_la-dict.lo: dict.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-dict.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-dict.Tpo -c -o libpmisis_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-dict.Tpo $(DEPDIR)/libpmisis_la-dict.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dict.c' object='libpmisis_la-dict.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c libpmisis_la-table.lo: table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-table.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-table.Tpo -c -o libpmisis_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-table.Tpo $(DEPDIR)/libpmisis_la-table.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='table.c' object='libpmisis_la-table.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c libpmisis_la-prefix.lo: prefix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-prefix.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-prefix.Tpo -c -o libpmisis_la-prefix.lo `test -f 'prefix.c' || echo '$(srcdir)/'`prefix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-prefix.Tpo $(DEPDIR)/libpmisis_la-prefix.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prefix.c' object='libpmisis_la-prefix.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-prefix.lo `test -f 'prefix.c' || echo '$(srcdir)/'`prefix.c libpmisis_la-sockunion.lo: sockunion.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-sockunion.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-sockunion.Tpo -c -o libpmisis_la-sockunion.lo `test -f 'sockunion.c' || echo '$(srcdir)/'`sockunion.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-sockunion.Tpo $(DEPDIR)/libpmisis_la-sockunion.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sockunion.c' object='libpmisis_la-sockunion.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-sockunion.lo `test -f 'sockunion.c' || echo '$(srcdir)/'`sockunion.c libpmisis_la-hash.lo: hash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-hash.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-hash.Tpo -c -o libpmisis_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-hash.Tpo $(DEPDIR)/libpmisis_la-hash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='libpmisis_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c libpmisis_la-stream.lo: stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-stream.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-stream.Tpo -c -o libpmisis_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-stream.Tpo $(DEPDIR)/libpmisis_la-stream.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stream.c' object='libpmisis_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c libpmisis_la-thread.lo: thread.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-thread.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-thread.Tpo -c -o libpmisis_la-thread.lo `test -f 'thread.c' || echo '$(srcdir)/'`thread.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-thread.Tpo $(DEPDIR)/libpmisis_la-thread.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread.c' object='libpmisis_la-thread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-thread.lo `test -f 'thread.c' || echo '$(srcdir)/'`thread.c libpmisis_la-isis_circuit.lo: isis_circuit.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_circuit.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_circuit.Tpo -c -o libpmisis_la-isis_circuit.lo `test -f 'isis_circuit.c' || echo '$(srcdir)/'`isis_circuit.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_circuit.Tpo $(DEPDIR)/libpmisis_la-isis_circuit.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_circuit.c' object='libpmisis_la-isis_circuit.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_circuit.lo `test -f 'isis_circuit.c' || echo '$(srcdir)/'`isis_circuit.c libpmisis_la-isis_events.lo: isis_events.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_events.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_events.Tpo -c -o libpmisis_la-isis_events.lo `test -f 'isis_events.c' || echo '$(srcdir)/'`isis_events.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_events.Tpo $(DEPDIR)/libpmisis_la-isis_events.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_events.c' object='libpmisis_la-isis_events.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_events.lo `test -f 'isis_events.c' || echo '$(srcdir)/'`isis_events.c libpmisis_la-isis_route.lo: isis_route.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_route.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_route.Tpo -c -o libpmisis_la-isis_route.lo `test -f 'isis_route.c' || echo '$(srcdir)/'`isis_route.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_route.Tpo $(DEPDIR)/libpmisis_la-isis_route.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_route.c' object='libpmisis_la-isis_route.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_route.lo `test -f 'isis_route.c' || echo '$(srcdir)/'`isis_route.c libpmisis_la-isis_tlv.lo: isis_tlv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_tlv.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_tlv.Tpo -c -o libpmisis_la-isis_tlv.lo `test -f 'isis_tlv.c' || echo '$(srcdir)/'`isis_tlv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_tlv.Tpo $(DEPDIR)/libpmisis_la-isis_tlv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_tlv.c' object='libpmisis_la-isis_tlv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_tlv.lo `test -f 'isis_tlv.c' || echo '$(srcdir)/'`isis_tlv.c libpmisis_la-isis_csm.lo: isis_csm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_csm.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_csm.Tpo -c -o libpmisis_la-isis_csm.lo `test -f 'isis_csm.c' || echo '$(srcdir)/'`isis_csm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_csm.Tpo $(DEPDIR)/libpmisis_la-isis_csm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_csm.c' object='libpmisis_la-isis_csm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_csm.lo `test -f 'isis_csm.c' || echo '$(srcdir)/'`isis_csm.c libpmisis_la-isis_flags.lo: isis_flags.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_flags.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_flags.Tpo -c -o libpmisis_la-isis_flags.lo `test -f 'isis_flags.c' || echo '$(srcdir)/'`isis_flags.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_flags.Tpo $(DEPDIR)/libpmisis_la-isis_flags.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_flags.c' object='libpmisis_la-isis_flags.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_flags.lo `test -f 'isis_flags.c' || echo '$(srcdir)/'`isis_flags.c libpmisis_la-isis_misc.lo: isis_misc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_misc.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_misc.Tpo -c -o libpmisis_la-isis_misc.lo `test -f 'isis_misc.c' || echo '$(srcdir)/'`isis_misc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_misc.Tpo $(DEPDIR)/libpmisis_la-isis_misc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_misc.c' object='libpmisis_la-isis_misc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_misc.lo `test -f 'isis_misc.c' || echo '$(srcdir)/'`isis_misc.c libpmisis_la-isisd.lo: isisd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isisd.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isisd.Tpo -c -o libpmisis_la-isisd.lo `test -f 'isisd.c' || echo '$(srcdir)/'`isisd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isisd.Tpo $(DEPDIR)/libpmisis_la-isisd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isisd.c' object='libpmisis_la-isisd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isisd.lo `test -f 'isisd.c' || echo '$(srcdir)/'`isisd.c libpmisis_la-isis_adjacency.lo: isis_adjacency.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_adjacency.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_adjacency.Tpo -c -o libpmisis_la-isis_adjacency.lo `test -f 'isis_adjacency.c' || echo '$(srcdir)/'`isis_adjacency.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_adjacency.Tpo $(DEPDIR)/libpmisis_la-isis_adjacency.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_adjacency.c' object='libpmisis_la-isis_adjacency.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_adjacency.lo `test -f 'isis_adjacency.c' || echo '$(srcdir)/'`isis_adjacency.c libpmisis_la-isis_dynhn.lo: isis_dynhn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_dynhn.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_dynhn.Tpo -c -o libpmisis_la-isis_dynhn.lo `test -f 'isis_dynhn.c' || echo '$(srcdir)/'`isis_dynhn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_dynhn.Tpo $(DEPDIR)/libpmisis_la-isis_dynhn.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_dynhn.c' object='libpmisis_la-isis_dynhn.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_dynhn.lo `test -f 'isis_dynhn.c' || echo '$(srcdir)/'`isis_dynhn.c libpmisis_la-isis_spf.lo: isis_spf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_spf.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_spf.Tpo -c -o libpmisis_la-isis_spf.lo `test -f 'isis_spf.c' || echo '$(srcdir)/'`isis_spf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_spf.Tpo $(DEPDIR)/libpmisis_la-isis_spf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_spf.c' object='libpmisis_la-isis_spf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_spf.lo `test -f 'isis_spf.c' || echo '$(srcdir)/'`isis_spf.c libpmisis_la-iso_checksum.lo: iso_checksum.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-iso_checksum.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-iso_checksum.Tpo -c -o libpmisis_la-iso_checksum.lo `test -f 'iso_checksum.c' || echo '$(srcdir)/'`iso_checksum.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-iso_checksum.Tpo $(DEPDIR)/libpmisis_la-iso_checksum.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iso_checksum.c' object='libpmisis_la-iso_checksum.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-iso_checksum.lo `test -f 'iso_checksum.c' || echo '$(srcdir)/'`iso_checksum.c libpmisis_la-isis_lsp.lo: isis_lsp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_lsp.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_lsp.Tpo -c -o libpmisis_la-isis_lsp.lo `test -f 'isis_lsp.c' || echo '$(srcdir)/'`isis_lsp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_lsp.Tpo $(DEPDIR)/libpmisis_la-isis_lsp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_lsp.c' object='libpmisis_la-isis_lsp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_lsp.lo `test -f 'isis_lsp.c' || echo '$(srcdir)/'`isis_lsp.c libpmisis_la-isis_pdu.lo: isis_pdu.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis_pdu.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis_pdu.Tpo -c -o libpmisis_la-isis_pdu.lo `test -f 'isis_pdu.c' || echo '$(srcdir)/'`isis_pdu.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis_pdu.Tpo $(DEPDIR)/libpmisis_la-isis_pdu.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis_pdu.c' object='libpmisis_la-isis_pdu.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis_pdu.lo `test -f 'isis_pdu.c' || echo '$(srcdir)/'`isis_pdu.c libpmisis_la-isis-globals.lo: isis-globals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -MT libpmisis_la-isis-globals.lo -MD -MP -MF $(DEPDIR)/libpmisis_la-isis-globals.Tpo -c -o libpmisis_la-isis-globals.lo `test -f 'isis-globals.c' || echo '$(srcdir)/'`isis-globals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmisis_la-isis-globals.Tpo $(DEPDIR)/libpmisis_la-isis-globals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isis-globals.c' object='libpmisis_la-isis-globals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmisis_la_CFLAGS) $(CFLAGS) -c -o libpmisis_la-isis-globals.lo `test -f 'isis-globals.c' || echo '$(srcdir)/'`isis-globals.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmisis_la-checksum.Plo -rm -f ./$(DEPDIR)/libpmisis_la-dict.Plo -rm -f ./$(DEPDIR)/libpmisis_la-hash.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis-globals.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_adjacency.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_circuit.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_csm.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_dynhn.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_events.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_flags.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_lsp.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_misc.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_pdu.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_route.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_spf.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_tlv.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isisd.Plo -rm -f ./$(DEPDIR)/libpmisis_la-iso_checksum.Plo -rm -f ./$(DEPDIR)/libpmisis_la-prefix.Plo -rm -f ./$(DEPDIR)/libpmisis_la-sockunion.Plo -rm -f ./$(DEPDIR)/libpmisis_la-stream.Plo -rm -f ./$(DEPDIR)/libpmisis_la-table.Plo -rm -f ./$(DEPDIR)/libpmisis_la-thread.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmisis_la-checksum.Plo -rm -f ./$(DEPDIR)/libpmisis_la-dict.Plo -rm -f ./$(DEPDIR)/libpmisis_la-hash.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis-globals.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_adjacency.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_circuit.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_csm.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_dynhn.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_events.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_flags.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_lsp.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_misc.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_pdu.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_route.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_spf.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isis_tlv.Plo -rm -f ./$(DEPDIR)/libpmisis_la-isisd.Plo -rm -f ./$(DEPDIR)/libpmisis_la-iso_checksum.Plo -rm -f ./$(DEPDIR)/libpmisis_la-prefix.Plo -rm -f ./$(DEPDIR)/libpmisis_la-sockunion.Plo -rm -f ./$(DEPDIR)/libpmisis_la-stream.Plo -rm -f ./$(DEPDIR)/libpmisis_la-table.Plo -rm -f ./$(DEPDIR)/libpmisis_la-thread.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/isis/thread.h0000644000175000017500000001467214354105275015202 0ustar paolopaolo/* Thread management routine header. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _THREAD_H_ #define _THREAD_H_ struct rusage_t { struct timeval real; }; #define RUSAGE_T struct rusage_t #define GETRUSAGE(X) thread_getrusage(X) /* Linked list of thread. */ struct thread_list { struct thread *head; struct thread *tail; int count; }; /* Master of the theads. */ struct thread_master { struct thread_list read; struct thread_list write; struct thread_list timer; struct thread_list event; struct thread_list ready; struct thread_list unuse; struct thread_list background; fd_set readfd; fd_set writefd; fd_set exceptfd; unsigned long alloc; }; typedef unsigned char thread_type; /* Thread itself. */ struct thread { thread_type type; /* thread type */ thread_type add_type; /* thread type */ struct thread *next; /* next pointer of the thread */ struct thread *prev; /* previous pointer of the thread */ struct thread_master *master; /* pointer to the struct thread_master. */ int (*func) (struct thread *); /* event function */ void *arg; /* event argument */ union { int val; /* second argument of the event. */ int fd; /* file descriptor in case of read/write. */ struct timeval sands; /* rest of time sands value. */ } u; RUSAGE_T ru; /* Indepth usage info. */ struct cpu_thread_history *hist; /* cache pointer to cpu_history */ char* funcname; }; struct cpu_thread_history { int (*func)(struct thread *); char *funcname; unsigned int total_calls; struct time_stats { unsigned long total, max; } real; thread_type types; }; /* Clocks supported by Quagga */ enum quagga_clkid { QUAGGA_CLK_REALTIME = 0, /* ala gettimeofday() */ QUAGGA_CLK_MONOTONIC, /* monotonic, against an indeterminate base */ QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */ }; /* Thread types. */ #define THREAD_READ 0 #define THREAD_WRITE 1 #define THREAD_TIMER 2 #define THREAD_EVENT 3 #define THREAD_READY 4 #define THREAD_BACKGROUND 5 #define THREAD_UNUSED 6 #define THREAD_EXECUTE 7 /* Thread yield time. */ #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */ /* Macros. */ #define THREAD_ARG(X) ((X)->arg) #define THREAD_FD(X) ((X)->u.fd) #define THREAD_VAL(X) ((X)->u.val) #define THREAD_READ_ON(master,thread,func,arg,sock) \ do { \ if (! thread) \ thread = thread_add_read (master, func, arg, sock); \ } while (0) #define THREAD_WRITE_ON(master,thread,func,arg,sock) \ do { \ if (! thread) \ thread = thread_add_write (master, func, arg, sock); \ } while (0) #define THREAD_TIMER_ON(master,thread,func,arg,time) \ do { \ if (! thread) \ thread = thread_add_timer (master, func, arg, time); \ } while (0) #define THREAD_OFF(thread) \ do { \ if (thread) \ { \ thread_cancel (thread); \ thread = NULL; \ } \ } while (0) #define THREAD_READ_OFF(thread) THREAD_OFF(thread) #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) #define THREAD_TIMER_OFF(thread) THREAD_OFF(thread) #define thread_add_read(m,f,a,v) funcname_thread_add_read(m,f,a,v,#f) #define thread_add_write(m,f,a,v) funcname_thread_add_write(m,f,a,v,#f) #define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f) #define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f) #define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f) #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f) /* The 4th arg to thread_add_background is the # of milliseconds to delay. */ #define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f) /* Prototypes. */ extern struct thread_master *thread_master_create (void); extern void thread_master_free (struct thread_master *); extern struct thread *funcname_thread_add_read (struct thread_master *, int (*)(struct thread *), void *, int, const char *); extern struct thread *funcname_thread_add_write (struct thread_master *, int (*)(struct thread *), void *, int, const char *); extern struct thread *funcname_thread_add_timer (struct thread_master *, int (*)(struct thread *), void *, long, const char *); extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, int (*)(struct thread *), void *, long, const char *); extern struct thread *funcname_thread_add_event (struct thread_master *, int (*)(struct thread *), void *, int, const char *); extern struct thread *funcname_thread_add_background (struct thread_master *, int (*func)(struct thread *), void *arg, long, const char *); extern struct thread *funcname_thread_execute (struct thread_master *, int (*)(struct thread *), void *, int, const char *); extern void thread_cancel (struct thread *); extern unsigned int thread_cancel_event (struct thread_master *, void *); extern struct thread *thread_fetch (struct thread_master *, struct thread *); extern void thread_call (struct thread *); extern unsigned long thread_timer_remain_second (struct thread *); extern int thread_should_yield (struct thread *); extern void thread_getrusage (RUSAGE_T *); extern int quagga_gettime (enum quagga_clkid, struct timeval *); extern time_t quagga_time (time_t *); extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, unsigned long *cpu_time_elapsed); /* Global variable containing a recent result from gettimeofday. This can be used instead of calling gettimeofday if a recent value is sufficient. This is guaranteed to be refreshed before a thread is called. */ extern struct timeval recent_time; /* Similar to recent_time, but a monotonically increasing time value */ extern struct timeval recent_relative_time (void); #endif /* _THREAD_H_ */ pmacct-1.7.8/src/isis/stream.h0000644000175000017500000001647714354105275015233 0ustar paolopaolo/* * Packet interface * Copyright (C) 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _STREAM_H_ #define _STREAM_H_ #include "prefix.h" /* * A stream is an arbitrary buffer, whose contents generally are assumed to * be in network order. * * A stream has the following attributes associated with it: * * - size: the allocated, invariant size of the buffer. * * - getp: the get position marker, denoting the offset in the stream where * the next read (or 'get') will be from. This getp marker is * automatically adjusted when data is read from the stream, the * user may also manipulate this offset as they wish, within limits * (see below) * * - endp: the end position marker, denoting the offset in the stream where * valid data ends, and if the user attempted to write (or * 'put') data where that data would be written (or 'put') to. * * These attributes are all size_t values. * * Constraints: * * 1. getp can never exceed endp * * - hence if getp is equal to endp, there is no more valid data that can be * gotten from the stream (though, the user may reposition getp to earlier in * the stream, if they wish). * * 2. endp can never exceed size * * - hence, if endp is equal to size, then the stream is full, and no more * data can be written to the stream. * * In other words the following must always be true, and the stream * abstraction is allowed internally to assert that the following property * holds true for a stream, as and when it wishes: * * getp <= endp <= size * * It is the users responsibility to ensure this property is never violated. * * A stream therefore can be thought of like this: * * --------------------------------------------------- * |XXXXXXXXXXXXXXXXXXXXXXXX | * --------------------------------------------------- * ^ ^ ^ * getp endp size * * This shows a stream containing data (shown as 'X') up to the endp offset. * The stream is empty from endp to size. Without adjusting getp, there are * still endp-getp bytes of valid data to be read from the stream. * * Methods are provided to get and put to/from the stream, as well as * retrieve the values of the 3 markers and manipulate the getp marker. * * Note: * At the moment, newly allocated streams are zero filled. Hence, one can * use stream_forward_endp() to effectively create arbitrary zero-fill * padding. However, note that stream_reset() does *not* zero-out the * stream. This property should **not** be relied upon. * * Best practice is to use stream_put (, NULL, ) to zero out * any part of a stream which isn't otherwise written to. */ /* Stream buffer. */ struct stream { size_t getp; /* next get position */ size_t endp; /* last valid data position */ size_t size; /* size of data segment */ unsigned char *data; /* data pointer */ }; /* Utility macros. */ #define STREAM_SIZE(S) ((S)->size) /* number of bytes which can still be written */ #define STREAM_WRITEABLE(S) ((S)->size - (S)->endp) /* number of bytes still to be read */ #define STREAM_READABLE(S) ((S)->endp - (S)->getp) /* deprecated macros - do not use in new code */ #define STREAM_PNT(S) stream_pnt((S)) #define STREAM_DATA(S) ((S)->data) #define STREAM_REMAIN(S) STREAM_WRITEABLE((S)) /* Stream prototypes. * For stream_{put,get}S, the S suffix mean: * * c: character (unsigned byte) * w: word (two bytes) * l: long (two words) * q: quad (four words) */ extern struct stream *stream_new (size_t); extern void stream_free (struct stream *); extern struct stream * stream_copy (struct stream *, struct stream *src); extern struct stream *stream_dup (struct stream *); extern size_t stream_resize (struct stream *, size_t); extern size_t stream_get_getp (struct stream *); extern size_t stream_get_endp (struct stream *); extern size_t stream_get_size (struct stream *); extern u_char *stream_get_data (struct stream *); extern void stream_set_getp (struct stream *, size_t); extern void stream_forward_getp (struct stream *, size_t); extern void stream_forward_endp (struct stream *, size_t); extern void stream_put (struct stream *, const void *, size_t); extern int stream_putc (struct stream *, u_char); extern int stream_putc_at (struct stream *, size_t, u_char); extern int stream_putw (struct stream *, u_int16_t); extern int stream_putw_at (struct stream *, size_t, u_int16_t); extern int stream_putl (struct stream *, u_int32_t); extern int stream_putl_at (struct stream *, size_t, u_int32_t); extern int stream_putq (struct stream *, uint64_t); extern int stream_putq_at (struct stream *, size_t, uint64_t); extern int stream_put_ipv4 (struct stream *, u_int32_t); extern int stream_put_in_addr (struct stream *, struct in_addr *); extern int stream_put_prefix (struct stream *, struct isis_prefix *); extern void stream_get (void *, struct stream *, size_t); extern u_char stream_getc (struct stream *); extern u_char stream_getc_from (struct stream *, size_t); extern u_int16_t stream_getw (struct stream *); extern u_int16_t stream_getw_from (struct stream *, size_t); extern u_int32_t stream_getl (struct stream *); extern u_int32_t stream_getl_from (struct stream *, size_t); extern uint64_t stream_getq (struct stream *); extern uint64_t stream_getq_from (struct stream *, size_t); extern u_int32_t stream_get_ipv4 (struct stream *); #undef stream_read #undef stream_write /* Deprecated: assumes blocking I/O. Will be removed. Use stream_read_try instead. */ extern int stream_read (struct stream *, int, size_t); /* Deprecated: all file descriptors should already be non-blocking. Will be removed. Use stream_read_try instead. */ extern int stream_read_unblock (struct stream *, int, size_t); /* Read up to size bytes into the stream. Return code: >0: number of bytes read 0: end-of-file -1: fatal error -2: transient error, should retry later (i.e. EAGAIN or EINTR) This is suitable for use with non-blocking file descriptors. */ extern ssize_t stream_read_try(struct stream *, int, size_t); extern ssize_t stream_recvmsg (struct stream *, int, struct msghdr *, int, size_t); extern ssize_t stream_recvfrom (struct stream *, int, size_t, int, struct sockaddr *, socklen_t *); extern size_t stream_write (struct stream *, const void *, size_t); extern void stream_reset (struct stream *); extern int stream_flush (struct stream *, int); extern int stream_empty (struct stream *); /* is the stream empty? */ extern u_char *stream_pnt (struct stream *); extern int readn (int, u_char *, int); #endif /* _STREAM_H_ */ pmacct-1.7.8/src/isis/isis-globals.c0000644000175000017500000000054014354105275016303 0ustar paolopaolo#include "pmacct.h" #include "isis.h" struct thread_master *master = NULL; struct isis *isis = NULL; struct in_addr router_id_zebra; struct timeval isis_now, isis_spf_deadline, isis_psnp_deadline; struct igp_map_entry ime; pcap_dumper_t *idmm_fd = NULL; u_int32_t glob_isis_seq_num = 0; struct sysid_fragment sysid_fragment_table[MAX_IGP_MAP_NODES]; pmacct-1.7.8/src/isis/isisd.h0000644000175000017500000001120614354105275015034 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isisd.h * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISISD_H_ #define _ISISD_H_ #define ISISD_VERSION "0.0.7" #define ZEBRA_ROUTE_MAX 11 /* uncomment if you are a developer in bug hunt */ struct rmap { char *name; struct route_map *map; }; struct isis { u_long process_id; int sysid_set; u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ struct pm_list *area_list; /* list of IS-IS areas */ struct pm_list *init_circ_list; struct pm_list *nexthops; /* IPv4 next hops from this IS */ struct pm_list *nexthops6; /* IPv6 next hops from this IS */ u_char max_area_addrs; /* maximumAreaAdresses */ struct area_addr *man_area_addrs; /* manualAreaAddresses */ u_int32_t debugs; /* bitmap for debug */ time_t uptime; /* when did we start */ struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ /* Redistributed external information. */ struct route_table *external_info[ZEBRA_ROUTE_MAX + 1]; /* Redistribute metric info. */ struct { int type; /* Internal or External */ int value; /* metric value */ } dmetric[ZEBRA_ROUTE_MAX + 1]; struct { char *name; struct route_map *map; } rmap[ZEBRA_ROUTE_MAX + 1]; struct { struct { char *name; struct route_map *map; } rmap[ZEBRA_ROUTE_MAX + 1]; } inet6_afmode; }; struct isis_area { struct isis *isis; /* back pointer */ dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ struct isis_spftree *spftree[ISIS_LEVELS]; /* The v4 SPTs */ struct route_table *route_table[ISIS_LEVELS]; /* IPv4 routes */ struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */ struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */ unsigned int min_bcast_mtu; struct pm_list *circuit_list; /* IS-IS circuits */ struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_remove_aged; struct thread *t_lsp_l1_regenerate; struct thread *t_lsp_l2_regenerate; int lsp_regenerate_pending[ISIS_LEVELS]; struct thread *t_lsp_refresh[ISIS_LEVELS]; /* * Configurables */ struct isis_passwd area_passwd; struct isis_passwd domain_passwd; /* do we support dynamic hostnames? */ char dynhostname; /* do we support new style metrics? */ char newmetric; char oldmetric; /* identifies the routing instance */ char *area_tag; /* area addresses for this area */ struct pm_list *area_addrs; u_int16_t max_lsp_lifetime[ISIS_LEVELS]; char is_type; /* level-1 level-1-2 or level-2-only */ u_int16_t lsp_refresh[ISIS_LEVELS]; /* minimum time allowed before lsp retransmission */ u_int16_t lsp_gen_interval[ISIS_LEVELS]; /* min interval between between consequtive SPFs */ u_int16_t min_spf_interval[ISIS_LEVELS]; /* the percentage of LSP mtu size used, before generating a new frag */ int lsp_frag_threshold; int ip_circuits; int ipv6_circuits; /* Counters */ u_int32_t circuit_state_changes; }; extern void isis_init (void); extern struct isis_area *isis_area_lookup (const char *); extern struct isis_area *isis_area_create (); extern int area_net_title(struct isis_area *, const char *); extern int area_clear_net_title(struct isis_area *, const char *); #define DEBUG_ADJ_PACKETS (1<<0) #define DEBUG_CHECKSUM_ERRORS (1<<1) #define DEBUG_LOCAL_UPDATES (1<<2) #define DEBUG_PROTOCOL_ERRORS (1<<3) #define DEBUG_SNP_PACKETS (1<<4) #define DEBUG_UPDATE_PACKETS (1<<5) #define DEBUG_SPF_EVENTS (1<<6) #define DEBUG_SPF_STATS (1<<7) #define DEBUG_SPF_TRIGGERS (1<<8) #define DEBUG_RTE_EVENTS (1<<9) #define DEBUG_EVENTS (1<<10) #define DEBUG_ZEBRA (1<<11) #endif /* _ISISD_H_ */ pmacct-1.7.8/src/isis/isis_tlv.h0000644000175000017500000002420314354105275015556 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - isis_tlv.h * IS-IS TLV related routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_TLV_H_ #define _ISIS_TLV_H_ /* * The list of TLVs we (should) support. * ____________________________________________________________________________ * Name Value IIH LSP SNP Status * LAN * ____________________________________________________________________________ * * Area Addresses 1 y y n ISO10589 * IIS Neighbors 2 n y n ISO10589 * ES Neighbors 3 n y n ISO10589 * IIS Neighbors 6 y n n ISO10589 * Padding 8 y n n ISO10589 * LSP Entries 9 n n y ISO10589 * Authentication 10 y y y ISO10589, RFC3567 * Checksum 12 y n y RFC3358 * TE IS Reachability 22 n y n RFC3784 * IS Alias 24 n y n RFC3786 * IP Int. Reachability 128 n y n RFC1195 * Protocols Supported 129 y y n RFC1195 * IP Ext. Reachability 130 n y n RFC1195 * IDRPI 131 n y y RFC1195 * IP Interface Address 132 y y n RFC1195 * TE Router ID 134 n y n RFC3784 * Extended IP Reachability 135 n y n RFC3784 * Dynamic Hostname 137 n y n RFC2763 * Shared Risk Link Group 138 n y y draft-ietf-isis-gmpls-extensions * Restart TLV 211 y n n RFC3847 * MT IS Reachability 222 n y n draft-ietf-isis-wg-multi-topology * MT Supported 229 y y n draft-ietf-isis-wg-multi-topology * IPv6 Interface Address 232 y y n draft-ietf-isis_ipv6 * MT IP Reachability 235 n y n draft-ietf-isis-wg-multi-topology * IPv6 IP Reachability 236 n y n draft-ietf-isis_ipv6 * MT IPv6 IP Reachability 237 n y n draft-ietf-isis-wg-multi-topology * P2P Adjacency State 240 y n n RFC3373 * IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence * Router Capability 242 - - - draft-ietf-isis-caps * * * IS Reachability sub-TLVs we (should) support. * ____________________________________________________________________________ * Name Value Status * ____________________________________________________________________________ * Administartive group (color) 3 RFC3784 * Link Local/Remote Identifiers 4 draft-ietf-isis-gmpls-extensions * IPv4 interface address 6 RFC3784 * IPv4 neighbor address 8 RFC3784 * Maximum link bandwidth 9 RFC3784 * Reservable link bandwidth 10 RFC3784 * Unreserved bandwidth 11 RFC3784 * TE Default metric 18 RFC3784 * Link Protection Type 20 draft-ietf-isis-gmpls-extensions * Interface Switching Capability 21 draft-ietf-isis-gmpls-extensions * * * IP Reachability sub-TLVs we (should) support. * ____________________________________________________________________________ * Name Value Status * ____________________________________________________________________________ * 32bit administrative tag 1 draft-ietf-isis-admin-tags * 64bit administrative tag 2 draft-ietf-isis-admin-tags * Management prefix color 117 draft-ietf-isis-wg-multi-topology */ #define AREA_ADDRESSES 1 #define IS_NEIGHBOURS 2 #define ES_NEIGHBOURS 3 #define LAN_NEIGHBOURS 6 #define PADDING 8 #define LSP_ENTRIES 9 #define AUTH_INFO 10 #define CHECKSUM 12 #define TE_IS_NEIGHBOURS 22 #define IS_ALIAS 24 #define IPV4_INT_REACHABILITY 128 #define PROTOCOLS_SUPPORTED 129 #define IPV4_EXT_REACHABILITY 130 #define IDRP_INFO 131 #define IPV4_ADDR 132 #define TE_ROUTER_ID 134 #define TE_IPV4_REACHABILITY 135 #define DYNAMIC_HOSTNAME 137 #define GRACEFUL_RESTART 211 #define IPV6_ADDR 232 #define IPV6_REACHABILITY 236 #define WAY3_HELLO 240 #define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5) #define LAN_NEIGHBOURS_LEN 6 #define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */ #define IPV4_REACH_LEN 12 #define IPV6_REACH_LEN 22 /* struct for neighbor */ struct is_neigh { struct metric metrics; u_char neigh_id[ISIS_SYS_ID_LEN + 1]; }; /* struct for te is neighbor */ struct te_is_neigh { u_char neigh_id[ISIS_SYS_ID_LEN + 1]; u_char te_metric[3]; u_char sub_tlvs_length; }; /* struct for es neighbors */ struct es_neigh { struct metric metrics; /* approximate position of first, we use the * length ((uchar*)metric-1) to know all */ u_char first_es_neigh[ISIS_SYS_ID_LEN]; }; struct partition_desig_level2_is { struct pm_list *isis_system_ids; }; /* struct for lan neighbors */ struct lan_neigh { u_char LAN_addr[6]; }; /* struct for LSP entry */ struct lsp_entry { u_int16_t rem_lifetime; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; u_int32_t seq_num; u_int16_t checksum; } __attribute__ ((packed)); /* struct for checksum */ struct checksum { u_int16_t checksum; }; /* ipv4 reachability */ struct ipv4_reachability { struct metric metrics; struct in_addr prefix; struct in_addr mask; }; /* te router id */ struct te_router_id { struct in_addr id; }; /* te ipv4 reachability */ struct te_ipv4_reachability { u_int32_t te_metric; u_char control; u_char prefix_start; /* since this is variable length by nature it only */ }; /* points to an approximate location */ #define ISIS_TLV_HDR_LEN 2 struct idrp_info { u_char value; u_char len; }; struct area_address { u_char len; u_char afi; u_int16_t area_id; }; struct ipv6_reachability { u_int32_t metric; u_char control_info; u_char prefix_len; u_char prefix[16]; }; /* bits in control_info */ #define CTRL_INFO_DIRECTION 0x80 #define DIRECTION_UP 0 #define DIRECTION_DOWN 1 #define CTRL_INFO_DISTRIBUTION 0x40 #define DISTRIBUTION_INTERNAL 0 #define DISTRIBUTION_EXTERNAL 1 #define CTRL_INFO_SUBTLVS 0x20 /* * Pointer to each tlv type, filled by parse_tlvs() */ struct tlvs { struct pm_list *area_addrs; struct pm_list *is_neighs; struct pm_list *te_is_neighs; struct pm_list *es_neighs; struct pm_list *lsp_entries; struct pm_list *prefix_neighs; struct pm_list *lan_neighs; struct checksum *checksum; struct nlpids *nlpids; struct pm_list *ipv4_addrs; struct pm_list *ipv4_int_reachs; struct pm_list *ipv4_ext_reachs; struct pm_list *te_ipv4_reachs; struct hostname *hostname; struct te_router_id *router_id; struct pm_list *ipv6_addrs; struct pm_list *ipv6_reachs; struct isis_passwd auth_info; }; /* * Own definitions - used to bitmask found and expected */ #define TLVFLAG_AREA_ADDRS (1<<0) #define TLVFLAG_IS_NEIGHS (1<<1) #define TLVFLAG_ES_NEIGHS (1<<2) #define TLVFLAG_PARTITION_DESIG_LEVEL2_IS (1<<3) #define TLVFLAG_PREFIX_NEIGHS (1<<4) #define TLVFLAG_LAN_NEIGHS (1<<5) #define TLVFLAG_LSP_ENTRIES (1<<6) #define TLVFLAG_PADDING (1<<7) #define TLVFLAG_AUTH_INFO (1<<8) #define TLVFLAG_IPV4_INT_REACHABILITY (1<<9) #define TLVFLAG_NLPID (1<<10) #define TLVFLAG_IPV4_EXT_REACHABILITY (1<<11) #define TLVFLAG_IPV4_ADDR (1<<12) #define TLVFLAG_DYN_HOSTNAME (1<<13) #define TLVFLAG_IPV6_ADDR (1<<14) #define TLVFLAG_IPV6_REACHABILITY (1<<15) #define TLVFLAG_TE_IS_NEIGHS (1<<16) #define TLVFLAG_TE_IPV4_REACHABILITY (1<<17) #define TLVFLAG_3WAY_HELLO (1<<18) #define TLVFLAG_TE_ROUTER_ID (1<<19) #define TLVFLAG_CHECKSUM (1<<20) #define TLVFLAG_GRACEFUL_RESTART (1<<21) extern void init_tlvs (struct tlvs *, uint32_t); extern void free_tlvs (struct tlvs *); extern int parse_tlvs (char *, u_char *, int, u_int32_t *, u_int32_t *, struct tlvs *); extern void free_tlv (void *); extern int tlv_add_area_addrs (struct pm_list *, struct stream *); extern int tlv_add_is_neighs (struct pm_list *, struct stream *); extern int tlv_add_te_is_neighs (struct pm_list *, struct stream *); extern int tlv_add_lan_neighs (struct pm_list *, struct stream *); extern int tlv_add_nlpid (struct nlpids *, struct stream *); extern int tlv_add_checksum (struct checksum *, struct stream *); extern int tlv_add_authinfo (char, char, u_char *, struct stream *); extern int tlv_add_ip_addrs (struct pm_list *, struct stream *); extern int tlv_add_in_addr (struct in_addr *, struct stream *, u_char); extern int tlv_add_dynamic_hostname (struct hostname *, struct stream *); extern int tlv_add_lsp_entries (struct pm_list *, struct stream *); extern int tlv_add_ipv4_reachs (struct pm_list *, struct stream *); extern int tlv_add_te_ipv4_reachs (struct pm_list *, struct stream *); extern int tlv_add_ipv6_addrs (struct pm_list *, struct stream *); extern int tlv_add_ipv6_reachs (struct pm_list *, struct stream *); extern int tlv_add_padding (struct stream *); #endif /* _ISIS_TLV_H_ */ pmacct-1.7.8/src/isis/prefix.c0000644000175000017500000003234414354105275015217 0ustar paolopaolo/* * Prefix related functions. * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your option) any * later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "prefix.h" #include "sockunion.h" /* Maskbit. */ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; /* Number of bits in prefix type. */ #ifndef PNBBY #define PNBBY 8 #endif /* PNBBY */ #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) /* If n includes p prefix then return 1 else return 0. */ int isis_prefix_match (const struct isis_prefix *n, const struct isis_prefix *p) { int offset; int shift; const u_char *np, *pp; /* If n's prefix is longer than p's one return 0. */ if (n->prefixlen > p->prefixlen) return 0; /* Set both prefix's head pointer. */ np = (const u_char *)&n->u.prefix; pp = (const u_char *)&p->u.prefix; offset = n->prefixlen / PNBBY; shift = n->prefixlen % PNBBY; if (shift) if (maskbit[shift] & (np[offset] ^ pp[offset])) return 0; while (offset--) if (np[offset] != pp[offset]) return 0; return 1; } /* Copy prefix from src to dest. */ void isis_prefix_copy (struct isis_prefix *dest, const struct isis_prefix *src) { dest->family = src->family; dest->prefixlen = src->prefixlen; if (src->family == AF_INET) dest->u.prefix4 = src->u.prefix4; else if (src->family == AF_INET6) dest->u.prefix6 = src->u.prefix6; else { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): isis_prefix_copy(): Unknown address family %d\n", config.name, src->family); assert (0); } dest->adv_router = src->adv_router; } /* * Return 1 if the address/netmask contained in the prefix structure * is the same, and else return 0. For this routine, 'same' requires * that not only the prefix length and the network part be the same, * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not * the same. Note that this routine has the same return value sense * as '==' (which is different from isis_prefix_cmp). */ int isis_prefix_same (const struct isis_prefix *p1, const struct isis_prefix *p2) { if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) { if (p1->family == AF_INET) if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) return 1; if (p1->family == AF_INET6 ) if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) return 1; } return 0; } /* * Return 0 if the network prefixes represented by the struct prefix * arguments are the same prefix, and 1 otherwise. Network prefixes * are considered the same if the prefix lengths are equal and the * network parts are the same. Host bits (which are considered masked * by the prefix length) are not significant. Thus, 10.0.0.1/8 and * 10.0.0.2/8 are considered equivalent by this routine. Note that * this routine has the same return sense as strcmp (which is different * from isis_prefix_same). */ int isis_prefix_cmp (const struct isis_prefix *p1, const struct isis_prefix *p2) { int offset; int shift; /* Set both prefix's head pointer. */ const u_char *pp1 = (const u_char *)&p1->u.prefix; const u_char *pp2 = (const u_char *)&p2->u.prefix; if (p1->family != p2->family || p1->prefixlen != p2->prefixlen) return 1; offset = p1->prefixlen / 8; shift = p1->prefixlen % 8; if (shift) if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) return 1; while (offset--) if (pp1[offset] != pp2[offset]) return 1; return 0; } /* Return prefix family type string. */ const char * isis_prefix_family_str (const struct isis_prefix *p) { if (p->family == AF_INET) return "inet"; if (p->family == AF_INET6) return "inet6"; return "unspec"; } /* Allocate new prefix_ipv4 structure. */ struct prefix_ipv4 * isis_prefix_ipv4_new () { struct prefix_ipv4 *p; /* Call isis_prefix_new to allocate a full-size struct isis_prefix to avoid problems where the struct prefix_ipv4 is cast to struct isis_prefix and unallocated bytes were being referenced (e.g. in structure assignments). */ p = (struct prefix_ipv4 *)isis_prefix_new(); p->family = AF_INET; return p; } /* When string format is invalid return 0. */ int isis_str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) { int ret; int plen; char *pnt; char *cp; /* Find slash inside string. */ pnt = strchr (str, '/'); /* String doesn't contail slash. */ if (pnt == NULL) { /* Convert string to prefix. */ ret = inet_aton (str, &p->prefix); if (ret == 0) return 0; /* If address doesn't contain slash we assume it host address. */ p->family = AF_INET; p->prefixlen = IPV4_MAX_BITLEN; return ret; } else { cp = calloc(1, (pnt - str) + 1); strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_aton (cp, &p->prefix); free(cp); /* Get prefix length. */ plen = (u_char) atoi (++pnt); if (plen > IPV4_MAX_PREFIXLEN) return 0; p->family = AF_INET; p->prefixlen = plen; } return ret; } /* Convert masklen into IP address's netmask. */ void isis_masklen2ip (int masklen, struct in_addr *netmask) { u_char *pnt; int bit; int offset; memset (netmask, 0, sizeof (struct in_addr)); pnt = (unsigned char *) netmask; offset = masklen / 8; bit = masklen % 8; while (offset--) *pnt++ = 0xff; if (bit) *pnt = maskbit[bit]; } /* Convert IP address's netmask into integer. We assume netmask is sequential one. Argument netmask should be network byte order. */ u_char isis_ip_masklen (struct in_addr netmask) { u_char len; u_char *pnt; u_char *end; u_char val; len = 0; pnt = (u_char *) &netmask; end = pnt + 4; while ((pnt < end) && (*pnt == 0xff)) { len+= 8; pnt++; } if (pnt < end) { val = *pnt; while (val) { len++; val <<= 1; } } return len; } /* Apply mask to IPv4 prefix. */ void isis_apply_mask_ipv4 (struct prefix_ipv4 *p) { u_char *pnt; int index; int offset; index = p->prefixlen / 8; if (index < 4) { pnt = (u_char *) &p->prefix; offset = p->prefixlen % 8; pnt[index] &= maskbit[offset]; index++; while (index < 4) pnt[index++] = 0; } } /* Allocate a new ip version 6 route */ struct prefix_ipv6 * isis_prefix_ipv6_new (void) { struct prefix_ipv6 *p; /* Allocate a full-size struct isis_prefix to avoid problems with structure size mismatches. */ p = (struct prefix_ipv6 *)isis_prefix_new(); p->family = AF_INET6; return p; } /* Free prefix for IPv6. */ void isis_prefix_ipv6_free (struct prefix_ipv6 *p) { isis_prefix_free((struct isis_prefix *)p); } /* If given string is valid return pin6 else return NULL */ int isis_str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) { char *pnt; char *cp; int ret; pnt = strchr (str, '/'); /* If string doesn't contain `/' treat it as host route. */ if (pnt == NULL) { ret = inet_pton (AF_INET6, str, &p->prefix); if (ret == 0) return 0; p->prefixlen = IPV6_MAX_BITLEN; } else { int plen; cp = calloc(0, (pnt - str) + 1); strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_pton (AF_INET6, cp, &p->prefix); free (cp); if (ret == 0) return 0; plen = (u_char) atoi (++pnt); if (plen > 128) return 0; p->prefixlen = plen; } p->family = AF_INET6; return ret; } /* Convert struct in6_addr netmask into integer. * FIXME return u_char as isis_ip_maskleni() does. */ int isis_ip6_masklen (struct in6_addr netmask) { int len = 0; unsigned char val; unsigned char *pnt; pnt = (unsigned char *) & netmask; while ((*pnt == 0xff) && len < 128) { len += 8; pnt++; } if (len < 128) { val = *pnt; while (val) { len++; val <<= 1; } } return len; } void isis_masklen2ip6 (int masklen, struct in6_addr *netmask) { unsigned char *pnt; int bit; int offset; memset (netmask, 0, sizeof (struct in6_addr)); pnt = (unsigned char *) netmask; offset = masklen / 8; bit = masklen % 8; while (offset--) *pnt++ = 0xff; if (bit) *pnt = maskbit[bit]; } void isis_apply_mask_ipv6 (struct prefix_ipv6 *p) { u_char *pnt; int index; int offset; index = p->prefixlen / 8; if (index < 16) { pnt = (u_char *) &p->prefix; offset = p->prefixlen % 8; pnt[index] &= maskbit[offset]; index++; while (index < 16) pnt[index++] = 0; } } void isis_str2in6_addr (const char *str, struct in6_addr *addr) { int i; unsigned int x; /* %x must point to unsinged int */ for (i = 0; i < 16; i++) { sscanf (str + (i * 2), "%02x", &x); addr->s6_addr[i] = x & 0xff; } } void isis_apply_mask (struct isis_prefix *p) { switch (p->family) { case AF_INET: isis_apply_mask_ipv4 ((struct prefix_ipv4 *)p); break; case AF_INET6: isis_apply_mask_ipv6 ((struct prefix_ipv6 *)p); break; default: break; } return; } /* Utility function of convert between struct isis_prefix <=> union sockunion. * FIXME This function isn't used anywhere. */ struct isis_prefix * sockunion2prefix (const union sockunion *dest, const union sockunion *mask) { if (dest->sa.sa_family == AF_INET) { struct prefix_ipv4 *p; p = isis_prefix_ipv4_new (); p->family = AF_INET; p->prefix = dest->sin.sin_addr; p->prefixlen = isis_ip_masklen (mask->sin.sin_addr); return (struct isis_prefix *) p; } if (dest->sa.sa_family == AF_INET6) { struct prefix_ipv6 *p; p = isis_prefix_ipv6_new (); p->family = AF_INET6; p->prefixlen = isis_ip6_masklen (mask->sin6.sin6_addr); memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); return (struct isis_prefix *) p; } return NULL; } /* Utility function of convert between struct isis_prefix <=> union sockunion. */ struct isis_prefix * sockunion2hostprefix (const union sockunion *su) { if (su->sa.sa_family == AF_INET) { struct prefix_ipv4 *p; p = isis_prefix_ipv4_new (); p->family = AF_INET; p->prefix = su->sin.sin_addr; p->prefixlen = IPV4_MAX_BITLEN; return (struct isis_prefix *) p; } if (su->sa.sa_family == AF_INET6) { struct prefix_ipv6 *p; p = isis_prefix_ipv6_new (); p->family = AF_INET6; p->prefixlen = IPV6_MAX_BITLEN; memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr)); return (struct isis_prefix *) p; } return NULL; } int isis_prefix_blen (const struct isis_prefix *p) { switch (p->family) { case AF_INET: return IPV4_MAX_BYTELEN; break; case AF_INET6: return IPV6_MAX_BYTELEN; break; } return 0; } /* Generic function for conversion string to struct prefix. */ int isis_str2prefix (const char *str, struct isis_prefix *p) { int ret; /* First we try to convert string to struct prefix_ipv4. */ ret = isis_str2prefix_ipv4 (str, (struct prefix_ipv4 *) p); if (ret) return ret; /* Next we try to convert string to struct prefix_ipv6. */ ret = isis_str2prefix_ipv6 (str, (struct prefix_ipv6 *) p); if (ret) return ret; return 0; } int isis_prefix2str (const struct isis_prefix *p, char *str, int size) { char buf[BUFSIZ]; inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); snprintf (str, size, "%s/%d", buf, p->prefixlen); return 0; } struct isis_prefix * isis_prefix_new () { struct isis_prefix *p; p = calloc(1, sizeof *p); return p; } /* Free prefix structure. */ void isis_prefix_free (struct isis_prefix *p) { free(p); } /* Utility function to convert ipv4 netmask to prefixes ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ int netmask_isis_str2prefix_str (const char *net_str, const char *mask_str, char *prefix_str) { struct in_addr network; struct in_addr mask; u_char prefixlen; u_int32_t destination; int ret; ret = inet_aton (net_str, &network); if (! ret) return 0; if (mask_str) { ret = inet_aton (mask_str, &mask); if (! ret) return 0; prefixlen = isis_ip_masklen (mask); } else { destination = ntohl (network.s_addr); if (network.s_addr == 0) prefixlen = 0; else if (IN_CLASSC (destination)) prefixlen = 24; else if (IN_CLASSB (destination)) prefixlen = 16; else if (IN_CLASSA (destination)) prefixlen = 8; else return 0; } sprintf (prefix_str, "%s/%d", net_str, prefixlen); return 1; } pmacct-1.7.8/src/isis/hash.c0000644000175000017500000001143414354105275014642 0ustar paolopaolo/* Hash routine. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra 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, or (at your * option) any later version. * * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "hash.h" /* Allocate a new hash. */ struct hash * isis_hash_create_size (unsigned int size, unsigned int (*hash_key) (void *), int (*hash_cmp) (const void *, const void *)) { struct hash *hash; hash = calloc(1, sizeof (struct hash)); hash->index = calloc(1, sizeof (struct hash_backet *) * size); hash->size = size; hash->hash_key = hash_key; hash->hash_cmp = hash_cmp; hash->count = 0; return hash; } /* Allocate a new hash with default hash size. */ struct hash * isis_hash_create (unsigned int (*hash_key) (void *), int (*hash_cmp) (const void *, const void *)) { return isis_hash_create_size (HASHTABSIZE, hash_key, hash_cmp); } /* Utility function for hash_get(). When this function is specified as alloc_func, return arugment as it is. This function is used for intern already allocated value. */ void * isis_hash_alloc_intern (void *arg) { return arg; } /* Lookup and return hash backet in hash. If there is no corresponding hash backet and alloc_func is specified, create new hash backet. */ void * isis_hash_get (struct hash *hash, void *data, void * (*alloc_func) (void *)) { unsigned int key; unsigned int index; void *newdata; struct hash_backet *backet; key = (*hash->hash_key) (data); index = key % hash->size; for (backet = hash->index[index]; backet != NULL; backet = backet->next) if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) return backet->data; if (alloc_func) { newdata = (*alloc_func) (data); if (newdata == NULL) return NULL; backet = calloc(1, sizeof (struct hash_backet)); backet->data = newdata; backet->key = key; backet->next = hash->index[index]; hash->index[index] = backet; hash->count++; return backet->data; } return NULL; } /* Hash lookup. */ void * isis_hash_lookup (struct hash *hash, void *data) { return isis_hash_get (hash, data, NULL); } /* Simple Bernstein hash which is simple and fast for common case */ unsigned int string_hash_make (const char *str) { unsigned int hash = 0; while (*str) hash = (hash * 33) ^ (unsigned int) *str++; return hash; } /* This function release registered value from specified hash. When release is successfully finished, return the data pointer in the hash backet. */ void * isis_hash_release (struct hash *hash, void *data) { void *ret; unsigned int key; unsigned int index; struct hash_backet *backet; struct hash_backet *pp; key = (*hash->hash_key) (data); index = key % hash->size; for (backet = pp = hash->index[index]; backet; backet = backet->next) { if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) { if (backet == pp) hash->index[index] = backet->next; else pp->next = backet->next; ret = backet->data; free(backet); hash->count--; return ret; } pp = backet; } return NULL; } /* Iterator function for hash. */ void isis_hash_iterate (struct hash *hash, void (*func) (struct hash_backet *, void *), void *arg) { unsigned int i; struct hash_backet *hb; struct hash_backet *hbnext; for (i = 0; i < hash->size; i++) for (hb = hash->index[i]; hb; hb = hbnext) { /* get pointer to next hash backet here, in case (*func) * decides to delete hb by calling hash_release */ hbnext = hb->next; (*func) (hb, arg); } } /* Clean up hash. */ void isis_hash_clean (struct hash *hash, void (*free_func) (void *)) { unsigned int i; struct hash_backet *hb; struct hash_backet *next; for (i = 0; i < hash->size; i++) { for (hb = hash->index[i]; hb; hb = next) { next = hb->next; if (free_func) (*free_func) (hb->data); free(hb); hash->count--; } hash->index[i] = NULL; } } /* Free hash memory. You may call hash_clean before call this function. */ void isis_hash_free (struct hash *hash) { free(hash->index); free(hash); } pmacct-1.7.8/src/isis/isis.c0000644000175000017500000006770314354105275014700 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-dlt.h" #include "isis.h" #include "thread_pool.h" #include "stream.h" #include "hash.h" #include "prefix.h" #include "dict.h" #include "thread.h" #include "iso.h" #include "table.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_adjacency.h" #include "isis_circuit.h" #include "isis_network.h" #include "isis_misc.h" #include "isis_flags.h" #include "isis_tlv.h" #include "isisd.h" #include "isis_dynhn.h" #include "isis_lsp.h" #include "isis_pdu.h" #include "iso_checksum.h" #include "isis_csm.h" #include "isis_events.h" #include "isis_spf.h" #include "isis_route.h" /* variables to be exported away */ thread_pool_t *isis_pool; /* Functions */ void nfacctd_isis_wrapper() { /* initialize threads pool */ isis_pool = allocate_thread_pool(1); assert(isis_pool); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): %d thread(s) initialized\n", config.name, 1); /* giving a kick to the BGP thread */ send_to_pool(isis_pool, skinny_isis_daemon, NULL); } int skinny_isis_daemon() { char errbuf[PCAP_ERRBUF_SIZE]; struct pm_pcap_device device; struct pm_pcap_isis_callback_data cb_data; struct host_addr addr; struct prefix_ipv4 *ipv4; struct plugin_requests req; int index, ret; char area_tag[] = "default"; struct isis_area *area; struct isis_circuit *circuit; struct interface interface; memset(&device, 0, sizeof(struct pm_pcap_device)); memset(&cb_data, 0, sizeof(cb_data)); memset(&interface, 0, sizeof(interface)); memset(&isis_spf_deadline, 0, sizeof(isis_spf_deadline)); memset(&ime, 0, sizeof(ime)); memset(&req, 0, sizeof(req)); reload_map = FALSE; glob_isis_seq_num = 0; /* initializing IS-IS structures */ isis = NULL; isis_init(); dyn_cache_init(); /* thread master */ master = thread_master_create(); if (!config.nfacctd_isis_iface && !config.igp_daemon_map) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): No 'isis_daemon_iface' and 'igp_daemon_map' values specified. Terminating thread.\n", config.name); exit_gracefully(1); } else if (config.nfacctd_isis_iface && config.igp_daemon_map) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): 'isis_daemon_iface' and 'igp_daemon_map' are mutually exclusive. Terminating thread.\n", config.name); exit_gracefully(1); } if (config.nfacctd_isis_iface) { if ((device.dev_desc = pcap_open_live(config.nfacctd_isis_iface, 65535, 0, 1000, errbuf)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): pcap_open_live(): %s\n", config.name, errbuf); exit_gracefully(1); } device.link_type = pcap_datalink(device.dev_desc); for (index = 0; _isis_devices[index].link_type != -1; index++) { if (device.link_type == _isis_devices[index].link_type) device.data = &_isis_devices[index]; } if (device.data == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): data link not supported: %d\n", config.name, device.link_type); return ERR; } else { Log(LOG_INFO, "OK ( %s/core/ISIS ): link type is: %d\n", config.name, device.link_type); cb_data.device = &device; } } if (config.igp_daemon_map) { int igp_map_allocated = FALSE; glob_isis_seq_num++; req.key_value_table = (void *) &ime; memset(&sysid_fragment_table, 0, sizeof(sysid_fragment_table)); load_id_file(MAP_IGP, config.igp_daemon_map, NULL, &req, &igp_map_allocated); } area = isis_area_create(); area->area_tag = area_tag; area->is_type = IS_LEVEL_2; area->newmetric = TRUE; pm_listnode_add(isis->area_list, area); Log(LOG_DEBUG, "DEBUG ( %s/core/ISIS ): New IS-IS area instance %s\n", config.name, area->area_tag); if (config.nfacctd_isis_net) area_net_title(area, config.nfacctd_isis_net); else { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): 'isis_daemon_net' value is not specified. Terminating thread.\n", config.name); exit_gracefully(1); } circuit = isis_circuit_new(); circuit->circ_type = CIRCUIT_T_P2P; if (config.nfacctd_isis_iface) { circuit->fd = pcap_fileno(device.dev_desc); circuit->tx = isis_send_pdu_p2p; } else { circuit->fd = 0; circuit->tx = NULL; } circuit->interface = &interface; circuit->state = C_STATE_UP; if (config.nfacctd_isis_ip) { trim_spaces(config.nfacctd_isis_ip); ret = str_to_addr(config.nfacctd_isis_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): 'isis_daemon_ip' value is not a valid IPv4/IPv6 address. Terminating thread.\n", config.name); exit_gracefully(1); } } else { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): 'isis_daemon_ip' value is not specified. Terminating thread.\n", config.name); exit_gracefully(1); } circuit->ip_router = addr.address.ipv4.s_addr; ipv4 = isis_prefix_ipv4_new(); ipv4->prefixlen = 32; ipv4->prefix.s_addr = addr.address.ipv4.s_addr; circuit->ip_addrs = pm_list_new(); pm_listnode_add(circuit->ip_addrs, ipv4); circuit_update_nlpids(circuit); isis_circuit_configure(circuit, area); cb_data.circuit = circuit; area->ip_circuits = 1; if (config.nfacctd_isis_iface) { memcpy(circuit->interface->name, config.nfacctd_isis_iface, strlen(config.nfacctd_isis_iface)); circuit->interface->ifindex = if_nametoindex(config.nfacctd_isis_iface); } else { // XXX } if (!config.nfacctd_isis_mtu) config.nfacctd_isis_mtu = SNAPLEN_ISIS_DEFAULT; if (config.nfacctd_isis_iface) { for (;;) { /* XXX: should get a select() here at some stage? */ pcap_loop(device.dev_desc, -1, isis_pdu_runner, (u_char *) &cb_data); break; } pcap_close(device.dev_desc); } else if (config.igp_daemon_map) { for (;;) { sleep(3); if (reload_map) { int igp_map_allocated = FALSE; glob_isis_seq_num++; memset(&sysid_fragment_table, 0, sizeof(sysid_fragment_table)); load_id_file(MAP_IGP, config.igp_daemon_map, NULL, &req, &igp_map_allocated); reload_map = FALSE; } } } return SUCCESS; } void isis_pdu_runner(u_char *user, const struct pcap_pkthdr *pkthdr, const u_char *buf) { struct pm_pcap_isis_callback_data *cb_data = (struct pm_pcap_isis_callback_data *) user; struct pm_pcap_device *device = cb_data->device; struct isis_circuit *circuit = cb_data->circuit; struct packet_ptrs pptrs; int ret; struct stream stm; u_char *ssnpa; /* Let's export a time reference */ memcpy(&isis_now, &pkthdr->ts, sizeof(struct timeval)); /* check if we have to expire adjacency first */ if (circuit && circuit->u.p2p.neighbor) { if (timeval_cmp(&isis_now, &circuit->u.p2p.neighbor->expire) >= 0) isis_adj_expire(circuit->u.p2p.neighbor); } memset(&pptrs, 0, sizeof(pptrs)); memset(&stm, 0, sizeof(stm)); if (buf) { pptrs.pkthdr = (struct pcap_pkthdr *) pkthdr; pptrs.packet_ptr = (u_char *) buf; (*device->data->handler)(pkthdr, &pptrs); if (pptrs.iph_ptr) { if ((*pptrs.l3_handler)(&pptrs)) { /*assembling handover to isis_handle_pdu() */ stm.data = pptrs.iph_ptr; stm.getp = 0; stm.endp = pkthdr->caplen - (pptrs.iph_ptr - pptrs.packet_ptr); stm.size = pkthdr->caplen - (pptrs.iph_ptr - pptrs.packet_ptr); ssnpa = pptrs.packet_ptr; circuit->rcv_stream = &stm; circuit->interface->mtu = config.nfacctd_isis_mtu; /* process IS-IS packet */ isis_handle_pdu (circuit, ssnpa); } } } /* check if it's time to run SPF */ if (timeval_cmp(&isis_now, &isis_spf_deadline) >= 0) { if (circuit->area->is_type & IS_LEVEL_1) { if (circuit->area->ip_circuits) { ret = isis_run_spf(circuit->area, 1, AF_INET); isis_route_validate_table (circuit->area, circuit->area->route_table[0]); } /* XXX: IPv6 handled here */ } if (circuit->area->is_type & IS_LEVEL_2) { if (circuit->area->ip_circuits) { ret = isis_run_spf(circuit->area, 2, AF_INET); (void)ret; //TODO treat error isis_route_validate_table (circuit->area, circuit->area->route_table[1]); } /* XXX: IPv6 handled here */ } isis_route_validate_merge (circuit->area, AF_INET); dyn_cache_cleanup(); isis_spf_deadline.tv_sec = isis_now.tv_sec + isis_jitter(PERIODIC_SPF_INTERVAL, 10); isis_spf_deadline.tv_usec = 0; } if (timeval_cmp(&isis_now, &isis_psnp_deadline) >= 0) { send_psnp(1, circuit); send_psnp(2, circuit); isis_psnp_deadline.tv_sec = isis_now.tv_sec + isis_jitter(PSNP_INTERVAL, PSNP_JITTER); isis_psnp_deadline.tv_usec = 0; } } void isis_sll_handler(const struct pcap_pkthdr *h, register struct packet_ptrs *pptrs) { register const struct sll_header *sllp; u_int caplen = h->caplen; u_int16_t etype, nl; u_char *p; if (caplen < SLL_HDR_LEN) { pptrs->iph_ptr = NULL; return; } p = pptrs->packet_ptr; (void)p; //TODO treat error sllp = (const struct sll_header *) pptrs->packet_ptr; etype = ntohs(sllp->sll_protocol); nl = SLL_HDR_LEN; if (etype == ETHERTYPE_GRE_ISO) { pptrs->l3_proto = ETHERTYPE_GRE_ISO; pptrs->l3_handler = iso_handler; pptrs->iph_ptr = (u_char *)(pptrs->packet_ptr + nl); return; } pptrs->l3_proto = 0; pptrs->l3_handler = NULL; pptrs->iph_ptr = NULL; } int iso_handler(register struct packet_ptrs *pptrs) { return FALSE; } void isis_srcdst_lookup(struct packet_ptrs *pptrs) { struct route_node *result; struct isis_area *area; char area_tag[] = "default"; int level; struct in_addr pref4; struct in6_addr pref6; pptrs->igp_src = NULL; pptrs->igp_dst = NULL; pptrs->igp_src_info = NULL; pptrs->igp_dst_info = NULL; area = isis_area_lookup(area_tag); if (area) { level = MAX(area->is_type, 2); if (pptrs->l3_proto == ETHERTYPE_IP) { if (!pptrs->igp_src) { memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, sizeof(struct in_addr)); result = route_node_match_ipv4(area->route_table[level-1], &pref4); if (result) { pptrs->igp_src = (char *) &result->p; pptrs->igp_src_info = (char *) result->info; if (result->p.prefixlen > pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_IGP; } } } if (!pptrs->igp_dst) { memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, sizeof(struct in_addr)); result = route_node_match_ipv4(area->route_table[level-1], &pref4); if (result) { pptrs->igp_dst = (char *) &result->p; pptrs->igp_dst_info = (char *) result->info; if (result->p.prefixlen > pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_IGP; } } } } else if (area && pptrs->l3_proto == ETHERTYPE_IPV6) { if (!pptrs->igp_src) { memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, sizeof(struct in6_addr)); result = route_node_match_ipv6(area->route_table6[level-1], &pref6); if (result) { pptrs->igp_src = (char *) &result->p; pptrs->igp_src_info = (char *) result->info; if (result->p.prefixlen > pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_IGP; } } } if (!pptrs->igp_dst) { memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, sizeof(struct in6_addr)); result = route_node_match_ipv6(area->route_table6[level-1], &pref6); if (result) { pptrs->igp_dst = (char *) &result->p; pptrs->igp_dst_info = (char *) result->info; if (result->p.prefixlen > pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_IGP; } } } } } } int igp_daemon_map_node_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; if (!str_to_addr(value, &entry->node) || entry->node.family != AF_INET) { Log(LOG_ERR, "ERROR ( %s ): Bad IPv4 address '%s'. ", filename, value); return TRUE; } return FALSE; } int igp_daemon_map_area_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; int x = 0, j, len; len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_ERR, "ERROR ( %s ): Bad 'area_id' value: '%s'. ", filename, value); return TRUE; } x++; } j = atoi(value); if (j < 0 || j > 65535) { Log(LOG_ERR, "ERROR ( %s ): Bad 'area_id' value (range: 0 >= value > 65536). ", filename); return TRUE; } entry->area_id = j; return FALSE; } int igp_daemon_map_adj_metric_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; char *str_ptr, *token, *sep, *ip_str, *metric_str, *endptr; int idx = 0; str_ptr = strdup(value); if (!str_ptr) { Log(LOG_ERR, "ERROR ( %s ): not enough memory to strdup(). ", filename); return TRUE; } while ((token = extract_token(&str_ptr, ';'))) { if (idx >= MAX_IGP_MAP_ELEM) { Log(LOG_ERR, "ERROR ( %s ): maximum number of elements (%u) per adj_metric violated. ", filename, MAX_IGP_MAP_ELEM); return TRUE; } sep = strchr(token, ','); if (!sep) { Log(LOG_WARNING, "WARN ( %s ): missing adj_metric entry separator '%s'.\n", filename, token); continue; } ip_str = token; metric_str = sep+1; *sep = '\0'; if (!isis_str2prefix(ip_str, &entry->adj_metric[idx].prefix) || entry->adj_metric[idx].prefix.family != AF_INET) { Log(LOG_WARNING, "WARN ( %s ): Bad IPv4 address '%s'.\n", filename, ip_str); continue; } entry->adj_metric[idx].metric = strtoull(metric_str, &endptr, 10); if (!entry->adj_metric[idx].metric) { Log(LOG_WARNING, "WARN ( %s ): Bad metric '%s'.\n", filename, metric_str); continue; } idx++; } if (!idx) { Log(LOG_ERR, "ERROR ( %s ): invalid or empty adj_metric entry '%s'. ", filename, value); return TRUE; } else entry->adj_metric_num = idx; return FALSE; } int igp_daemon_map_reach_metric_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; char *str_ptr, *token, *sep, *ip_str, *metric_str, *endptr; int idx = 0; str_ptr = strdup(value); if (!str_ptr) { Log(LOG_ERR, "ERROR ( %s ): not enough memory to strdup(). ", filename); return TRUE; } while ((token = extract_token(&str_ptr, ';'))) { if (idx >= MAX_IGP_MAP_ELEM) { Log(LOG_ERR, "ERROR ( %s ): maximum number of elements (%u) per reach_metric violated. ", filename, MAX_IGP_MAP_ELEM); return TRUE; } sep = strchr(token, ','); if (!sep) { Log(LOG_WARNING, "WARN ( %s ): missing reach_metric entry separator '%s'.\n", filename, token); continue; } ip_str = token; metric_str = sep+1; *sep = '\0'; if (!isis_str2prefix(ip_str, &entry->reach_metric[idx].prefix) || entry->reach_metric[idx].prefix.family != AF_INET) { Log(LOG_WARNING, "WARN ( %s ): Bad IPv4 address '%s'.\n", filename, ip_str); continue; } entry->reach_metric[idx].metric = strtoull(metric_str, &endptr, 10); if (!entry->reach_metric[idx].metric) { Log(LOG_WARNING, "WARN ( %s ): Bad metric '%s'.\n", filename, metric_str); continue; } idx++; } if (!idx) { Log(LOG_ERR, "ERROR ( %s ): invalid or empty reach_metric entry '%s'. ", filename, value); return TRUE; } else entry->reach_metric_num = idx; return FALSE; } int igp_daemon_map_reach6_metric_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; char *str_ptr, *token, *sep, *ip_str, *metric_str, *endptr; int idx = 0; str_ptr = strdup(value); if (!str_ptr) { Log(LOG_ERR, "ERROR ( %s ): not enough memory to strdup(). ", filename); return TRUE; } while ((token = extract_token(&str_ptr, ';'))) { if (idx >= MAX_IGP_MAP_ELEM) { Log(LOG_ERR, "ERROR ( %s ): maximum number of elements (%u) per reach6_metric violated. ", filename, MAX_IGP_MAP_ELEM); return TRUE; } sep = strchr(token, ','); if (!sep) { Log(LOG_WARNING, "WARN ( %s ): missing reach6_metric entry separator '%s'.\n", filename, token); continue; } ip_str = token; metric_str = sep+1; *sep = '\0'; if (!isis_str2prefix(ip_str, &entry->reach6_metric[idx].prefix) || entry->reach6_metric[idx].prefix.family != AF_INET6) { Log(LOG_WARNING, "WARN ( %s ): Bad IPv6 address '%s'.\n", filename, ip_str); continue; } entry->reach6_metric[idx].metric = strtoull(metric_str, &endptr, 10); if (!entry->reach6_metric[idx].metric) { Log(LOG_WARNING, "WARN ( %s ): Bad metric '%s'.\n", filename, metric_str); continue; } idx++; } if (!idx) { Log(LOG_ERR, "ERROR ( %s ): invalid or empty reach6_metric entry '%s'. ", filename, value); return TRUE; } else entry->reach6_metric_num = idx; return FALSE; } void igp_daemon_map_validate(char *filename, struct plugin_requests *req) { struct igp_map_entry *entry = (struct igp_map_entry *) req->key_value_table; struct pcap_pkthdr phdr; if (entry) { if (entry->node.family && entry->area_id && (entry->adj_metric_num || entry->reach_metric_num || entry->reach6_metric_num)) { u_char isis_dgram[RECEIVE_LSP_BUFFER_SIZE+sizeof(struct chdlc_header)+sizeof(struct isis_fixed_hdr)]; u_char *isis_dgram_ptr = isis_dgram; struct chdlc_header *chdlc_hdr; struct isis_fixed_hdr *isis_hdr; struct isis_link_state_hdr *lsp_hdr; struct idrp_info *adj_hdr, *reach_v4_hdr, *reach_v6_hdr, *proto_supported_hdr, *area_address_hdr; struct is_neigh *adj; struct ipv4_reachability *reach_v4; struct ipv6_reachability *reach_v6; struct area_address *area_addr; int rem_len = sizeof(isis_dgram), cnt, tlvs_cnt = 0, pdu_len = 0; memset(isis_dgram, 0, sizeof(isis_dgram)); /* can't use DLT_RAW for IS-IS, let's use DLT_CHDLC */ chdlc_hdr = (struct chdlc_header *) isis_dgram_ptr; chdlc_hdr->address = CHDLC_MCAST_ADDR; chdlc_hdr->control = CHDLC_FIXED_CONTROL; chdlc_hdr->protocol = ETHERTYPE_ISO; isis_dgram_ptr += sizeof(struct chdlc_header); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct chdlc_header), req, filename)) return; isis_hdr = (struct isis_fixed_hdr *) isis_dgram_ptr; isis_hdr->idrp = ISO10589_ISIS; isis_hdr->length = 27; /* fixed: IS-IS header + LSP header */ isis_hdr->version1 = TRUE; isis_hdr->pdu_type = 0x14; isis_hdr->version2 = TRUE; isis_dgram_ptr += sizeof(struct isis_fixed_hdr); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct isis_fixed_hdr), req, filename)) return; lsp_hdr = (struct isis_link_state_hdr *) isis_dgram_ptr; lsp_hdr->pdu_len = 0; /* updated later */ if (igp_daemon_map_handle_lsp_id(lsp_hdr->lsp_id, &entry->node)) return; lsp_hdr->seq_num = htonl(glob_isis_seq_num); lsp_hdr->rem_lifetime = htons(-1); /* maximum lifetime possible */ lsp_hdr->lsp_bits = 0x03; /* IS Type = L2 */ isis_dgram_ptr += sizeof(struct isis_link_state_hdr); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct isis_link_state_hdr), req, filename)) return; proto_supported_hdr = (struct idrp_info *) isis_dgram_ptr; proto_supported_hdr->value = PROTOCOLS_SUPPORTED; isis_dgram_ptr += sizeof(struct idrp_info); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct idrp_info), req, filename)) return; *isis_dgram_ptr = (u_char) 0xCC; isis_dgram_ptr++; proto_supported_hdr->len++; *isis_dgram_ptr = (u_char) 0x8E; isis_dgram_ptr++; proto_supported_hdr->len++; if (igp_daemon_map_handle_len(&rem_len, proto_supported_hdr->len, req, filename)) return; pdu_len += proto_supported_hdr->len; tlvs_cnt++; area_address_hdr = (struct idrp_info *) isis_dgram_ptr; area_address_hdr->value = AREA_ADDRESSES; area_address_hdr->len = sizeof(struct area_address); isis_dgram_ptr += sizeof(struct idrp_info); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct idrp_info), req, filename)) return; area_addr = (struct area_address *) isis_dgram_ptr; area_addr->len = 3; area_addr->afi = 0x49; area_addr->area_id = htons(entry->area_id); isis_dgram_ptr += area_address_hdr->len; if (igp_daemon_map_handle_len(&rem_len, area_address_hdr->len, req, filename)) return; pdu_len += area_address_hdr->len; tlvs_cnt++; if (entry->adj_metric_num) { adj_hdr = (struct idrp_info *) isis_dgram_ptr; adj_hdr->value = IS_NEIGHBOURS; adj_hdr->len = (11 * entry->adj_metric_num) + 1; pdu_len += adj_hdr->len; isis_dgram_ptr += sizeof(struct idrp_info); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct idrp_info), req, filename)) return; for (cnt = 0; cnt < entry->adj_metric_num; cnt++) { if (!cnt) { /* reserved space must be zero */ isis_dgram_ptr++; if (igp_daemon_map_handle_len(&rem_len, 1, req, filename)) return; } adj = (struct is_neigh *) isis_dgram_ptr; adj->metrics.metric_default = entry->adj_metric[cnt].metric; adj->metrics.metric_error = 0x80; adj->metrics.metric_expense = 0x80; adj->metrics.metric_delay = 0x80; memcpy(adj->neigh_id, &entry->adj_metric[cnt].prefix.u.prefix4, 4); isis_dgram_ptr += sizeof(struct is_neigh); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct is_neigh), req, filename)) return; } tlvs_cnt++; } if (entry->reach_metric_num) { reach_v4_hdr = (struct idrp_info *) isis_dgram_ptr; reach_v4_hdr->value = IPV4_INT_REACHABILITY; reach_v4_hdr->len = (IPV4_REACH_LEN * entry->reach_metric_num); pdu_len += reach_v4_hdr->len; isis_dgram_ptr += sizeof(struct idrp_info); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct idrp_info), req, filename)) return; for (cnt = 0; cnt < entry->reach_metric_num; cnt++) { reach_v4 = (struct ipv4_reachability *) isis_dgram_ptr; reach_v4->metrics.metric_default = entry->reach_metric[cnt].metric; reach_v4->metrics.metric_error = 0x80; reach_v4->metrics.metric_expense = 0x80; reach_v4->metrics.metric_delay = 0x80; memcpy(&reach_v4->prefix, &entry->reach_metric[cnt].prefix.u.prefix4, 4); reach_v4->mask.s_addr = htonl((entry->reach_metric[cnt].prefix.prefixlen == 32) ? 0xffffffffUL : ~(0xffffffffUL >> entry->reach_metric[cnt].prefix.prefixlen)); isis_dgram_ptr += sizeof(struct ipv4_reachability); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct ipv4_reachability), req, filename)) return; } tlvs_cnt++; } if (entry->reach6_metric_num) { int prefix_len = 0; reach_v6_hdr = (struct idrp_info *) isis_dgram_ptr; reach_v6_hdr->value = IPV6_REACHABILITY; reach_v6_hdr->len = 0; isis_dgram_ptr += sizeof(struct idrp_info); if (igp_daemon_map_handle_len(&rem_len, sizeof(struct idrp_info), req, filename)) return; for (cnt = 0; cnt < entry->reach6_metric_num; cnt++) { reach_v6 = (struct ipv6_reachability *) isis_dgram_ptr; reach_v6->metric = htonl(entry->reach6_metric[cnt].metric); reach_v6->control_info = 0; reach_v6->prefix_len = entry->reach6_metric[cnt].prefix.prefixlen; prefix_len = reach_v6->prefix_len / 8; memcpy(&reach_v6->prefix, &entry->reach6_metric[cnt].prefix.u.prefix6, prefix_len); reach_v6_hdr->len += 6 + prefix_len; isis_dgram_ptr += 6 + prefix_len; if (igp_daemon_map_handle_len(&rem_len, 6 + prefix_len, req, filename)) return; } pdu_len += reach_v6_hdr->len; tlvs_cnt++; } /* wrapping up: fix lsp length */ pdu_len += sizeof(struct isis_fixed_hdr)+ISIS_LSP_HDR_LEN+(ISIS_TLV_HDR_LEN*tlvs_cnt); lsp_hdr->pdu_len = htons(pdu_len); if (config.debug && config.igp_daemon_map_msglog) { memset(&phdr, 0, sizeof(phdr)); phdr.len = phdr.caplen = sizeof(isis_dgram)-rem_len; pcap_dump((u_char *) idmm_fd, &phdr, isis_dgram); } } else { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): required key missing at line %d in map '%s'. Required keys are:\n", config.name, req->line_num, filename); Log(LOG_ERR, "ERROR ( %s/core/ISIS ): node, area_id, adj_metric or reach_metric or reach6_metric.\n", config.name); } } else Log(LOG_ERR, "ERROR ( %s ): Invalid pointer to entry. ", filename); } void igp_daemon_map_initialize(char *filename, struct plugin_requests *req) { pcap_t *p; if (config.debug && config.igp_daemon_map_msglog) { p = pcap_open_dead(DLT_CHDLC, RECEIVE_LSP_BUFFER_SIZE+sizeof(struct chdlc_header)+sizeof(struct isis_fixed_hdr)); if ((idmm_fd = pcap_dump_open(p, config.igp_daemon_map_msglog)) == NULL) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Can not open igp_daemon_map_msglog '%s' (%s).\n", config.name, config.igp_daemon_map_msglog, pcap_geterr(p)); exit_gracefully(1); } } } void igp_daemon_map_finalize(char *filename, struct plugin_requests *req) { if (config.debug && config.igp_daemon_map_msglog) pcap_dump_close(idmm_fd); } int igp_daemon_map_handle_len(int *rem_len, int len, struct plugin_requests *req, char *filename) { *rem_len -= len; if (*rem_len < 0) { Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Resulting LSP longer than %u. Ignoring line %d in map '%s'.\n", config.name, RECEIVE_LSP_BUFFER_SIZE, req->line_num, filename); return TRUE; } return FALSE; } int igp_daemon_map_handle_lsp_id(u_char *lsp_id, struct host_addr *addr) { u_char sysid[ISIS_SYS_ID_LEN]; int idx; memset(sysid, 0, sizeof(sysid)); memcpy(sysid, &addr->address.ipv4, 4); for (idx = 0; idx < MAX_IGP_MAP_NODES && sysid_fragment_table[idx].valid; idx++) { if (!memcmp(sysid, sysid_fragment_table[idx].sysid, ISIS_SYS_ID_LEN)) { /* check if maximum segment number reached */ if (sysid_fragment_table[idx].frag_num == 255) { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Maximum segment number (255) reached for sysid: '%s'\n", config.name, sysid); memset(lsp_id, 0, ISIS_SYS_ID_LEN + 2); return TRUE; } else { memcpy(lsp_id, sysid_fragment_table[idx].sysid, 4); memcpy(lsp_id + ISIS_SYS_ID_LEN + 1, &sysid_fragment_table[idx].frag_num, 1); sysid_fragment_table[idx].frag_num++; return FALSE; } } } /* sys id not found: let's insert it */ if (idx < MAX_IGP_MAP_NODES) { memcpy(sysid_fragment_table[idx].sysid, sysid, ISIS_SYS_ID_LEN); sysid_fragment_table[idx].frag_num = 0; sysid_fragment_table[idx].valid = TRUE; memcpy(lsp_id, sysid_fragment_table[idx].sysid, 4); memcpy(lsp_id + ISIS_SYS_ID_LEN + 1, &sysid_fragment_table[idx].frag_num, 1); sysid_fragment_table[idx].frag_num++; return FALSE; } else { Log(LOG_WARNING, "WARN ( %s/core/ISIS ): Maximum number of nodes (%u) reached in igp_daemon_map\n", config.name, MAX_IGP_MAP_NODES); memset(lsp_id, 0, ISIS_SYS_ID_LEN + 2); return TRUE; } } pmacct-1.7.8/src/isis/Makefile.am0000644000175000017500000000143314354105275015605 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmisis.la libpmisis_la_SOURCES = isis.c checksum.c dict.c table.c prefix.c \ sockunion.c hash.c stream.c thread.c \ isis_circuit.c isis_events.c isis_route.c isis_tlv.c \ isis_csm.c isis_flags.c isis_misc.c isisd.c isis_adjacency.c \ isis_dynhn.c isis_spf.c iso_checksum.c isis_lsp.c isis_pdu.c \ checksum.h dict.h hash.h isis_adjacency.h isis_circuit.h \ isis_common.h isis_constants.h isis_csm.h isis-data.h isisd.h \ isis_dynhn.h isis_events.h isis_flags.h isis.h isis_ll.h \ isis_lsp.h isis_misc.h isis_network.h isis_pdu.h isis_route.h \ isis_spf.h isis_tlv.h iso_checksum.h iso.h \ prefix.h sockunion.h stream.h table.h thread.h isis-globals.c libpmisis_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) -Wno-error=pointer-sign pmacct-1.7.8/src/isis/iso.h0000644000175000017500000001615114354105275014517 0ustar paolopaolo/* $NetBSD: iso.h,v 1.13 2000/07/28 12:13:34 kleink Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)iso.h 8.1 (Berkeley) 6/10/93 */ /*********************************************************** Copyright IBM Corporation 1987 All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of IBM not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison */ #ifndef _NETISO_ISO_H_ #define _NETISO_ISO_H_ #if 0 #include #endif #if 0 #ifndef sa_family_t typedef __sa_family_t sa_family_t; #define sa_family_t __sa_family_t #endif #endif /* * Return true if this is a multicast address * This assumes that the bit transmission is lsb first. This * assumption is valid for 802.3 but not 802.5. There is a * kludge to get around this for 802.5 -- see if_lan.c * where subnetwork header is setup. */ #define IS_MULTICAST(snpa)\ ((snpa)[0] & 0x01) /* * Protocols */ #define ISOPROTO_TCP 6 /* IETF experiment */ #define ISOPROTO_UDP 17 /* IETF experiment */ #define ISOPROTO_TP0 25 /* connection oriented transport protocol */ #define ISOPROTO_TP1 26 /* not implemented */ #define ISOPROTO_TP2 27 /* not implemented */ #define ISOPROTO_TP3 28 /* not implemented */ #define ISOPROTO_TP4 29 /* connection oriented transport protocol */ #define ISOPROTO_TP ISOPROTO_TP4 /* tp-4 with negotiation */ #define ISOPROTO_CLTP 30 /* connectionless transport (not yet impl.) */ #define ISOPROTO_CLNP 31 /* connectionless internetworking protocol */ #define ISOPROTO_X25 32 /* cons */ #define ISOPROTO_INACT_NL 33 /* inactive network layer! */ #define ISOPROTO_ESIS 34 /* ES-IS protocol */ #define ISOPROTO_INTRAISIS 35 /* IS-IS protocol */ #define ISOPROTO_IDRP 36 /* Interdomain Routing Protocol */ #define ISOPROTO_RAW 255 /* raw clnp */ #define ISOPROTO_MAX 256 #define ISO_PORT_RESERVED 1024 #define ISO_PORT_USERRESERVED 5000 /* * Port/socket numbers: standard network functions * NOT PRESENTLY USED */ #define ISO_PORT_MAINT 501 #define ISO_PORT_ECHO 507 #define ISO_PORT_DISCARD 509 #define ISO_PORT_SYSTAT 511 #define ISO_PORT_NETSTAT 515 /* * Port/socket numbers: non-standard application functions */ #define ISO_PORT_LOGIN 513 /* * Port/socket numbers: public use */ #define ISO_PORT_PUBLIC 1024 /* high bit set --> public */ /* * Network layer protocol identifiers */ #define ISO8473_CLNP 0x81 #define ISO9542_ESIS 0x82 #define ISO9542X25_ESIS 0x8a #define ISO10589_ISIS 0x83 #define ISO8878A_CONS 0x84 #define ISO10747_IDRP 0x85 #ifndef IN_CLASSA_NET #include #endif /* IN_CLASSA_NET */ /* * The following looks like a sockaddr to facilitate using tree lookup * routines */ struct iso_addr { u_char isoa_len; /* length (in bytes) */ char isoa_genaddr[20]; /* general opaque address */ }; struct sockaddr_iso { u_char siso_len; /* length */ sa_family_t siso_family; /* family */ u_char siso_plen; /* presentation selector length */ u_char siso_slen; /* session selector length */ u_char siso_tlen; /* transport selector length */ struct iso_addr siso_addr; /* network address */ u_char siso_pad[6]; /* space for gosip v2 sels */ /* makes struct 32 bytes long */ }; #define siso_nlen siso_addr.isoa_len #define siso_data siso_addr.isoa_genaddr #define TSEL(s) ((caddr_t)((s)->siso_data + (s)->siso_nlen)) #define SAME_ISOADDR(a, b) \ (bcmp((a)->siso_data, (b)->siso_data, (unsigned)(a)->siso_nlen)==0) #define SAME_ISOIFADDR(a, b) (bcmp((a)->siso_data, (b)->siso_data, \ (unsigned)((b)->siso_nlen - (b)->siso_tlen)) == 0) /* * The following are specific values for siso->siso_data[0], * otherwise known as the AFI: */ #define AFI_37 0x37 /* bcd of "37" */ #define AFI_OSINET 0x47 /* bcd of "47" */ #define AFI_RFC986 0x47 /* bcd of "47" */ #define AFI_SNA 0x00 /* SubNetwork Address; invalid really... */ #ifdef _KERNEL extern struct domain isodomain; extern struct protosw isosw[]; #define satosiso(sa) ((struct sockaddr_iso *)(sa)) #define sisotosa(siso) ((struct sockaddr *)(siso)) #else /* user utilities definitions from the iso library */ #ifdef SOLARIS #define __P(x) x #define __BEGIN_DECLS #define __END_DECLS #endif #ifdef __cplusplus extern "C" { struct iso_addr *iso_addr __P((const char *)); char *iso_ntoa __P((const struct iso_addr *)); /* THESE DON'T EXIST YET */ struct hostent *iso_gethostbyname __P((const char *)); struct hostent *iso_gethostbyaddr __P((const char *, int, int)); } #endif #endif /* _KERNEL */ #endif /* _NETISO_ISO_H_ */ pmacct-1.7.8/src/isis/iso_checksum.c0000644000175000017500000000373014354105275016373 0ustar paolopaolo/* * IS-IS Rout(e)ing protocol - iso_checksum.c * ISO checksum related routines * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "isis.h" #include "checksum.h" #include "iso_checksum.h" /* * Calculations of the OSI checksum. * ISO/IEC 8473 defines the sum as * * L * sum a (mod 255) = 0 * 1 i * * L * sum (L-i+1)a (mod 255) = 0 * 1 i * */ /* * Verifies that the checksum is correct. * Return 0 on correct and 1 on invalid checksum. * Based on Annex C.4 of ISO/IEC 8473 */ int iso_csum_verify (u_char * buffer, int len, uint16_t * csum) { u_int16_t checksum; u_int32_t c0; u_int32_t c1; c0 = *csum & 0xff00; c1 = *csum & 0x00ff; /* * If both are zero return correct */ if (c0 == 0 && c1 == 0) return 0; /* * If either, but not both are zero return incorrect */ if (c0 == 0 || c1 == 0) return 1; /* Offset of checksum from the start of the buffer */ int offset = (u_char *) csum - buffer; checksum = fletcher_checksum(buffer, len, offset); if (checksum == *csum) return 0; return 1; } pmacct-1.7.8/src/isis/isis_ll.h0000644000175000017500000000203614354105275015360 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ISIS_LL_H_ #define _ISIS_LL_H_ /* defines */ /* structures */ /* prototypes */ extern void isis_sll_handler(const struct pcap_pkthdr *, register struct packet_ptrs *); /* global variables */ #endif pmacct-1.7.8/src/isis/checksum.c0000644000175000017500000000523114354105275015517 0ustar paolopaolo/* * Checksum routine for Internet Protocol family headers (C Version). * * Refer to "Computing the Internet Checksum" by R. Braden, D. Borman and * C. Partridge, Computer Communication Review, Vol. 19, No. 2, April 1989, * pp. 86-101, for additional details on computing this checksum. */ #include "pmacct.h" #include "isis.h" #include "checksum.h" int /* return checksum in low-order 16 bits */ in_cksum(void *parg, int nbytes) { u_short *ptr = parg; register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return(answer); } /* Fletcher Checksum -- Refer to RFC1008. */ #define MODX 4102 /* 5802 should be fine */ /* To be consistent, offset is 0-based index, rather than the 1-based index required in the specification ISO 8473, Annex C.1 */ u_int16_t fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset) { u_int8_t *p; int x, y, c0, c1; u_int16_t checksum; u_int16_t *csum; size_t partial_len, i, left = len; checksum = 0; assert (offset < len); /* * Zero the csum in the packet. */ csum = (u_int16_t *) (buffer + offset); *(csum) = 0; p = buffer; c0 = 0; c1 = 0; while (left != 0) { partial_len = MIN(left, MODX); for (i = 0; i < partial_len; i++) { c0 = c0 + *(p++); c1 += c0; } c0 = c0 % 255; c1 = c1 % 255; left -= partial_len; } /* The cast is important, to ensure the mod is taken as a signed value. */ x = (int)((len - offset - 1) * c0 - c1) % 255; if (x <= 0) x += 255; y = 510 - c0 - x; if (y > 255) y -= 255; /* * Now we write this to the packet. * We could skip this step too, since the checksum returned would * be stored into the checksum field by the caller. */ buffer[offset] = x; buffer[offset + 1] = y; /* Take care of the endian issue */ checksum = htons((x << 8) | (y & 0xFF)); return checksum; } pmacct-1.7.8/src/isis/dict.c0000644000175000017500000007114014354105275014642 0ustar paolopaolo/* * Dictionary Abstract Data Type * Copyright (C) 1997 Kaz Kylheku * * Free Software License: * * All rights are reserved by the author, with the following exceptions: * Permission is granted to freely reproduce and distribute this software, * possibly in exchange for a fee, provided that this copyright notice appears * intact. Permission is also granted to adapt this software to produce * derivative works, as long as the modified versions carry this copyright * notice and additional notices stating that the work has been modified. * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. */ #include "pmacct.h" #include "isis.h" #define DICT_IMPLEMENTATION #include "dict.h" /* * These macros provide short convenient names for structure members, * which are embellished with dict_ prefixes so that they are * properly confined to the documented namespace. It's legal for a * program which uses dict to define, for instance, a macro called ``parent''. * Such a macro would interfere with the dnode_t struct definition. * In general, highly portable and reusable C modules which expose their * structures need to confine structure member names to well-defined spaces. * The resulting identifiers aren't necessarily convenient to use, nor * readable, in the implementation, however! */ #define left dict_left #define right dict_right #define parent dict_parent #define color dict_color #define key dict_key #define data dict_data #define nilnode dict_nilnode #define nodecount dict_nodecount #define maxcount dict_maxcount #define compare dict_compare #define allocnode dict_allocnode #define freenode dict_freenode #define context dict_context #define dupes dict_dupes #define dictptr dict_dictptr #define dict_root(D) ((D)->nilnode.left) #define dict_nil(D) (&(D)->nilnode) #define DICT_DEPTH_MAX 64 static dnode_t *dnode_alloc(void *context); static void dnode_free(dnode_t *node, void *context); /* * Perform a ``left rotation'' adjustment on the tree. The given node P and * its right child C are rearranged so that the P instead becomes the left * child of C. The left subtree of C is inherited as the new right subtree * for P. The ordering of the keys within the tree is thus preserved. */ static void rotate_left(dnode_t *upper) { dnode_t *lower, *lowleft, *upparent; lower = upper->right; upper->right = lowleft = lower->left; lowleft->parent = upper; lower->parent = upparent = upper->parent; /* don't need to check for root node here because root->parent is the sentinel nil node, and root->parent->left points back to root */ if (upper == upparent->left) { upparent->left = lower; } else { assert (upper == upparent->right); upparent->right = lower; } lower->left = upper; upper->parent = lower; } /* * This operation is the ``mirror'' image of rotate_left. It is * the same procedure, but with left and right interchanged. */ static void rotate_right(dnode_t *upper) { dnode_t *lower, *lowright, *upparent; lower = upper->left; upper->left = lowright = lower->right; lowright->parent = upper; lower->parent = upparent = upper->parent; if (upper == upparent->right) { upparent->right = lower; } else { assert (upper == upparent->left); upparent->left = lower; } lower->right = upper; upper->parent = lower; } /* * Do a postorder traversal of the tree rooted at the specified * node and free everything under it. Used by dict_free(). */ static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) { if (node == nil) return; free_nodes(dict, node->left, nil); free_nodes(dict, node->right, nil); dict->freenode(node, dict->context); } /* * This procedure performs a verification that the given subtree is a binary * search tree. It performs an inorder traversal of the tree using the * dict_next() successor function, verifying that the key of each node is * strictly lower than that of its successor, if duplicates are not allowed, * or lower or equal if duplicates are allowed. This function is used for * debugging purposes. */ static int verify_bintree(dict_t *dict) { dnode_t *first, *next; first = dict_first(dict); if (dict->dupes) { while (first && (next = dict_next(dict, first))) { if (dict->compare(first->key, next->key) > 0) return 0; first = next; } } else { while (first && (next = dict_next(dict, first))) { if (dict->compare(first->key, next->key) >= 0) return 0; first = next; } } return 1; } /* * This function recursively verifies that the given binary subtree satisfies * three of the red black properties. It checks that every red node has only * black children. It makes sure that each node is either red or black. And it * checks that every path has the same count of black nodes from root to leaf. * It returns the blackheight of the given subtree; this allows blackheights to * be computed recursively and compared for left and right siblings for * mismatches. It does not check for every nil node being black, because there * is only one sentinel nil node. The return value of this function is the * black height of the subtree rooted at the node ``root'', or zero if the * subtree is not red-black. */ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) { unsigned height_left, height_right; if (root != nil) { height_left = verify_redblack(nil, root->left); height_right = verify_redblack(nil, root->right); if (height_left == 0 || height_right == 0) return 0; if (height_left != height_right) return 0; if (root->color == dnode_red) { if (root->left->color != dnode_black) return 0; if (root->right->color != dnode_black) return 0; return height_left; } if (root->color != dnode_black) return 0; return height_left + 1; } return 1; } /* * Compute the actual count of nodes by traversing the tree and * return it. This could be compared against the stored count to * detect a mismatch. */ static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) { if (root == nil) return 0; else return 1 + verify_node_count(nil, root->left) + verify_node_count(nil, root->right); } /* * Verify that the tree contains the given node. This is done by * traversing all of the nodes and comparing their pointers to the * given pointer. Returns 1 if the node is found, otherwise * returns zero. It is intended for debugging purposes. */ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) { if (root != nil) { return root == node || verify_dict_has_node(nil, root->left, node) || verify_dict_has_node(nil, root->right, node); } return 0; } /* * Dynamically allocate and initialize a dictionary object. */ dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp) { dict_t *new = calloc(1, sizeof *new); if (new) { new->compare = comp; new->allocnode = dnode_alloc; new->freenode = dnode_free; new->context = NULL; new->nodecount = 0; new->maxcount = maxcount; new->nilnode.left = &new->nilnode; new->nilnode.right = &new->nilnode; new->nilnode.parent = &new->nilnode; new->nilnode.color = dnode_black; new->dupes = 0; } return new; } /* * Select a different set of node allocator routines. */ void dict_set_allocator(dict_t *dict, dnode_alloc_t al, dnode_free_t fr, void *context) { assert (dict_count(dict) == 0); assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); dict->allocnode = al ? al : dnode_alloc; dict->freenode = fr ? fr : dnode_free; dict->context = context; } /* * Free a dynamically allocated dictionary object. Removing the nodes * from the tree before deleting it is required. */ void dict_destroy(dict_t *dict) { assert (dict_isempty(dict)); free(dict); } /* * Free all the nodes in the dictionary by using the dictionary's * installed free routine. The dictionary is emptied. */ void dict_free_nodes(dict_t *dict) { dnode_t *nil = dict_nil(dict), *root = dict_root(dict); free_nodes(dict, root, nil); dict->nodecount = 0; dict->nilnode.left = &dict->nilnode; dict->nilnode.right = &dict->nilnode; } /* * Obsolescent function, equivalent to dict_free_nodes */ void dict_free(dict_t *dict) { dict_free_nodes(dict); } /* * Initialize a user-supplied dictionary object. */ dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) { dict->compare = comp; dict->allocnode = dnode_alloc; dict->freenode = dnode_free; dict->context = NULL; dict->nodecount = 0; dict->maxcount = maxcount; dict->nilnode.left = &dict->nilnode; dict->nilnode.right = &dict->nilnode; dict->nilnode.parent = &dict->nilnode; dict->nilnode.color = dnode_black; dict->dupes = 0; return dict; } /* * Initialize a dictionary in the likeness of another dictionary */ void dict_init_like(dict_t *dict, const dict_t *template) { dict->compare = template->compare; dict->allocnode = template->allocnode; dict->freenode = template->freenode; dict->context = template->context; dict->nodecount = 0; dict->maxcount = template->maxcount; dict->nilnode.left = &dict->nilnode; dict->nilnode.right = &dict->nilnode; dict->nilnode.parent = &dict->nilnode; dict->nilnode.color = dnode_black; dict->dupes = template->dupes; assert (dict_similar(dict, template)); } /* * Remove all nodes from the dictionary (without freeing them in any way). */ static void dict_clear(dict_t *dict) { dict->nodecount = 0; dict->nilnode.left = &dict->nilnode; dict->nilnode.right = &dict->nilnode; dict->nilnode.parent = &dict->nilnode; assert (dict->nilnode.color == dnode_black); } /* * Verify the integrity of the dictionary structure. This is provided for * debugging purposes, and should be placed in assert statements. Just because * this function succeeds doesn't mean that the tree is not corrupt. Certain * corruptions in the tree may simply cause undefined behavior. */ int dict_verify(dict_t *dict) { dnode_t *nil = dict_nil(dict), *root = dict_root(dict); /* check that the sentinel node and root node are black */ if (root->color != dnode_black) return 0; if (nil->color != dnode_black) return 0; if (nil->right != nil) return 0; /* nil->left is the root node; check that its parent pointer is nil */ if (nil->left->parent != nil) return 0; /* perform a weak test that the tree is a binary search tree */ if (!verify_bintree(dict)) return 0; /* verify that the tree is a red-black tree */ if (!verify_redblack(nil, root)) return 0; if (verify_node_count(nil, root) != dict_count(dict)) return 0; return 1; } /* * Determine whether two dictionaries are similar: have the same comparison and * allocator functions, and same status as to whether duplicates are allowed. */ int dict_similar(const dict_t *left, const dict_t *right) { if (left->compare != right->compare) return 0; if (left->allocnode != right->allocnode) return 0; if (left->freenode != right->freenode) return 0; if (left->context != right->context) return 0; if (left->dupes != right->dupes) return 0; return 1; } /* * Locate a node in the dictionary having the given key. * If the node is not found, a null a pointer is returned (rather than * a pointer that dictionary's nil sentinel node), otherwise a pointer to the * located node is returned. */ dnode_t *dict_lookup(dict_t *dict, const void *key) { dnode_t *root = dict_root(dict); dnode_t *nil = dict_nil(dict); dnode_t *saved; int result; /* simple binary search adapted for trees that contain duplicate keys */ while (root != nil) { result = dict->compare(key, root->key); if (result < 0) root = root->left; else if (result > 0) root = root->right; else { if (!dict->dupes) { /* no duplicates, return match */ return root; } else { /* could be dupes, find leftmost one */ do { saved = root; root = root->left; while (root != nil && dict->compare(key, root->key)) root = root->right; } while (root != nil); return saved; } } } return NULL; } /* * Look for the node corresponding to the lowest key that is equal to or * greater than the given key. If there is no such node, return null. */ dnode_t *dict_lower_bound(dict_t *dict, const void *key) { dnode_t *root = dict_root(dict); dnode_t *nil = dict_nil(dict); dnode_t *tentative = 0; while (root != nil) { int result = dict->compare(key, root->key); if (result > 0) { root = root->right; } else if (result < 0) { tentative = root; root = root->left; } else { if (!dict->dupes) { return root; } else { tentative = root; root = root->left; } } } return tentative; } /* * Look for the node corresponding to the greatest key that is equal to or * lower than the given key. If there is no such node, return null. */ dnode_t *dict_upper_bound(dict_t *dict, const void *key) { dnode_t *root = dict_root(dict); dnode_t *nil = dict_nil(dict); dnode_t *tentative = 0; while (root != nil) { int result = dict->compare(key, root->key); if (result < 0) { root = root->left; } else if (result > 0) { tentative = root; root = root->right; } else { if (!dict->dupes) { return root; } else { tentative = root; root = root->right; } } } return tentative; } /* * Insert a node into the dictionary. The node should have been * initialized with a data field. All other fields are ignored. * The behavior is undefined if the user attempts to insert into * a dictionary that is already full (for which the dict_isfull() * function returns true). */ void dict_insert(dict_t *dict, dnode_t *node, const void *key) { dnode_t *where = dict_root(dict), *nil = dict_nil(dict); dnode_t *parent = nil, *uncle, *grandpa; int result = -1; node->key = key; assert (!dict_isfull(dict)); assert (!dict_contains(dict, node)); assert (!dnode_is_in_a_dict(node)); /* basic binary tree insert */ while (where != nil) { parent = where; result = dict->compare(key, where->key); /* trap attempts at duplicate key insertion unless it's explicitly allowed */ assert (dict->dupes || result != 0); if (result < 0) where = where->left; else where = where->right; } assert (where == nil); if (result < 0) parent->left = node; else parent->right = node; node->parent = parent; node->left = nil; node->right = nil; dict->nodecount++; /* red black adjustments */ node->color = dnode_red; while (parent->color == dnode_red) { grandpa = parent->parent; if (parent == grandpa->left) { uncle = grandpa->right; if (uncle->color == dnode_red) { /* red parent, red uncle */ parent->color = dnode_black; uncle->color = dnode_black; grandpa->color = dnode_red; node = grandpa; parent = grandpa->parent; } else { /* red parent, black uncle */ if (node == parent->right) { rotate_left(parent); parent = node; assert (grandpa == parent->parent); /* rotation between parent and child preserves grandpa */ } parent->color = dnode_black; grandpa->color = dnode_red; rotate_right(grandpa); break; } } else { /* symmetric cases: parent == parent->parent->right */ uncle = grandpa->left; if (uncle->color == dnode_red) { parent->color = dnode_black; uncle->color = dnode_black; grandpa->color = dnode_red; node = grandpa; parent = grandpa->parent; } else { if (node == parent->left) { rotate_right(parent); parent = node; assert (grandpa == parent->parent); } parent->color = dnode_black; grandpa->color = dnode_red; rotate_left(grandpa); break; } } } dict_root(dict)->color = dnode_black; assert (dict_verify(dict)); } /* * Delete the given node from the dictionary. If the given node does not belong * to the given dictionary, undefined behavior results. A pointer to the * deleted node is returned. */ dnode_t *dict_delete(dict_t *dict, dnode_t *delete) { dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; /* basic deletion */ assert (!dict_isempty(dict)); assert (dict_contains(dict, delete)); /* * If the node being deleted has two children, then we replace it with its * successor (i.e. the leftmost node in the right subtree.) By doing this, * we avoid the traditional algorithm under which the successor's key and * value *only* move to the deleted node and the successor is spliced out * from the tree. We cannot use this approach because the user may hold * pointers to the successor, or nodes may be inextricably tied to some * other structures by way of embedding, etc. So we must splice out the * node we are given, not some other node, and must not move contents from * one node to another behind the user's back. */ if (delete->left != nil && delete->right != nil) { dnode_t *next = dict_next(dict, delete); dnode_t *nextparent = next->parent; dnode_color_t nextcolor = next->color; assert (next != nil); assert (next->parent != nil); assert (next->left == nil); /* * First, splice out the successor from the tree completely, by * moving up its right child into its place. */ child = next->right; child->parent = nextparent; if (nextparent->left == next) { nextparent->left = child; } else { assert (nextparent->right == next); nextparent->right = child; } /* * Now that the successor has been extricated from the tree, install it * in place of the node that we want deleted. */ next->parent = delparent; next->left = delete->left; next->right = delete->right; next->left->parent = next; next->right->parent = next; next->color = delete->color; delete->color = nextcolor; if (delparent->left == delete) { delparent->left = next; } else { assert (delparent->right == delete); delparent->right = next; } } else { assert (delete != nil); assert (delete->left == nil || delete->right == nil); child = (delete->left != nil) ? delete->left : delete->right; child->parent = delparent = delete->parent; if (delete == delparent->left) { delparent->left = child; } else { assert (delete == delparent->right); delparent->right = child; } } delete->parent = NULL; delete->right = NULL; delete->left = NULL; dict->nodecount--; assert (verify_bintree(dict)); /* red-black adjustments */ if (delete->color == dnode_black) { dnode_t *parent, *sister; dict_root(dict)->color = dnode_red; while (child->color == dnode_black) { parent = child->parent; if (child == parent->left) { sister = parent->right; assert (sister != nil); if (sister->color == dnode_red) { sister->color = dnode_black; parent->color = dnode_red; rotate_left(parent); sister = parent->right; assert (sister != nil); } if (sister->left->color == dnode_black && sister->right->color == dnode_black) { sister->color = dnode_red; child = parent; } else { if (sister->right->color == dnode_black) { assert (sister->left->color == dnode_red); sister->left->color = dnode_black; sister->color = dnode_red; rotate_right(sister); sister = parent->right; assert (sister != nil); } sister->color = parent->color; sister->right->color = dnode_black; parent->color = dnode_black; rotate_left(parent); break; } } else { /* symmetric case: child == child->parent->right */ assert (child == parent->right); sister = parent->left; assert (sister != nil); if (sister->color == dnode_red) { sister->color = dnode_black; parent->color = dnode_red; rotate_right(parent); sister = parent->left; assert (sister != nil); } if (sister->right->color == dnode_black && sister->left->color == dnode_black) { sister->color = dnode_red; child = parent; } else { if (sister->left->color == dnode_black) { assert (sister->right->color == dnode_red); sister->right->color = dnode_black; sister->color = dnode_red; rotate_left(sister); sister = parent->left; assert (sister != nil); } sister->color = parent->color; sister->left->color = dnode_black; parent->color = dnode_black; rotate_right(parent); break; } } } child->color = dnode_black; dict_root(dict)->color = dnode_black; } assert (dict_verify(dict)); return delete; } /* * Allocate a node using the dictionary's allocator routine, give it * the data item. */ int dict_alloc_insert(dict_t *dict, const void *key, void *data) { dnode_t *node = dict->allocnode(dict->context); if (node) { dnode_init(node, data); dict_insert(dict, node, key); return 1; } return 0; } void dict_delete_free(dict_t *dict, dnode_t *node) { dict_delete(dict, node); dict->freenode(node, dict->context); } /* * Return the node with the lowest (leftmost) key. If the dictionary is empty * (that is, dict_isempty(dict) returns 1) a null pointer is returned. */ dnode_t *dict_first(dict_t *dict) { dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; if (root != nil) while ((left = root->left) != nil) root = left; return (root == nil) ? NULL : root; } /* * Return the node with the highest (rightmost) key. If the dictionary is empty * (that is, dict_isempty(dict) returns 1) a null pointer is returned. */ dnode_t *dict_last(dict_t *dict) { dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; if (root != nil) while ((right = root->right) != nil) root = right; return (root == nil) ? NULL : root; } /* * Return the given node's successor node---the node which has the * next key in the the left to right ordering. If the node has * no successor, a null pointer is returned rather than a pointer to * the nil node. */ dnode_t *dict_next(dict_t *dict, dnode_t *curr) { dnode_t *nil = dict_nil(dict), *parent, *left; if (curr->right != nil) { curr = curr->right; while ((left = curr->left) != nil) curr = left; return curr; } parent = curr->parent; while (parent != nil && curr == parent->right) { curr = parent; parent = curr->parent; } return (parent == nil) ? NULL : parent; } /* * Return the given node's predecessor, in the key order. * The nil sentinel node is returned if there is no predecessor. */ dnode_t *dict_prev(dict_t *dict, dnode_t *curr) { dnode_t *nil = dict_nil(dict), *parent, *right; if (curr->left != nil) { curr = curr->left; while ((right = curr->right) != nil) curr = right; return curr; } parent = curr->parent; while (parent != nil && curr == parent->left) { curr = parent; parent = curr->parent; } return (parent == nil) ? NULL : parent; } void dict_allow_dupes(dict_t *dict) { dict->dupes = 1; } #undef dict_count #undef dict_isempty #undef dict_isfull #undef dnode_get #undef dnode_put #undef dnode_getkey dictcount_t dict_count(dict_t *dict) { return dict->nodecount; } int dict_isempty(dict_t *dict) { return dict->nodecount == 0; } int dict_isfull(dict_t *dict) { return dict->nodecount == dict->maxcount; } int dict_contains(dict_t *dict, dnode_t *node) { return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); } static dnode_t *dnode_alloc(void *context) { return calloc(1, sizeof *dnode_alloc(NULL)); } static void dnode_free(dnode_t *node, void *context) { free(node); } dnode_t *dnode_create(void *data) { dnode_t *new = calloc(1, sizeof *new); if (new) { new->data = data; new->parent = NULL; new->left = NULL; new->right = NULL; } return new; } dnode_t *dnode_init(dnode_t *dnode, void *data) { dnode->data = data; dnode->parent = NULL; dnode->left = NULL; dnode->right = NULL; return dnode; } void dnode_destroy(dnode_t *dnode) { assert (!dnode_is_in_a_dict(dnode)); free(dnode); } void *dnode_get(dnode_t *dnode) { return dnode->data; } const void *dnode_getkey(dnode_t *dnode) { return dnode->key; } void dnode_put(dnode_t *dnode, void *data) { dnode->data = data; } int dnode_is_in_a_dict(dnode_t *dnode) { return (dnode->parent && dnode->left && dnode->right); } void dict_process(dict_t *dict, void *context, dnode_process_t function) { dnode_t *node = dict_first(dict), *next; while (node != NULL) { /* check for callback function deleting */ /* the next node from under us */ assert (dict_contains(dict, node)); next = dict_next(dict, node); function(dict, node, context); node = next; } } static void load_begin_internal(dict_load_t *load, dict_t *dict) { load->dictptr = dict; load->nilnode.left = &load->nilnode; load->nilnode.right = &load->nilnode; } void dict_load_begin(dict_load_t *load, dict_t *dict) { assert (dict_isempty(dict)); load_begin_internal(load, dict); } void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key) { dict_t *dict = load->dictptr; dnode_t *nil = &load->nilnode; assert (!dnode_is_in_a_dict(newnode)); assert (dict->nodecount < dict->maxcount); #ifndef NDEBUG if (dict->nodecount > 0) { if (dict->dupes) assert (dict->compare(nil->left->key, key) <= 0); else assert (dict->compare(nil->left->key, key) < 0); } #endif newnode->key = key; nil->right->left = newnode; nil->right = newnode; newnode->left = nil; dict->nodecount++; } void dict_load_end(dict_load_t *load) { dict_t *dict = load->dictptr; dnode_t *tree[DICT_DEPTH_MAX] = { 0 }; dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next; dnode_t *complete = 0; dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; dictcount_t botrowcount; unsigned baselevel = 0, level = 0, i; assert (dnode_red == 0 && dnode_black == 1); while (fullcount >= nodecount && fullcount) fullcount >>= 1; botrowcount = nodecount - fullcount; for (curr = loadnil->left; curr != loadnil; curr = next) { next = curr->left; if (complete == NULL && botrowcount-- == 0) { assert (baselevel == 0); assert (level == 0); baselevel = level = 1; complete = tree[0]; if (complete != 0) { tree[0] = 0; complete->right = dictnil; while (tree[level] != 0) { tree[level]->right = complete; complete->parent = tree[level]; complete = tree[level]; tree[level++] = 0; } } } if (complete == NULL) { curr->left = dictnil; curr->right = dictnil; curr->color = level % 2; complete = curr; assert (level == baselevel); while (tree[level] != 0) { tree[level]->right = complete; complete->parent = tree[level]; complete = tree[level]; tree[level++] = 0; } } else { curr->left = complete; curr->color = (level + 1) % 2; complete->parent = curr; tree[level] = curr; complete = 0; level = baselevel; } } if (complete == NULL) complete = dictnil; for (i = 0; i < DICT_DEPTH_MAX; i++) { if (tree[i] != 0) { tree[i]->right = complete; complete->parent = tree[i]; complete = tree[i]; } } dictnil->color = dnode_black; dictnil->right = dictnil; complete->parent = dictnil; complete->color = dnode_black; dict_root(dict) = complete; assert (dict_verify(dict)); } void dict_merge(dict_t *dest, dict_t *source) { dict_load_t load; dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); assert (dict_similar(dest, source)); if (source == dest) return; dest->nodecount = 0; load_begin_internal(&load, dest); for (;;) { if (leftnode != NULL && rightnode != NULL) { if (dest->compare(leftnode->key, rightnode->key) < 0) goto copyleft; else goto copyright; } else if (leftnode != NULL) { goto copyleft; } else if (rightnode != NULL) { goto copyright; } else { assert (leftnode == NULL && rightnode == NULL); break; } copyleft: { dnode_t *next = dict_next(dest, leftnode); #ifndef NDEBUG leftnode->left = NULL; /* suppress assertion in dict_load_next */ #endif dict_load_next(&load, leftnode, leftnode->key); leftnode = next; continue; } copyright: { dnode_t *next = dict_next(source, rightnode); #ifndef NDEBUG rightnode->left = NULL; #endif dict_load_next(&load, rightnode, rightnode->key); rightnode = next; continue; } } dict_clear(source); dict_load_end(&load); } pmacct-1.7.8/src/addr.h0000644000175000017500000001023714354105275013667 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ADDR_H #define ADDR_H /* defines */ #if defined IM_LITTLE_ENDIAN #define IS_IPV4_MULTICAST(a) ((((u_int32_t)(a)) & 0x000000f0) == 0x000000e0) #else #define IS_IPV4_MULTICAST(a) ((((u_int32_t)(a)) & 0xf0000000) == 0xe0000000) #endif #define IS_IPV6_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff) #define IS_MAC_MULTICAST(a) (((const uint8_t *) (a))[0] == 0x01) /* structs */ struct host_addr { u_int8_t family; union { struct in_addr ipv4; struct in6_addr ipv6; } address; }; struct host_mask { u_int8_t family; u_int8_t len; union { u_int32_t m4; u_int8_t m6[16]; } mask; }; /* vars */ static const char __attribute__((unused)) *ip_version_string[] = { "v4", "v6" }; static const u_int8_t __attribute__((unused)) ip_version_num[] = { 4, 6 }; /* prototypes */ extern unsigned int str_to_addr(const char *, struct host_addr *); extern unsigned int addr_to_str(char *, const struct host_addr *); extern unsigned int addr_to_str2(char *, const struct host_addr *, int); extern unsigned int addr_mask_to_str(char *, int, const struct host_addr *, const struct host_mask *); extern unsigned int apply_addr_mask(struct host_addr *, struct host_mask *); extern unsigned int str_to_addr_mask(const char *, struct host_addr *, struct host_mask *); extern unsigned int addr_to_sa(struct sockaddr *, struct host_addr *, u_int16_t); extern unsigned int sa_to_addr(struct sockaddr *, struct host_addr *, u_int16_t *); extern int sa_addr_cmp(struct sockaddr *, struct host_addr *); extern int sa_port_cmp(struct sockaddr *, u_int16_t); extern int host_addr_cmp(struct host_addr *, struct host_addr *); extern int host_addr_cmp2(struct host_addr *, struct host_addr *); extern int host_addr_mask_sa_cmp(struct host_addr *, struct host_mask *, struct sockaddr *); extern int host_addr_mask_cmp(struct host_addr *, struct host_mask *, struct host_addr *); extern unsigned int raw_to_sa(struct sockaddr *, u_char *, u_int16_t port, u_int8_t); extern unsigned int raw_to_addr(struct host_addr *, u_char *, u_int8_t); extern unsigned int sa_to_str(char *, int, const struct sockaddr *, int); extern unsigned int sa_to_port(int *, const struct sockaddr *); extern void *pm_htonl6(void *); extern void *pm_ntohl6(void *); extern u_int64_t pm_htonll(u_int64_t); extern u_int64_t pm_ntohll(u_int64_t); extern int ip6_addr_cmp(void *, void *); extern void ip6_addr_cpy(void *, void *); extern void ip6_addr_32bit_cpy(void *, void *, int, int, int); extern void etheraddr_string(const u_char *, char *); extern int string_etheraddr(const char *, u_char *); extern int is_multicast(struct host_addr *); extern int is_any(struct host_addr *); extern void clean_sin_addr(struct sockaddr *); extern u_int8_t etype_to_af(u_int16_t); extern u_int16_t af_to_etype(u_int8_t); extern const char *af_to_version_str(u_int8_t); extern u_int8_t af_to_version(u_int8_t); extern const char *etype_to_version_str(u_int16_t); extern u_int8_t etype_to_version(u_int16_t); extern u_int32_t addr_hash(struct host_addr *, u_int32_t); extern u_int32_t addr_port_hash(struct host_addr *, u_int16_t, u_int32_t); extern u_int32_t sa_hash(struct sockaddr *, u_int32_t); extern u_int16_t sa_has_family(struct sockaddr *); extern socklen_t sa_len(struct sockaddr_storage *); extern void ipv4_to_ipv4_mapped(struct sockaddr_storage *); extern void ipv4_mapped_to_ipv4(struct sockaddr_storage *); #endif //ADDR_H pmacct-1.7.8/src/ebpf/0000755000175000017500000000000014354105415013511 5ustar paolopaolopmacct-1.7.8/src/ebpf/ebpf_rp_balancer.c0000644000175000017500000001130114354105275017121 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "addr.h" #include "log.h" #include "ebpf_rp_balancer.h" #ifdef WITH_EBPF #include #include #endif /* Functions */ extern int mkdir_multilevel(const char *, int, uid_t, gid_t); #ifdef WITH_EBPF static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { return level <= LIBBPF_DEBUG ? vfprintf(stderr, format, args) : 0; } int attach_ebpf_reuseport_balancer(int fd, char *filename, char *cluster_name, char *aux, u_int32_t key, int is_tcp) { char default_cluster_name[] = "default", path[256]; u_int32_t nonce_key = 0, nonce_value = 12345; int map_fd, prog_fd, nonce_fd, ret; int64_t local_fd = fd; long err = 0; struct bpf_map *map, *nonce_map; uid_t owner = -1; gid_t group = -1; if (!filename) { Log(LOG_ERR, "ERROR: attach_ebpf_reuseport_balancer(): Invalid 'filename' supplied.\n"); return -1; } if (fd < 0) { Log(LOG_ERR, "ERROR ( %s ): attach_ebpf_reuseport_balancer(): Invalid 'fd' supplied.\n", filename); return -1; } if (!filename) { Log(LOG_ERR, "ERROR ( %s ): attach_ebpf_reuseport_balancer(): No 'aux' string supplied.\n", filename); return -1; } // set log libbpf_set_print(libbpf_print_fn); if (cluster_name) { snprintf(path, sizeof(path), "/sys/fs/bpf/pmacct/%s/%s", cluster_name, aux); } else { snprintf(path, sizeof(path), "/sys/fs/bpf/pmacct/%s/%s", default_cluster_name, aux); } ret = mkdir_multilevel(path, 0, owner, group); if (ret) { Log(LOG_ERR, "ERROR ( %s ): attach_ebpf_reuseport_balancer(): mkdir_multilevel() failed.\n", filename); return -1; } struct bpf_object_open_opts opts = {.sz = sizeof(struct bpf_object_open_opts), .pin_root_path = path}; struct bpf_object *obj = bpf_object__open_file(filename, &opts); err = libbpf_get_error(obj); if (err) { Log(LOG_ERR, "ERROR ( %s ): Failed to open BPF elf file\n", filename); return -1; } // nonce map nonce_map = bpf_object__find_map_by_name(obj, "nonce"); assert(nonce_map); // balancing targets map if (!is_tcp) { map = bpf_object__find_map_by_name(obj, "udp_balancing_targets"); } else { map = bpf_object__find_map_by_name(obj, "tcp_balancing_targets"); } assert(map); // Load BPF program to the kernel if (bpf_object__load(obj) != 0) { Log(LOG_ERR, "ERROR ( %s ): Failed loading BPF object into kernel\n", filename); return -1; } struct bpf_program *prog = bpf_object__find_program_by_name(obj, "_selector"); if (!prog) { Log(LOG_ERR, "ERROR ( %s ): Could not find BPF program in BPF object\n", filename); return -1; } prog_fd = bpf_program__fd(prog); assert(prog_fd); nonce_fd = bpf_map__fd(nonce_map); assert(nonce_fd); map_fd = bpf_map__fd(map); assert(map_fd); ret = bpf_map_update_elem(nonce_fd, &nonce_key, &nonce_value, BPF_ANY); if (ret) { Log(LOG_ERR, "ERROR ( %s ): Could not update nonce array (map=%d key=%d fd=%d errno=%d\n", filename, nonce_fd, nonce_key, nonce_value, errno); return -1; } if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &prog_fd, sizeof(prog_fd)) != 0) { Log(LOG_ERR, "ERROR ( %s ): Could not attach BPF prog\n", filename); return -1; } ret = bpf_map_update_elem(map_fd, &key, &local_fd, BPF_ANY); if (ret) { Log(LOG_ERR, "ERROR ( %s ): Could not update reuseport array (map=%d key=%d fd=%ld errno=%d\n", filename, map_fd, key, local_fd, errno); return -1; } else { Log(LOG_DEBUG, "DEBUG ( %s ): Updated reuseport array (map=%d key=%d fd=%ld\n", filename, map_fd, key, local_fd); } return local_fd; } #endif pmacct-1.7.8/src/ebpf/ebpf_rp_balancer.h0000644000175000017500000000205014354105275017127 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EBPF_UDP_H #define EBPF_UDP_H /* includes */ /* defines */ /* prototypes */ #ifdef WITH_EBPF extern int attach_ebpf_reuseport_balancer(int, char *, char *, char *, u_int32_t, int); #endif #endif //EBPF_UDP_H pmacct-1.7.8/src/ebpf/Makefile.in0000644000175000017500000005061214354105415015562 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/ebpf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpmebpf_la_LIBADD = am_libpmebpf_la_OBJECTS = libpmebpf_la-ebpf_rp_balancer.lo libpmebpf_la_OBJECTS = $(am_libpmebpf_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libpmebpf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpmebpf_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpmebpf_la_SOURCES) DIST_SOURCES = $(libpmebpf_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmebpf.la libpmebpf_la_SOURCES = ebpf_rp_balancer.c ebpf_rp_balancer.h libpmebpf_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/ebpf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/ebpf/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpmebpf.la: $(libpmebpf_la_OBJECTS) $(libpmebpf_la_DEPENDENCIES) $(EXTRA_libpmebpf_la_DEPENDENCIES) $(AM_V_CCLD)$(libpmebpf_la_LINK) $(libpmebpf_la_OBJECTS) $(libpmebpf_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libpmebpf_la-ebpf_rp_balancer.lo: ebpf_rp_balancer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmebpf_la_CFLAGS) $(CFLAGS) -MT libpmebpf_la-ebpf_rp_balancer.lo -MD -MP -MF $(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Tpo -c -o libpmebpf_la-ebpf_rp_balancer.lo `test -f 'ebpf_rp_balancer.c' || echo '$(srcdir)/'`ebpf_rp_balancer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Tpo $(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ebpf_rp_balancer.c' object='libpmebpf_la-ebpf_rp_balancer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpmebpf_la_CFLAGS) $(CFLAGS) -c -o libpmebpf_la-ebpf_rp_balancer.lo `test -f 'ebpf_rp_balancer.c' || echo '$(srcdir)/'`ebpf_rp_balancer.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libpmebpf_la-ebpf_rp_balancer.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/ebpf/Makefile.am0000644000175000017500000000025714354105275015555 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libpmebpf.la libpmebpf_la_SOURCES = ebpf_rp_balancer.c ebpf_rp_balancer.h libpmebpf_la_CFLAGS = -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/sfacctd.c0000644000175000017500000032252214354105275014362 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "sflow.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "sfacctd.h" #include "sfv5_module.h" #include "pretag_handlers.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_flow.h" #include "ip_frag.h" #include "net_aggr.h" #include "crc32.h" #include "isis/isis.h" #include "bmp/bmp.h" #if defined WITH_EBPF #include "ebpf/ebpf_rp_balancer.h" #endif #ifdef WITH_RABBITMQ #include "amqp_common.h" #endif #ifdef WITH_KAFKA #include "kafka_common.h" #endif #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #include "ndpi/ndpi_util.h" #endif /* variables to be exported away */ int sfacctd_counter_backend_methods; struct bgp_misc_structs *sf_cnt_misc_db; struct host_addr debug_a; char debug_agent_addr[50]; u_int16_t debug_agent_port; /* Functions */ void usage_daemon(char *prog_name) { printf("%s %s (%s)\n", SFACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); printf("Usage: %s [ -D | -d ] [ -L IP address ] [ -l port ] [ -c primitive [ , ... ] ] [ -P plugin [ , ... ] ]\n", prog_name); printf(" %s [ -f config_file ]\n", prog_name); printf(" %s [ -h ]\n", prog_name); printf("\nGeneral options:\n"); printf(" -h \tShow this page\n"); printf(" -V \tShow version and compile-time options and exit\n"); printf(" -L \tBind to the specified IP address\n"); printf(" -l \tListen on the specified UDP port\n"); printf(" -f \tLoad configuration from the specified file\n"); printf(" -a \tPrint list of supported aggregation primitives\n"); printf(" -c \tAggregation method, see full list of primitives with -a (DEFAULT: src_host)\n"); printf(" -D \tDaemonize\n"); printf(" -n \tPath to a file containing networks and/or ASNs definitions\n"); printf(" -t \tPath to a file containing ports definitions\n"); printf(" -P \t[ memory | print | mysql | pgsql | sqlite3 | amqp | kafka | tee ] \n\tActivate plugin\n"); printf(" -d \tEnable debug\n"); printf(" -S \t[ auth | mail | daemon | kern | user | local[0-7] ] \n\tLog to the specified syslog facility\n"); printf(" -F \tWrite Core Process PID into the specified file\n"); printf(" -R \tRenormalize sampled data\n"); printf(" -u \tLeave IP protocols in numerical format\n"); printf(" -I \tRead packets from the specified savefile\n"); printf(" -Z \tReading from a savefile, sleep the given amount of seconds at startup and between replays\n"); printf(" -W \tReading from a savefile, don't exit but sleep when finished\n"); printf(" -Y \tReading from a savefile, replay the number of times specified\n"); printf("\nMemory plugin (-P memory) options:\n"); printf(" -p \tSocket for client-server communication (DEFAULT: /tmp/collect.pipe)\n"); printf(" -b \tNumber of buckets\n"); printf(" -m \tNumber of memory pools\n"); printf(" -s \tMemory pool size\n"); printf("\nPrint plugin (-P print) plugin options:\n"); printf(" -r \tRefresh time (in seconds)\n"); printf(" -O \t[ formatted | csv | json | avro ] \n\tOutput format\n"); printf(" -o \tPath to output file\n"); printf(" -M \tPrint event init/close marker messages\n"); printf(" -A \tAppend output (applies to -o)\n"); printf(" -E \tCSV format separator (applies to -O csv, DEFAULT: ',')\n"); printf("\n"); printf("For examples, see:\n"); printf(" https://github.com/pmacct/pmacct/blob/master/QUICKSTART or\n"); printf(" https://github.com/pmacct/pmacct/wiki\n"); printf("\n"); printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER); } int main(int argc,char **argv, char **envp) { struct plugins_list_entry *list; struct plugin_requests req; struct packet_ptrs_vector pptrs; char config_file[SRVBUFLEN]; unsigned char *sflow_packet; int logf, rc, yes=1, allowed; struct host_addr addr; struct hosts_table allow; struct id_table bpas_table; struct id_table blp_table; struct id_table bmed_table; struct id_table biss_table; struct id_table bta_table; struct id_table bitr_table; struct id_table sampling_table; u_int32_t idx; int capture_methods = 0; int ret, alloc_sppi = FALSE; SFSample spp; struct sockaddr_storage server, client; struct ipv6_mreq multi_req6; socklen_t clen = sizeof(client), slen = 0; struct ip_mreq multi_req4; int pm_pcap_savefile_round = 0; unsigned char dummy_packet[64]; unsigned char dummy_packet_vlan[64]; unsigned char dummy_packet_mpls[128]; unsigned char dummy_packet_vlan_mpls[128]; struct pcap_pkthdr dummy_pkthdr; struct pcap_pkthdr dummy_pkthdr_vlan; struct pcap_pkthdr dummy_pkthdr_mpls; struct pcap_pkthdr dummy_pkthdr_vlan_mpls; unsigned char dummy_packet6[92]; unsigned char dummy_packet_vlan6[92]; unsigned char dummy_packet_mpls6[128]; unsigned char dummy_packet_vlan_mpls6[128]; struct pcap_pkthdr dummy_pkthdr6; struct pcap_pkthdr dummy_pkthdr_vlan6; struct pcap_pkthdr dummy_pkthdr_mpls6; struct pcap_pkthdr dummy_pkthdr_vlan_mpls6; struct packet_ptrs recv_pptrs; struct pcap_pkthdr recv_pkthdr; sigset_t signal_set; /* getopt() stuff */ extern char *optarg; int errflag, cp; #ifdef WITH_REDIS struct p_redis_host redis_host; #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif umask(077); SF_compute_once(); /* a bunch of default definitions */ reload_map = FALSE; print_stats = FALSE; reload_geoipv2_file = FALSE; reload_log_sf_cnt = FALSE; bpas_map_allocated = FALSE; blp_map_allocated = FALSE; bmed_map_allocated = FALSE; biss_map_allocated = FALSE; bta_map_allocated = FALSE; bitr_map_allocated = FALSE; custom_primitives_allocated = FALSE; bta_map_caching = TRUE; sampling_map_caching = TRUE; find_id_func = SF_find_id; plugins_list = NULL; sflow_packet = malloc(SFLOW_MAX_MSG_SIZE); data_plugins = 0; tee_plugins = 0; errflag = 0; sfacctd_counter_backend_methods = 0; memset(cfg_cmdline, 0, sizeof(cfg_cmdline)); memset(&server, 0, sizeof(server)); memset(&config, 0, sizeof(struct configuration)); memset(&config_file, 0, sizeof(config_file)); memset(&failed_plugins, 0, sizeof(failed_plugins)); memset(&pptrs, 0, sizeof(pptrs)); memset(&req, 0, sizeof(req)); memset(&spp, 0, sizeof(spp)); memset(&xflow_status_table, 0, sizeof(xflow_status_table)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); memset(&bpas_table, 0, sizeof(bpas_table)); memset(&blp_table, 0, sizeof(blp_table)); memset(&bmed_table, 0, sizeof(bmed_table)); memset(&biss_table, 0, sizeof(biss_table)); memset(&bta_table, 0, sizeof(bta_table)); memset(&bitr_table, 0, sizeof(bitr_table)); memset(&sampling_table, 0, sizeof(sampling_table)); memset(&reload_map_tstamp, 0, sizeof(reload_map_tstamp)); log_notifications_init(&log_notifications); config.acct_type = ACCT_SF; config.progname = sfacctd_globstr; rows = 0; memset(&device, 0, sizeof(device)); memset(&recv_pptrs, 0, sizeof(recv_pptrs)); memset(&recv_pkthdr, 0, sizeof(recv_pkthdr)); /* getting commandline values */ while (!errflag && ((cp = getopt(argc, argv, ARGS_SFACCTD)) != -1)) { if (!cfg_cmdline[rows]) cfg_cmdline[rows] = malloc(SRVBUFLEN); memset(cfg_cmdline[rows], 0, SRVBUFLEN); switch (cp) { case 'L': strlcpy(cfg_cmdline[rows], "sfacctd_ip: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'l': strlcpy(cfg_cmdline[rows], "sfacctd_port: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'P': strlcpy(cfg_cmdline[rows], "plugins: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'D': strlcpy(cfg_cmdline[rows], "daemonize: true", SRVBUFLEN); rows++; break; case 'd': debug = TRUE; strlcpy(cfg_cmdline[rows], "debug: true", SRVBUFLEN); rows++; break; case 'n': strlcpy(cfg_cmdline[rows], "networks_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 't': strlcpy(cfg_cmdline[rows], "ports_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'O': strlcpy(cfg_cmdline[rows], "print_output: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'o': strlcpy(cfg_cmdline[rows], "print_output_file: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'M': strlcpy(cfg_cmdline[rows], "print_markers: true", SRVBUFLEN); rows++; break; case 'A': strlcpy(cfg_cmdline[rows], "print_output_file_append: true", SRVBUFLEN); rows++; break; case 'E': strlcpy(cfg_cmdline[rows], "print_output_separator: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'u': strlcpy(cfg_cmdline[rows], "print_num_protos: true", SRVBUFLEN); rows++; break; case 'f': strlcpy(config_file, optarg, sizeof(config_file)); free(cfg_cmdline[rows]); cfg_cmdline[rows] = NULL; break; case 'F': strlcpy(cfg_cmdline[rows], "pidfile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'c': strlcpy(cfg_cmdline[rows], "aggregate: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'b': strlcpy(cfg_cmdline[rows], "imt_buckets: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'm': strlcpy(cfg_cmdline[rows], "imt_mem_pools_number: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'p': strlcpy(cfg_cmdline[rows], "imt_path: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'r': strlcpy(cfg_cmdline[rows], "sql_refresh_time: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 's': strlcpy(cfg_cmdline[rows], "imt_mem_pools_size: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'S': strlcpy(cfg_cmdline[rows], "syslog: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'R': strlcpy(cfg_cmdline[rows], "sfacctd_renormalize: true", SRVBUFLEN); rows++; break; case 'I': strlcpy(cfg_cmdline[rows], "pcap_savefile: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'W': strlcpy(cfg_cmdline[rows], "pcap_savefile_wait: true", SRVBUFLEN); rows++; break; case 'Z': strlcpy(cfg_cmdline[rows], "pcap_savefile_delay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'Y': strlcpy(cfg_cmdline[rows], "pcap_savefile_replay: ", SRVBUFLEN); strncat(cfg_cmdline[rows], optarg, CFG_LINE_LEN(cfg_cmdline[rows])); rows++; break; case 'h': usage_daemon(argv[0]); exit(0); break; case 'V': version_daemon(config.acct_type, SFACCTD_USAGE_HEADER); exit(0); break; case 'a': print_primitives(config.acct_type, SFACCTD_USAGE_HEADER); exit(0); break; default: usage_daemon(argv[0]); exit(1); break; } } /* post-checks and resolving conflicts */ if (strlen(config_file)) { if (parse_configuration_file(config_file) != SUCCESS) exit(1); } else { if (parse_configuration_file(NULL) != SUCCESS) exit(1); } /* XXX: glue; i'm conscious it's a dirty solution from an engineering viewpoint; someday later i'll fix this */ list = plugins_list; while(list) { list->cfg.acct_type = ACCT_SF; list->cfg.progname = sfacctd_globstr; set_default_preferences(&list->cfg); if (!strcmp(list->type.string, "core")) { memcpy(&config, &list->cfg, sizeof(struct configuration)); config.name = list->name; config.type = list->type.string; } list = list->next; } if (config.files_umask) umask(config.files_umask); initsetproctitle(argc, argv, envp); if (config.syslog) { logf = parse_log_facility(config.syslog); if (logf == ERR) { config.syslog = NULL; printf("WARN ( %s/core ): specified syslog facility is not supported. Logging to standard error (stderr).\n", config.name); } else openlog(NULL, LOG_PID, logf); Log(LOG_INFO, "INFO ( %s/core ): Start logging ...\n", config.name); } if (config.logfile) { config.logfile_fd = open_output_file(config.logfile, "a", FALSE); list = plugins_list; while (list) { list->cfg.logfile_fd = config.logfile_fd ; list = list->next; } } if (config.daemon) { list = plugins_list; while (list) { if (!strcmp(list->type.string, "print") && !list->cfg.print_output_file) printf("INFO ( %s/%s ): Daemonizing. Bye bye screen.\n", list->name, list->type.string); list = list->next; } if (!config.syslog && !config.logfile) { if (debug || config.debug) { printf("WARN ( %s/core ): debug is enabled; forking in background. Logging to standard error (stderr) will get lost.\n", config.name); } } daemonize(); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/core ): proc_priority failed (errno: %d)\n", config.name, errno); else Log(LOG_INFO, "INFO ( %s/core ): proc_priority set to %d\n", config.name, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/core ): %s %s (%s)\n", config.name, SFACCTD_USAGE_HEADER, PMACCT_VERSION, PMACCT_BUILD); Log(LOG_INFO, "INFO ( %s/core ): %s\n", config.name, PMACCT_COMPILE_ARGS); if (strlen(config_file)) { char canonical_path[PATH_MAX], *canonical_path_ptr; canonical_path_ptr = realpath(config_file, canonical_path); if (canonical_path_ptr) Log(LOG_INFO, "INFO ( %s/core ): Reading configuration file '%s'.\n", config.name, canonical_path); } else Log(LOG_INFO, "INFO ( %s/core ): Reading configuration from cmdline.\n", config.name); /* Enforcing policies over aggregation methods */ list = plugins_list; while (list) { if (list->type.id != PLUGIN_ID_CORE) { /* applies to all plugins */ plugin_pipe_check(&list->cfg); if (list->cfg.sampling_rate && config.ext_sampling_rate) { Log(LOG_ERR, "ERROR ( %s/core ): Internal packet sampling and external packet sampling are mutual exclusive.\n", config.name); exit_gracefully(1); } /* applies to specific plugins */ if (list->type.id == PLUGIN_ID_NFPROBE || list->type.id == PLUGIN_ID_SFPROBE) { Log(LOG_ERR, "ERROR ( %s/core ): 'nfprobe' and 'sfprobe' plugins not supported in 'sfacctd'.\n", config.name); exit_gracefully(1); } else if (list->type.id == PLUGIN_ID_TEE) { tee_plugins++; list->cfg.what_to_count = COUNT_NONE; list->cfg.data_type = PIPE_TYPE_MSG; } else { list->cfg.data_type = PIPE_TYPE_METADATA; if (list->cfg.what_to_count_2 & (COUNT_POST_NAT_SRC_HOST|COUNT_POST_NAT_DST_HOST| COUNT_POST_NAT_SRC_PORT|COUNT_POST_NAT_DST_PORT|COUNT_NAT_EVENT| COUNT_TIMESTAMP_START|COUNT_TIMESTAMP_END|COUNT_TIMESTAMP_ARRIVAL| COUNT_EXPORT_PROTO_TIME|COUNT_FWD_STATUS|COUNT_FW_EVENT)) list->cfg.data_type |= PIPE_TYPE_NAT; if (list->cfg.what_to_count_2 & (COUNT_MPLS_LABEL_TOP|COUNT_MPLS_LABEL_BOTTOM)) list->cfg.data_type |= PIPE_TYPE_MPLS; if (list->cfg.what_to_count_2 & (COUNT_TUNNEL_SRC_MAC|COUNT_TUNNEL_DST_MAC| COUNT_TUNNEL_SRC_HOST|COUNT_TUNNEL_DST_HOST|COUNT_TUNNEL_IP_PROTO| COUNT_TUNNEL_IP_TOS|COUNT_TUNNEL_SRC_PORT|COUNT_TUNNEL_DST_PORT| COUNT_VXLAN)) { list->cfg.data_type |= PIPE_TYPE_TUN; alloc_sppi = TRUE; } if (list->cfg.what_to_count_2 & (COUNT_LABEL|COUNT_MPLS_LABEL_STACK)) list->cfg.data_type |= PIPE_TYPE_VLEN; evaluate_sums(&list->cfg.what_to_count, &list->cfg.what_to_count_2, list->name, list->type.string); if (!list->cfg.what_to_count && !list->cfg.what_to_count_2 && !list->cfg.cpptrs.num) { Log(LOG_WARNING, "WARN ( %s/%s ): defaulting to SRC HOST aggregation.\n", list->name, list->type.string); list->cfg.what_to_count |= COUNT_SRC_HOST; } if (list->cfg.what_to_count & (COUNT_SRC_AS|COUNT_DST_AS|COUNT_SUM_AS)) { if (!list->cfg.networks_file && list->cfg.nfacctd_as & NF_AS_NEW) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation was selected but NO 'networks_file' specified. Exiting...\n\n", list->name, list->type.string); exit_gracefully(1); } if (!list->cfg.bgp_daemon && !list->cfg.bmp_daemon && list->cfg.nfacctd_as == NF_AS_BGP) { Log(LOG_ERR, "ERROR ( %s/%s ): AS aggregation selected but 'bgp_daemon' or 'bmp_daemon' is not enabled. Exiting...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_as & NF_AS_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_as |= NF_AS_NEW; } if (list->cfg.what_to_count & (COUNT_SRC_NET|COUNT_DST_NET|COUNT_SUM_NET|COUNT_SRC_NMASK|COUNT_DST_NMASK|COUNT_PEER_DST_IP)) { if (!list->cfg.nfacctd_net) { if (list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; if (list->cfg.networks_mask) list->cfg.nfacctd_net |= NF_NET_STATIC; if (!list->cfg.nfacctd_net) list->cfg.nfacctd_net = NF_NET_KEEP; } else { if ((list->cfg.nfacctd_net == NF_NET_NEW && !list->cfg.networks_file) || (list->cfg.nfacctd_net == NF_NET_STATIC && !list->cfg.networks_mask) || (list->cfg.nfacctd_net == NF_NET_BGP && !list->cfg.bgp_daemon && !list->cfg.bmp_daemon) || (list->cfg.nfacctd_net == NF_NET_IGP && !list->cfg.nfacctd_isis)) { Log(LOG_ERR, "ERROR ( %s/%s ): network aggregation selected but none of 'bgp_daemon', 'bmp_daemon', 'isis_daemon', 'networks_file', 'networks_mask' is specified. Exiting ...\n\n", list->name, list->type.string); exit_gracefully(1); } if (list->cfg.nfacctd_net & NF_NET_FALLBACK && list->cfg.networks_file) list->cfg.nfacctd_net |= NF_NET_NEW; } } #if defined (WITH_NDPI) if (list->cfg.what_to_count_2 & COUNT_NDPI_CLASS) { enable_ip_fragment_handler(); config.classifier_ndpi = TRUE; } #endif list->cfg.type_id = list->type.id; bgp_config_checks(&list->cfg); data_plugins++; list->cfg.what_to_count |= COUNT_COUNTERS; } } list = list->next; } if (tee_plugins && data_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): 'tee' plugins are not compatible with data (memory/mysql/pgsql/etc.) plugins. Exiting...\n\n", config.name); exit_gracefully(1); } if (config.pcap_savefile) capture_methods++; if (config.nfacctd_port || config.nfacctd_ip) capture_methods++; #ifdef WITH_KAFKA if (config.nfacctd_kafka_broker_host || config.nfacctd_kafka_topic) capture_methods++; #endif #ifdef WITH_ZMQ if (config.nfacctd_zmq_address) capture_methods++; #endif if (capture_methods > 1) { Log(LOG_ERR, "ERROR ( %s/core ): pcap_savefile, sfacctd_ip, sfacctd_kafka_* and sfacctd_zmq_* are mutual exclusive. Exiting...\n\n", config.name); exit_gracefully(1); } #ifdef WITH_KAFKA if ((config.nfacctd_kafka_broker_host && !config.nfacctd_kafka_topic) || (config.nfacctd_kafka_topic && !config.nfacctd_kafka_broker_host)) { Log(LOG_ERR, "ERROR ( %s/core ): Kafka collection requires both sfacctd_kafka_broker_host and sfacctd_kafka_topic to be specified. Exiting...\n\n", config.name); exit_gracefully(1); } if (config.nfacctd_kafka_broker_host && tee_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): Kafka collection is mutual exclusive with 'tee' plugins. Exiting...\n\n", config.name); exit_gracefully(1); } #endif #ifdef WITH_ZMQ if (config.nfacctd_zmq_address && tee_plugins) { Log(LOG_ERR, "ERROR ( %s/core ): ZeroMQ collection is mutual exclusive with 'tee' plugins. Exiting...\n\n", config.name); exit_gracefully(1); } #endif /* signal handling we want to inherit to plugins (when not re-defined elsewhere) */ memset(&sighandler_action, 0, sizeof(sighandler_action)); /* To ensure the struct holds no garbage values */ sigemptyset(&sighandler_action.sa_mask); /* Within a signal handler all the signals are enabled */ sighandler_action.sa_flags = SA_RESTART; /* To enable re-entering a system call afer done with signal handling */ sighandler_action.sa_handler = startup_handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); /* handles reopening of syslog channel */ sighandler_action.sa_handler = reload; sigaction(SIGHUP, &sighandler_action, NULL); /* logs various statistics via Log() calls */ sighandler_action.sa_handler = push_stats; sigaction(SIGUSR1, &sighandler_action, NULL); /* sets to true the reload_maps flag */ sighandler_action.sa_handler = reload_maps; sigaction(SIGUSR2, &sighandler_action, NULL); /* we want to exit gracefully when a pipe is broken */ sighandler_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigalrm_noop_handler; sigaction(SIGALRM, &sighandler_action, NULL); if (config.pcap_savefile) { open_pcap_savefile(&device, config.pcap_savefile); pm_pcap_savefile_round = 1; enable_ip_fragment_handler(); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { SF_init_kafka_host(&nfacctd_kafka_host); recv_pptrs.pkthdr = &recv_pkthdr; enable_ip_fragment_handler(); } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { int pipe_fd = 0; SF_init_zmq_host(&nfacctd_zmq_host, &pipe_fd); recv_pptrs.pkthdr = &recv_pkthdr; enable_ip_fragment_handler(); } #endif else { /* If no IP address is supplied, let's set our default behaviour: IPv4 address, INADDR_ANY, port 2100 */ if (!config.nfacctd_port) config.nfacctd_port = DEFAULT_SFACCTD_PORT; collector_port = config.nfacctd_port; if (!config.nfacctd_ip) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&server; sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(config.nfacctd_port); slen = sizeof(struct sockaddr_in6); } else { trim_spaces(config.nfacctd_ip); ret = str_to_addr(config.nfacctd_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( %s/core ): 'sfacctd_ip' value is not valid. Exiting.\n", config.name); exit_gracefully(1); } slen = addr_to_sa((struct sockaddr *)&server, &addr, config.nfacctd_port); } /* socket creation */ config.sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); if (config.sock < 0) { /* retry with IPv4 */ if (!config.nfacctd_ip) { struct sockaddr_in *sa4 = (struct sockaddr_in *)&server; sa4->sin_family = AF_INET; sa4->sin_addr.s_addr = htonl(0); sa4->sin_port = htons(config.nfacctd_port); slen = sizeof(struct sockaddr_in); config.sock = socket(((struct sockaddr *)&server)->sa_family, SOCK_DGRAM, 0); } if (config.sock < 0) { Log(LOG_ERR, "ERROR ( %s/core ): socket() failed.\n", config.name); exit_gracefully(1); } } /* bind socket to port */ #if (defined HAVE_SO_REUSEPORT) rc = setsockopt(config.sock, SOL_SOCKET, SO_REUSEPORT, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEPORT.\n", config.name); #endif rc = setsockopt(config.sock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_REUSEADDR.\n", config.name); #if (defined HAVE_SO_BINDTODEVICE) if (config.nfacctd_interface) { rc = setsockopt(config.sock, SOL_SOCKET, SO_BINDTODEVICE, config.nfacctd_interface, (socklen_t) strlen(config.nfacctd_interface)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for SO_BINDTODEVICE (errno: %d).\n", config.name, errno); } #endif if (config.nfacctd_ipv6_only) { int yes=1; rc = setsockopt(config.sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &yes, (socklen_t) sizeof(yes)); if (rc < 0) Log(LOG_ERR, "WARN ( %s/core ): setsockopt() failed for IPV6_V6ONLY.\n", config.name); } if (config.nfacctd_pipe_size) { socklen_t l = sizeof(config.nfacctd_pipe_size); int saved = 0, obtained = 0; getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &saved, &l); Setsocksize(config.sock, SOL_SOCKET, SO_RCVBUF, &config.nfacctd_pipe_size, (socklen_t) sizeof(config.nfacctd_pipe_size)); getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); if (obtained < saved) { Setsocksize(config.sock, SOL_SOCKET, SO_RCVBUF, &saved, l); getsockopt(config.sock, SOL_SOCKET, SO_RCVBUF, &obtained, &l); } Log(LOG_INFO, "INFO ( %s/core ): sfacctd_pipe_size: obtained=%d target=%d.\n", config.name, obtained, config.nfacctd_pipe_size); } /* Multicast: memberships handling */ for (idx = 0; mcast_groups[idx].family && idx < MAX_MCAST_GROUPS; idx++) { if (mcast_groups[idx].family == AF_INET) { memset(&multi_req4, 0, sizeof(multi_req4)); multi_req4.imr_multiaddr.s_addr = mcast_groups[idx].address.ipv4.s_addr; if (setsockopt(config.sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multi_req4, (socklen_t) sizeof(multi_req4)) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): IPv4 multicast address - ADD membership failed.\n", config.name); exit_gracefully(1); } } if (mcast_groups[idx].family == AF_INET6) { memset(&multi_req6, 0, sizeof(multi_req6)); ip6_addr_cpy(&multi_req6.ipv6mr_multiaddr, &mcast_groups[idx].address.ipv6); if (setsockopt(config.sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&multi_req6, (socklen_t) sizeof(multi_req6)) < 0) { Log(LOG_ERR, "ERROR ( %s/core ): IPv6 multicast address - ADD membership failed.\n", config.name); exit_gracefully(1); } } } } if (config.nfacctd_allow_file) load_allow_file(config.nfacctd_allow_file, &allow); else memset(&allow, 0, sizeof(allow)); if (config.sampling_map) { load_id_file(MAP_SAMPLING, config.sampling_map, &sampling_table, &req, &sampling_map_allocated); set_sampling_table(&pptrs, (u_char *) &sampling_table); } else set_sampling_table(&pptrs, NULL); if (config.nfacctd_flow_to_rd_map) { load_id_file(MAP_FLOW_TO_RD, config.nfacctd_flow_to_rd_map, &bitr_table, &req, &bitr_map_allocated); pptrs.v4.bitr_table = (u_char *) &bitr_table; } else pptrs.v4.bitr_table = NULL; if (config.aggregate_primitives) { req.key_value_table = (void *) &custom_primitives_registry; load_id_file(MAP_CUSTOM_PRIMITIVES, config.aggregate_primitives, NULL, &req, &custom_primitives_allocated); } else memset(&custom_primitives_registry, 0, sizeof(custom_primitives_registry)); /* fixing per plugin custom primitives pointers, offsets and lengths */ list = plugins_list; while(list) { custom_primitives_reconcile(&list->cfg.cpptrs, &custom_primitives_registry); if (custom_primitives_vlen(&list->cfg.cpptrs)) list->cfg.data_type |= PIPE_TYPE_VLEN; list = list->next; } if (config.bgp_daemon && config.bmp_daemon) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_daemon and bmp_daemon are currently mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } /* starting the ISIS threa */ if (config.nfacctd_isis) { req.bpf_filter = TRUE; nfacctd_isis_wrapper(); /* Let's give the ISIS thread some advantage to create its structures */ sleep(DEFAULT_SLOTH_SLEEP_TIME); } /* starting the BGP thread */ if (config.bgp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_stdcomm_pattern_to_asn && config.bgp_daemon_lrgcomm_pattern_to_asn) { Log(LOG_ERR, "ERROR ( %s/core ): bgp_stdcomm_pattern_to_asn and bgp_lrgcomm_pattern_to_asn are mutual exclusive. Exiting.\n", config.name); exit_gracefully(1); } load_comm_patterns(&config.bgp_daemon_stdcomm_pattern, &config.bgp_daemon_extcomm_pattern, &config.bgp_daemon_lrgcomm_pattern, &config.bgp_daemon_stdcomm_pattern_to_asn, &config.bgp_daemon_lrgcomm_pattern_to_asn); if (config.bgp_daemon_peer_as_src_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_peer_as_src_map) { load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); pptrs.v4.bpas_table = (u_char *) &bpas_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_peer_as_src_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.bpas_table = NULL; if (config.bgp_daemon_src_local_pref_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_local_pref_map) { load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); pptrs.v4.blp_table = (u_char *) &blp_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_local_pref_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.blp_table = NULL; if (config.bgp_daemon_src_med_type == BGP_SRC_PRIMITIVES_MAP) { if (config.bgp_daemon_src_med_map) { load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); pptrs.v4.bmed_table = (u_char *) &bmed_table; } else { Log(LOG_ERR, "ERROR ( %s/core ): bgp_src_med_type set to 'map' but no map defined. Exiting.\n", config.name); exit_gracefully(1); } } else pptrs.v4.bmed_table = NULL; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); pptrs.v4.bta_table = (u_char *) &bta_table; } else pptrs.v4.bta_table = NULL; bgp_daemon_wrapper(); /* Let's give the BGP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } /* starting the BMP thread */ if (config.bmp_daemon) { int sleep_time = DEFAULT_SLOTH_SLEEP_TIME; req.bpf_filter = TRUE; if (config.bgp_daemon_to_xflow_agent_map) { load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); pptrs.v4.bta_table = (u_char *) &bta_table; } else pptrs.v4.bta_table = NULL; bmp_daemon_wrapper(); /* Let's give the BMP thread some advantage to create its structures */ if (config.rpki_roas_file || config.rpki_rtr_cache) sleep_time += DEFAULT_SLOTH_SLEEP_TIME; sleep(sleep_time); } #if defined WITH_GEOIP if (config.geoip_ipv4_file || config.geoip_ipv6_file) { req.bpf_filter = TRUE; } #endif #if defined WITH_GEOIPV2 if (config.geoipv2_file) { req.bpf_filter = TRUE; } #endif if (!config.pcap_savefile && !config.nfacctd_kafka_broker_host) { rc = bind(config.sock, (struct sockaddr *) &server, slen); if (rc < 0) { Log(LOG_ERR, "ERROR ( %s/core ): bind() to ip=%s port=%d/udp failed (errno: %d).\n", config.name, config.nfacctd_ip, config.nfacctd_port, errno); exit_gracefully(1); } #if defined WITH_EBPF if (config.nfacctd_rp_ebpf_prog) { attach_ebpf_reuseport_balancer(config.sock, config.nfacctd_rp_ebpf_prog, config.cluster_name, "sfacctd", config.cluster_id, FALSE); } #endif } #if defined (WITH_NDPI) if (config.classifier_ndpi) { enable_ip_fragment_handler(); pm_ndpi_wfl = pm_ndpi_workflow_init(); pm_ndpi_export_proto_to_class(pm_ndpi_wfl); } else pm_ndpi_wfl = NULL; #endif /* plugins glue: creation */ load_plugins(&req); load_plugin_filters(1); evaluate_packet_handlers(); pm_setproctitle("%s [%s]", "Core Process", config.proc_name); if (config.pidfile) write_pid_file(config.pidfile); load_networks(config.networks_file, &nt, &nc); /* signals to be handled only by the core process; we set proper handlers after plugin creation */ sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGINT, &sighandler_action, NULL); sighandler_action.sa_handler = PM_sigint_handler; sigaction(SIGTERM, &sighandler_action, NULL); sighandler_action.sa_handler = handle_falling_child; sigaction(SIGCHLD, &sighandler_action, NULL); kill(getpid(), SIGCHLD); /* arranging pointers to dummy packet; to speed up things into the main loop we mantain two packet_ptrs structures when IPv6 is enabled: we will sync here 'pptrs6' for common tables and pointers */ memset(dummy_packet, 0, sizeof(dummy_packet)); pptrs.v4.f_data = (u_char *) &spp; pptrs.v4.f_agent = (u_char *) &client; pptrs.v4.packet_ptr = dummy_packet; pptrs.v4.pkthdr = &dummy_pkthdr; Assign16(((struct eth_header *)pptrs.v4.packet_ptr)->ether_type, htons(ETHERTYPE_IP)); /* 0x800 */ pptrs.v4.mac_ptr = (u_char *)((struct eth_header *)pptrs.v4.packet_ptr)->ether_dhost; pptrs.v4.iph_ptr = pptrs.v4.packet_ptr + ETHER_HDRLEN; pptrs.v4.tlh_ptr = pptrs.v4.packet_ptr + ETHER_HDRLEN + sizeof(struct pm_iphdr); Assign8(((struct pm_iphdr *)pptrs.v4.iph_ptr)->ip_vhl, 5); // pptrs.v4.pkthdr->caplen = 38; /* eth_header + pm_iphdr + pm_tlhdr */ pptrs.v4.pkthdr->caplen = 55; pptrs.v4.pkthdr->len = 100; /* fake len */ pptrs.v4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_vlan, 0, sizeof(dummy_packet_vlan)); pptrs.vlan4.f_data = pptrs.v4.f_data; pptrs.vlan4.f_agent = (u_char *) &client; pptrs.vlan4.packet_ptr = dummy_packet_vlan; pptrs.vlan4.pkthdr = &dummy_pkthdr_vlan; Assign16(((struct eth_header *)pptrs.vlan4.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlan4.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlan4.packet_ptr)->ether_dhost; pptrs.vlan4.vlan_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN; Assign16(*(pptrs.vlan4.vlan_ptr+2), htons(ETHERTYPE_IP)); pptrs.vlan4.iph_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; pptrs.vlan4.tlh_ptr = pptrs.vlan4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN + sizeof(struct pm_iphdr); Assign8(((struct pm_iphdr *)pptrs.vlan4.iph_ptr)->ip_vhl, 5); // pptrs.vlan4.pkthdr->caplen = 42; /* eth_header + vlan + pm_iphdr + pm_tlhdr */ pptrs.vlan4.pkthdr->caplen = 59; pptrs.vlan4.pkthdr->len = 100; /* fake len */ pptrs.vlan4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_mpls, 0, sizeof(dummy_packet_mpls)); pptrs.mpls4.f_data = pptrs.v4.f_data; pptrs.mpls4.f_agent = (u_char *) &client; pptrs.mpls4.packet_ptr = dummy_packet_mpls; pptrs.mpls4.pkthdr = &dummy_pkthdr_mpls; Assign16(((struct eth_header *)pptrs.mpls4.packet_ptr)->ether_type, htons(ETHERTYPE_MPLS)); pptrs.mpls4.mac_ptr = (u_char *)((struct eth_header *)pptrs.mpls4.packet_ptr)->ether_dhost; pptrs.mpls4.mpls_ptr = pptrs.mpls4.packet_ptr + ETHER_HDRLEN; // pptrs.mpls4.pkthdr->caplen = 78; /* eth_header + upto 10 MPLS labels + pm_iphdr + pm_tlhdr */ pptrs.mpls4.pkthdr->caplen = 95; pptrs.mpls4.pkthdr->len = 100; /* fake len */ pptrs.mpls4.l3_proto = ETHERTYPE_IP; memset(dummy_packet_vlan_mpls, 0, sizeof(dummy_packet_vlan_mpls)); pptrs.vlanmpls4.f_data = pptrs.v4.f_data; pptrs.vlanmpls4.f_agent = (u_char *) &client; pptrs.vlanmpls4.packet_ptr = dummy_packet_vlan_mpls; pptrs.vlanmpls4.pkthdr = &dummy_pkthdr_vlan_mpls; Assign16(((struct eth_header *)pptrs.vlanmpls4.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlanmpls4.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlanmpls4.packet_ptr)->ether_dhost; pptrs.vlanmpls4.vlan_ptr = pptrs.vlanmpls4.packet_ptr + ETHER_HDRLEN; Assign16(((struct vlan_header *)pptrs.vlanmpls4.vlan_ptr)->proto, htons(ETHERTYPE_MPLS)); pptrs.vlanmpls4.mpls_ptr = pptrs.vlanmpls4.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; // pptrs.vlanmpls4.pkthdr->caplen = 82; /* eth_header + vlan + upto 10 MPLS labels + pm_iphdr + pm_tlhdr */ pptrs.vlanmpls4.pkthdr->caplen = 99; pptrs.vlanmpls4.pkthdr->len = 100; /* fake len */ pptrs.vlanmpls4.l3_proto = ETHERTYPE_IP; memset(dummy_packet6, 0, sizeof(dummy_packet6)); pptrs.v6.f_data = pptrs.v4.f_data; pptrs.v6.f_agent = (u_char *) &client; pptrs.v6.packet_ptr = dummy_packet6; pptrs.v6.pkthdr = &dummy_pkthdr6; Assign16(((struct eth_header *)pptrs.v6.packet_ptr)->ether_type, htons(ETHERTYPE_IPV6)); pptrs.v6.mac_ptr = (u_char *)((struct eth_header *)pptrs.v6.packet_ptr)->ether_dhost; pptrs.v6.iph_ptr = pptrs.v6.packet_ptr + ETHER_HDRLEN; pptrs.v6.tlh_ptr = pptrs.v6.packet_ptr + ETHER_HDRLEN + sizeof(struct ip6_hdr); Assign16(((struct ip6_hdr *)pptrs.v6.iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs.v6.iph_ptr)->ip6_hlim = 64; // pptrs.v6.pkthdr->caplen = 60; /* eth_header + ip6_hdr + pm_tlhdr */ pptrs.v6.pkthdr->caplen = 77; pptrs.v6.pkthdr->len = 100; /* fake len */ pptrs.v6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_vlan6, 0, sizeof(dummy_packet_vlan6)); pptrs.vlan6.f_data = pptrs.v4.f_data; pptrs.vlan6.f_agent = (u_char *) &client; pptrs.vlan6.packet_ptr = dummy_packet_vlan6; pptrs.vlan6.pkthdr = &dummy_pkthdr_vlan6; Assign16(((struct eth_header *)pptrs.vlan6.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlan6.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlan6.packet_ptr)->ether_dhost; pptrs.vlan6.vlan_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN; Assign8(*(pptrs.vlan6.vlan_ptr+2), 0x86); Assign8(*(pptrs.vlan6.vlan_ptr+3), 0xDD); pptrs.vlan6.iph_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; pptrs.vlan6.tlh_ptr = pptrs.vlan6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN + sizeof(struct ip6_hdr); Assign16(((struct ip6_hdr *)pptrs.vlan6.iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs.vlan6.iph_ptr)->ip6_hlim = 64; // pptrs.vlan6.pkthdr->caplen = 64; /* eth_header + vlan + ip6_hdr + pm_tlhdr */ pptrs.vlan6.pkthdr->caplen = 81; pptrs.vlan6.pkthdr->len = 100; /* fake len */ pptrs.vlan6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_mpls6, 0, sizeof(dummy_packet_mpls6)); pptrs.mpls6.f_data = pptrs.v4.f_data; pptrs.mpls6.f_agent = (u_char *) &client; pptrs.mpls6.packet_ptr = dummy_packet_mpls6; pptrs.mpls6.pkthdr = &dummy_pkthdr_mpls6; Assign16(((struct eth_header *)pptrs.mpls6.packet_ptr)->ether_type, htons(ETHERTYPE_MPLS)); pptrs.mpls6.mac_ptr = (u_char *)((struct eth_header *)pptrs.mpls6.packet_ptr)->ether_dhost; pptrs.mpls6.mpls_ptr = pptrs.mpls6.packet_ptr + ETHER_HDRLEN; // pptrs.mpls6.pkthdr->caplen = 100; /* eth_header + upto 10 MPLS labels + ip6_hdr + pm_tlhdr */ pptrs.mpls6.pkthdr->caplen = 117; pptrs.mpls6.pkthdr->len = 128; /* fake len */ pptrs.mpls6.l3_proto = ETHERTYPE_IPV6; memset(dummy_packet_vlan_mpls6, 0, sizeof(dummy_packet_vlan_mpls6)); pptrs.vlanmpls6.f_data = pptrs.v4.f_data; pptrs.vlanmpls6.f_agent = (u_char *) &client; pptrs.vlanmpls6.packet_ptr = dummy_packet_vlan_mpls6; pptrs.vlanmpls6.pkthdr = &dummy_pkthdr_vlan_mpls6; Assign16(((struct eth_header *)pptrs.vlanmpls6.packet_ptr)->ether_type, htons(ETHERTYPE_8021Q)); pptrs.vlanmpls6.mac_ptr = (u_char *)((struct eth_header *)pptrs.vlanmpls6.packet_ptr)->ether_dhost; pptrs.vlanmpls6.vlan_ptr = pptrs.vlanmpls6.packet_ptr + ETHER_HDRLEN; Assign8(*(pptrs.vlanmpls6.vlan_ptr+2), 0x88); Assign8(*(pptrs.vlanmpls6.vlan_ptr+3), 0x47); pptrs.vlanmpls6.mpls_ptr = pptrs.vlanmpls6.packet_ptr + ETHER_HDRLEN + IEEE8021Q_TAGLEN; // pptrs.vlanmpls6.pkthdr->caplen = 104; /* eth_header + vlan + upto 10 MPLS labels + ip6_hdr + pm_tlhdr */ pptrs.vlanmpls6.pkthdr->caplen = 121; pptrs.vlanmpls6.pkthdr->len = 128; /* fake len */ pptrs.vlanmpls6.l3_proto = ETHERTYPE_IPV6; if (config.pcap_savefile) { Log(LOG_INFO, "INFO ( %s/core ): reading sFlow data from: %s\n", config.name, config.pcap_savefile); allowed = TRUE; if (!config.pcap_sf_delay) sleep(2); else sleep(config.pcap_sf_delay); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { Log(LOG_INFO, "INFO ( %s/core ): reading sFlow data from Kafka %s:%s\n", config.name, p_kafka_get_broker(&nfacctd_kafka_host), p_kafka_get_topic(&nfacctd_kafka_host)); allowed = TRUE; } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { Log(LOG_INFO, "INFO ( %s/core ): reading sFlow data from ZeroMQ %s\n", config.name, p_zmq_get_address(&nfacctd_zmq_host)); allowed = TRUE; } #endif else { char srv_string[INET6_ADDRSTRLEN]; struct host_addr srv_addr; u_int16_t srv_port; sa_to_addr((struct sockaddr *)&server, &srv_addr, &srv_port); addr_to_str(srv_string, &srv_addr); Log(LOG_INFO, "INFO ( %s/core ): waiting for sFlow data on %s:%u\n", config.name, srv_string, srv_port); allowed = TRUE; } if (config.sfacctd_counter_file || config.sfacctd_counter_amqp_routing_key || config.sfacctd_counter_kafka_topic) { if (config.sfacctd_counter_file) sfacctd_counter_backend_methods++; if (config.sfacctd_counter_amqp_routing_key) sfacctd_counter_backend_methods++; if (config.sfacctd_counter_kafka_topic) sfacctd_counter_backend_methods++; if (sfacctd_counter_backend_methods > 1) { Log(LOG_ERR, "ERROR ( %s/core ): sfacctd_counter_file, sfacctd_counter_amqp_routing_key and sfacctd_counter_kafka_topic are mutually exclusive. Exiting.\n", config.name); exit_all(1); } else { sf_cnt_misc_db = &inter_domain_misc_dbs[FUNC_TYPE_SFLOW_COUNTER]; config.sfacctd_counter_max_nodes = MAX_SF_CNT_LOG_ENTRIES; memset(sf_cnt_misc_db, 0, sizeof(struct bgp_misc_structs)); sf_cnt_link_misc_structs(sf_cnt_misc_db); sf_cnt_misc_db->peers_log = malloc(MAX_SF_CNT_LOG_ENTRIES*sizeof(struct bgp_peer_log)); if (!sf_cnt_misc_db->peers_log) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to malloc() sFlow counters log structure. Exiting.\n", config.name); exit_gracefully(1); } memset(sf_cnt_misc_db->peers_log, 0, MAX_SF_CNT_LOG_ENTRIES*sizeof(struct bgp_peer_log)); bgp_peer_log_seq_init(&sf_cnt_misc_db->log_seq); } if (!config.sfacctd_counter_output) { #ifdef WITH_JANSSON config.sfacctd_counter_output = PRINT_OUTPUT_JSON; #else Log(LOG_WARNING, "WARN ( %s/core ): sfacctd_counter_output set to json but will produce no output (missing --enable-jansson).\n", config.name); #endif } } if (config.sfacctd_counter_amqp_routing_key) { #ifdef WITH_RABBITMQ sfacctd_counter_init_amqp_host(); p_amqp_connect_to_publish(&sfacctd_counter_amqp_host); if (!config.sfacctd_counter_amqp_retry) config.sfacctd_counter_amqp_retry = AMQP_DEFAULT_RETRY; #else Log(LOG_WARNING, "WARN ( %s/core ): p_amqp_connect_to_publish() not possible due to missing --enable-rabbitmq\n", config.name); #endif } if (config.sfacctd_counter_kafka_topic) { #ifdef WITH_KAFKA sfacctd_counter_init_kafka_host(); #else Log(LOG_WARNING, "WARN ( %s/core ): p_kafka_connect_to_produce() not possible due to missing --enable-rabbitmq\n", config.name); #endif } #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_core_handler); } #endif if (alloc_sppi) { spp.sppi = malloc(sizeof(SFSample)); memset(spp.sppi, 0, sizeof(SFSample)); } sigemptyset(&signal_set); sigaddset(&signal_set, SIGCHLD); sigaddset(&signal_set, SIGHUP); sigaddset(&signal_set, SIGUSR1); sigaddset(&signal_set, SIGUSR2); sigaddset(&signal_set, SIGTERM); if (config.daemon) { sigaddset(&signal_set, SIGINT); } /* Main loop */ for (;;) { sigprocmask(SIG_BLOCK, &signal_set, NULL); if (config.pcap_savefile) { ret = recvfrom_savefile(&device, (void **) &sflow_packet, (struct sockaddr *) &client, &spp.ts, &pm_pcap_savefile_round, &recv_pptrs); } #ifdef WITH_KAFKA else if (config.nfacctd_kafka_broker_host) { int kafka_reconnect = FALSE; void *kafka_msg = NULL; ret = p_kafka_consume_poller(&nfacctd_kafka_host, &kafka_msg, 1000); switch (ret) { case TRUE: /* got data */ ret = p_kafka_consume_data(&nfacctd_kafka_host, kafka_msg, sflow_packet, SFLOW_MAX_MSG_SIZE); if (ret < 0) kafka_reconnect = TRUE; break; case FALSE: /* timeout */ continue; break; case ERR: /* error */ default: kafka_reconnect = TRUE; break; } if (kafka_reconnect) { /* Close */ p_kafka_manage_consumer(&nfacctd_kafka_host, FALSE); /* Re-open */ SF_init_kafka_host(&nfacctd_kafka_host); continue; } ret = recvfrom_rawip(sflow_packet, ret, (struct sockaddr *) &client, &recv_pptrs); } #endif #ifdef WITH_ZMQ else if (config.nfacctd_zmq_address) { ret = p_zmq_recv_poll(&nfacctd_zmq_host.sock, 1000); switch (ret) { case TRUE: /* got data */ ret = p_zmq_recv_bin(&nfacctd_zmq_host.sock, sflow_packet, SFLOW_MAX_MSG_SIZE); if (ret < 0) continue; /* ZMQ_RECONNECT_IVL */ break; case FALSE: /* timeout */ continue; break; case ERR: /* error */ default: continue; /* ZMQ_RECONNECT_IVL */ break; } ret = recvfrom_rawip(sflow_packet, ret, (struct sockaddr *) &client, &recv_pptrs); } #endif else { ret = recvfrom(config.sock, (unsigned char *)sflow_packet, SFLOW_MAX_MSG_SIZE, 0, (struct sockaddr *) &client, &clen); } spp.rawSample = pptrs.v4.f_header = sflow_packet; spp.rawSampleLen = pptrs.v4.f_len = ret; spp.datap = (u_int32_t *) spp.rawSample; spp.endp = sflow_packet + spp.rawSampleLen; reset_tag_label_status(&pptrs); reset_shadow_status(&pptrs); ipv4_mapped_to_ipv4(&client); /* check if Hosts Allow Table is loaded; if it is, we will enforce rules */ if (allow.num) allowed = check_allow(&allow, (struct sockaddr *)&client); if (!allowed) continue; if (reload_map) { bta_map_caching = TRUE; sampling_map_caching = TRUE; if (config.nfacctd_allow_file) load_allow_file(config.nfacctd_allow_file, &allow); load_networks(config.networks_file, &nt, &nc); if (config.bgp_daemon && config.bgp_daemon_peer_as_src_map) load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, &bpas_table, &req, &bpas_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_local_pref_map) load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, &blp_table, &req, &blp_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_med_map) load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, &bmed_table, &req, &bmed_map_allocated); if (config.bgp_daemon && config.bgp_daemon_to_xflow_agent_map) load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, &bta_table, &req, &bta_map_allocated); if (config.nfacctd_flow_to_rd_map) load_id_file(MAP_FLOW_TO_RD, config.nfacctd_flow_to_rd_map, &bitr_table, &req, &bitr_map_allocated); if (config.sampling_map) { load_id_file(MAP_SAMPLING, config.sampling_map, &sampling_table, &req, &sampling_map_allocated); set_sampling_table(&pptrs, (u_char *) &sampling_table); } reload_map = FALSE; gettimeofday(&reload_map_tstamp, NULL); } if (reload_log) { reload_logs(SFACCTD_USAGE_HEADER); reload_log = FALSE; } if (reload_log_sf_cnt) { int nodes_idx; for (nodes_idx = 0; nodes_idx < config.sfacctd_counter_max_nodes; nodes_idx++) { if (sf_cnt_misc_db->peers_log[nodes_idx].fd) { fclose(sf_cnt_misc_db->peers_log[nodes_idx].fd); sf_cnt_misc_db->peers_log[nodes_idx].fd = open_output_file(sf_cnt_misc_db->peers_log[nodes_idx].filename, "a", FALSE); setlinebuf(sf_cnt_misc_db->peers_log[nodes_idx].fd); } else break; } reload_log_sf_cnt = FALSE; } if (print_stats) { time_t now = time(NULL); print_status_table(&xflow_status_table, now, XFLOW_STATUS_TABLE_SZ); print_stats = FALSE; } if (sfacctd_counter_backend_methods) { gettimeofday(&sf_cnt_misc_db->log_tstamp, NULL); compose_timestamp(sf_cnt_misc_db->log_tstamp_str, SRVBUFLEN, &sf_cnt_misc_db->log_tstamp, TRUE, config.timestamps_since_epoch, config.timestamps_rfc3339, config.timestamps_utc); /* let's reset log sequence here as we do not sequence dump_init/dump_close events */ if (bgp_peer_log_seq_has_ro_bit(&sf_cnt_misc_db->log_seq)) bgp_peer_log_seq_init(&sf_cnt_misc_db->log_seq); #ifdef WITH_RABBITMQ if (config.sfacctd_counter_amqp_routing_key) { time_t last_fail = P_broker_timers_get_last_fail(&sfacctd_counter_amqp_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&sfacctd_counter_amqp_host.btimers)) <= sf_cnt_misc_db->log_tstamp.tv_sec)) { sfacctd_counter_init_amqp_host(); p_amqp_connect_to_publish(&sfacctd_counter_amqp_host); } } #endif #ifdef WITH_KAFKA if (config.sfacctd_counter_kafka_topic) { time_t last_fail = P_broker_timers_get_last_fail(&sfacctd_counter_kafka_host.btimers); if (last_fail && ((last_fail + P_broker_timers_get_retry_interval(&sfacctd_counter_kafka_host.btimers)) <= sf_cnt_misc_db->log_tstamp.tv_sec)) sfacctd_counter_init_kafka_host(); } #endif } if (data_plugins) { switch(spp.datagramVersion = getData32(&spp)) { case 5: getAddress(&spp, &spp.agent_addr); /* We trash the source IP address from f_agent */ if (spp.agent_addr.type == SFLADDRESSTYPE_IP_V4) { struct sockaddr *sa = (struct sockaddr *) &client; struct sockaddr_in *sa4 = (struct sockaddr_in *) &client; sa->sa_family = AF_INET; sa4->sin_addr.s_addr = spp.agent_addr.address.ip_v4.s_addr; } else if (spp.agent_addr.type == SFLADDRESSTYPE_IP_V6) { struct sockaddr *sa = (struct sockaddr *) &client; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &client; sa->sa_family = AF_INET6; ip6_addr_cpy(&sa6->sin6_addr, &spp.agent_addr.address.ip_v6); } process_SFv5_packet(&spp, &pptrs, &req, (struct sockaddr *) &client); break; case 4: case 2: getAddress(&spp, &spp.agent_addr); /* We trash the source IP address from f_agent */ if (spp.agent_addr.type == SFLADDRESSTYPE_IP_V4) { struct sockaddr *sa = (struct sockaddr *) &client; struct sockaddr_in *sa4 = (struct sockaddr_in *) &client; sa->sa_family = AF_INET; sa4->sin_addr.s_addr = spp.agent_addr.address.ip_v4.s_addr; } else if (spp.agent_addr.type == SFLADDRESSTYPE_IP_V6) { struct sockaddr *sa = (struct sockaddr *) &client; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &client; sa->sa_family = AF_INET6; ip6_addr_cpy(&sa6->sin6_addr, &spp.agent_addr.address.ip_v6); } process_SFv2v4_packet(&spp, &pptrs, &req, (struct sockaddr *) &client); break; default: if (!config.nfacctd_disable_checks) { SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown packet", (struct sockaddr *) pptrs.v4.f_agent); xflow_status_table.tot_bad_datagrams++; } break; } } else if (tee_plugins) { process_SF_raw_packet(&spp, &pptrs, &req, (struct sockaddr *) &client); } sigprocmask(SIG_UNBLOCK, &signal_set, NULL); } } void InterSampleCleanup(SFSample *spp) { u_char *start = (u_char *) spp; u_char *ptr = (u_char *) &spp->sampleType; SFSample *sppi = (SFSample *) spp->sppi; memset(ptr, 0, (SFSampleSz - (ptr - start))); spp->sppi = (void *) sppi; if (spp->sppi) { start = (u_char *) sppi; ptr = (u_char *) &sppi->sampleType; memset(ptr, 0, (SFSampleSz - (ptr - start))); } } void process_SFv2v4_packet(SFSample *spp, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req, struct sockaddr *agent) { u_int32_t samplesInPacket, idx; u_int32_t sampleType, sysUpTime, sequenceNo; spp->agentSubId = 0; /* not supported */ sequenceNo = spp->sequenceNo = getData32(spp); sysUpTime = spp->sysUpTime = getData32(spp); samplesInPacket = getData32(spp); pptrsv->v4.f_status = (u_char *) sfv245_check_status(spp, &pptrsv->v4, agent); set_vector_f_status(pptrsv); if (config.debug) { sa_to_addr((struct sockaddr *)pptrsv->v4.f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received sFlow packet from [%s:%u] version [%u] seqno [%u]\n", config.name, debug_agent_addr, debug_agent_port, spp->datagramVersion, sequenceNo); } if (sfacctd_counter_backend_methods) sfv245_check_counter_log_init(&pptrsv->v4); for (idx = 0; idx < samplesInPacket; idx++) { InterSampleCleanup(spp); spp->sequenceNo = sequenceNo; spp->sysUpTime = sysUpTime; set_vector_sample_type(pptrsv, 0); sampleType = getData32(spp); if (!pptrsv->v4.sample_type) set_vector_sample_type(pptrsv, sampleType); switch (sampleType) { case SFLFLOW_SAMPLE: readv2v4FlowSample(spp, pptrsv, req); break; case SFLCOUNTERS_SAMPLE: readv2v4CountersSample(spp, pptrsv); break; default: SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown v2/v4 sample", (struct sockaddr *) pptrsv->v4.f_agent); xflow_status_table.tot_bad_datagrams++; return; /* unexpected sampleType; aborting packet */ } if ((u_char *)spp->datap > spp->endp) return; } } void process_SFv5_packet(SFSample *spp, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req, struct sockaddr *agent) { u_int32_t samplesInPacket, idx; u_int32_t sampleType, agentSubId, sequenceNo, sysUpTime; agentSubId = spp->agentSubId = getData32(spp); sequenceNo = spp->sequenceNo = getData32(spp); sysUpTime = spp->sysUpTime = getData32(spp); samplesInPacket = getData32(spp); pptrsv->v4.f_status = (u_char *) sfv245_check_status(spp, &pptrsv->v4, agent); set_vector_f_status(pptrsv); if (config.debug) { sa_to_addr((struct sockaddr *)pptrsv->v4.f_agent, &debug_a, &debug_agent_port); addr_to_str(debug_agent_addr, &debug_a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received sFlow packet from [%s:%u] version [%u] seqno [%u]\n", config.name, debug_agent_addr, debug_agent_port, spp->datagramVersion, sequenceNo); } if (sfacctd_counter_backend_methods) sfv245_check_counter_log_init(&pptrsv->v4); for (idx = 0; idx < samplesInPacket; idx++) { InterSampleCleanup(spp); spp->agentSubId = agentSubId; spp->sequenceNo = sequenceNo; spp->sysUpTime = sysUpTime; set_vector_sample_type(pptrsv, 0); sfv5_modules_db_init(); SFv5_read_sampleType: sampleType = getData32(spp); if (!pptrsv->v4.sample_type) set_vector_sample_type(pptrsv, sampleType); switch (sampleType) { case SFLFLOW_SAMPLE: readv5FlowSample(spp, FALSE, pptrsv, req, TRUE); break; case SFLCOUNTERS_SAMPLE: readv5CountersSample(spp, FALSE, pptrsv); break; case SFLFLOW_SAMPLE_EXPANDED: readv5FlowSample(spp, TRUE, pptrsv, req, TRUE); break; case SFLCOUNTERS_SAMPLE_EXPANDED: readv5CountersSample(spp, TRUE, pptrsv); break; case SFLACL_BROCADE_SAMPLE: getData32(spp); /* trash: sample length */ getData32(spp); /* trash: FoundryFlags */ getData32(spp); /* trash: FoundryGroupID */ goto SFv5_read_sampleType; /* rewind */ break; default: SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown v5 sample", (struct sockaddr *) pptrsv->v4.f_agent); xflow_status_table.tot_bad_datagrams++; return; /* unexpected sampleType; aborting packet */ } if ((u_char *)spp->datap > spp->endp) return; } } void process_SF_raw_packet(SFSample *spp, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req, struct sockaddr *agent) { struct packet_ptrs *pptrs = &pptrsv->v4; u_int32_t agentSubId; switch (spp->datagramVersion = getData32(spp)) { case 5: getAddress(spp, &spp->agent_addr); spp->agentSubId = agentSubId = getData32(spp); pptrs->seqno = getData32(spp); break; case 4: case 2: getAddress(spp, &spp->agent_addr); spp->agentSubId = agentSubId = 0; /* not supported */ pptrs->seqno = getData32(spp); break; default: if (!config.nfacctd_disable_checks) { SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown sFlow packet", (struct sockaddr *) pptrs->f_agent); xflow_status_table.tot_bad_datagrams++; } return; } if (config.debug) { struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)pptrs->f_agent, &a, &agent_port); addr_to_str(agent_addr, &a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Received sFlow packet from [%s:%u] version [%u] seqno [%u]\n", config.name, agent_addr, agent_port, spp->datagramVersion, pptrs->seqno); } if (req->ptm_c.exec_ptm_dissect) { /* Dissecting is not supported for sFlow v2-v4 due to lack of length fields */ if (spp->datagramVersion == 5) { u_int32_t samplesInPacket, sampleType, idx, *flowLenPtr; struct SF_dissect dissect; memset(&dissect, 0, sizeof(dissect)); pptrs->tee_dissect = (char *) &dissect; req->ptm_c.exec_ptm_res = TRUE; dissect.hdrBasePtr = spp->rawSample; skipBytes(spp, 4); /* sysUpTime */ dissect.samplesInPkt = (u_int32_t *) getPointer(spp); samplesInPacket = getData32(spp); dissect.hdrEndPtr = (u_char *) getPointer(spp); dissect.hdrLen = (dissect.hdrEndPtr - dissect.hdrBasePtr); (*dissect.samplesInPkt) = htonl(1); for (idx = 0; idx < samplesInPacket; idx++) { InterSampleCleanup(spp); set_vector_sample_type(pptrsv, 0); spp->agentSubId = agentSubId; dissect.flowBasePtr = (u_char *) getPointer(spp); sampleType = getData32(spp); set_vector_sample_type(pptrsv, sampleType); sfv5_modules_db_init(); flowLenPtr = (u_int32_t *) getPointer(spp); dissect.flowLen = (ntohl(*flowLenPtr) + 8 /* add sample type + sample length */); dissect.flowEndPtr = (dissect.flowBasePtr + dissect.flowLen); switch (sampleType) { case SFLFLOW_SAMPLE: readv5FlowSample(spp, FALSE, pptrsv, req, FALSE); break; case SFLFLOW_SAMPLE_EXPANDED: readv5FlowSample(spp, TRUE, pptrsv, req, FALSE); break; default: /* we just trash counter samples and all when dissecting */ skipBytes(spp, (dissect.flowLen - 4 /* subtract sample type */)); continue; } if (config.debug) { struct host_addr a; char agent_addr[50]; u_int16_t agent_port; sa_to_addr((struct sockaddr *)pptrs->f_agent, &a, &agent_port); addr_to_str(agent_addr, &a); Log(LOG_DEBUG, "DEBUG ( %s/core ): Split sFlow Flow Sample from [%s:%u] version [%u] seqno [%u] [%u/%u]\n", config.name, agent_addr, agent_port, spp->datagramVersion, pptrs->seqno, (idx+1), samplesInPacket); } /* if something is wrong with the pointers, let's stop here but still we take a moment to send the full packet over */ if ((u_char *) spp->datap > spp->endp) break; exec_plugins(pptrs, req); } /* preps to possibly send over the full packet next */ InterSampleCleanup(spp); set_vector_sample_type(pptrsv, 0); spp->agentSubId = agentSubId; (*dissect.samplesInPkt) = htonl(samplesInPacket); } else Log(LOG_DEBUG, "DEBUG ( %s/core ): sFlow packet version (%u) not supported for dissection\n", config.name, spp->datagramVersion); } else sfv245_check_status(spp, pptrs, agent); /* If dissecting, we may also send the full packet in case multiple tee plugins are instantiated and any of them does not require dissection */ pptrs->tee_dissect = NULL; req->ptm_c.exec_ptm_res = FALSE; exec_plugins(pptrs, req); } void SF_compute_once() { struct pkt_data dummy; CounterSz = sizeof(dummy.pkt_len); PdataSz = sizeof(struct pkt_data); PpayloadSz = sizeof(struct pkt_payload); PmsgSz = sizeof(struct pkt_msg); PextrasSz = sizeof(struct pkt_extras); PbgpSz = sizeof(struct pkt_bgp_primitives); PlbgpSz = sizeof(struct pkt_legacy_bgp_primitives); PnatSz = sizeof(struct pkt_nat_primitives); PmplsSz = sizeof(struct pkt_mpls_primitives); PtunSz = sizeof(struct pkt_tunnel_primitives); PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); ChBufHdrSz = sizeof(struct ch_buf_hdr); CharPtrSz = sizeof(char *); IP4HdrSz = sizeof(struct pm_iphdr); IP4TlSz = sizeof(struct pm_iphdr)+sizeof(struct pm_tlhdr); SFSampleSz = sizeof(SFSample); SFLAddressSz = sizeof(SFLAddress); SFrenormEntrySz = sizeof(struct xflow_status_entry_sampling); PptrsSz = sizeof(struct packet_ptrs); HostAddrSz = sizeof(struct host_addr); UDPHdrSz = sizeof(struct pm_udphdr); IP6HdrSz = sizeof(struct ip6_hdr); IP6AddrSz = sizeof(struct in6_addr); IP6TlSz = sizeof(struct ip6_hdr)+sizeof(struct pm_tlhdr); } void SF_notify_malf_packet(short int severity, char *severity_str, char *ostr, struct sockaddr *sa) { struct host_addr a; char errstr[SRVBUFLEN]; char agent_addr[50] /* able to fit an IPv6 string aswell */, any[] = "0.0.0.0"; u_int16_t agent_port; sa_to_addr((struct sockaddr *)sa, &a, &agent_port); addr_to_str(agent_addr, &a); snprintf(errstr, SRVBUFLEN, "%s ( %s/core ): %s: sfacctd=%s:%u agent=%s:%u \n", severity_str, config.name, ostr, ((config.nfacctd_ip) ? config.nfacctd_ip : any), collector_port, agent_addr, agent_port); Log(severity, "%s", errstr); } void finalizeSample(SFSample *sample, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req) { struct packet_ptrs *pptrs = &pptrsv->v4; u_int16_t dcd_sport = htons(sample->dcd_sport), dcd_dport = htons(sample->dcd_dport); u_int8_t dcd_ipProtocol = sample->dcd_ipProtocol, dcd_ipTos = sample->dcd_ipTos; u_int8_t dcd_tcpFlags = sample->dcd_tcpFlags; u_int16_t vlan = htons(sample->in_vlan); /* check for out_vlan */ if (!vlan && sample->out_vlan) vlan = htons(sample->out_vlan); /* We consider packets if: - sample->gotIPV4 || sample->gotIPV6 : it belongs to either an IPv4 or IPv6 packet. - !sample->eth_type : we don't know the L3 protocol. VLAN or MPLS accounting case. */ if (sample->gotIPV4 || sample->gotIPV6 || !sample->eth_type) { reset_net_status_v(pptrsv); pptrs->flow_type.traffic_type = SF_evaluate_flow_type(pptrs); if (config.classifier_ndpi || config.aggregate_primitives) sf_flow_sample_hdr_decode(sample); /* we need to understand the IP protocol version in order to build the fake packet */ switch (pptrs->flow_type.traffic_type) { case PM_FTYPE_IPV4: if (req->bpf_filter) { reset_mac(pptrs); reset_ip4(pptrs); memcpy(pptrs->mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrs->mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); ((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, &sample->dcd_srcIP, 4); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, &sample->dcd_dstIP, 4); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_p, &dcd_ipProtocol, 1); memcpy(&((struct pm_iphdr *)pptrs->iph_ptr)->ip_tos, &dcd_ipTos, 1); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrs->lm_mask_src = sample->srcMask; pptrs->lm_mask_dst = sample->dstMask; pptrs->lm_method_src = NF_NET_KEEP; pptrs->lm_method_dst = NF_NET_KEEP; pptrs->l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(pptrs); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, pptrs, &pptrs->bta, &pptrs->bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, pptrs, &pptrs->bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(pptrs, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, pptrs, &pptrs->bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, pptrs, &pptrs->blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, pptrs, &pptrs->bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(pptrs); exec_plugins(pptrs, req); break; case PM_FTYPE_IPV6: memcpy(&pptrsv->v6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac(&pptrsv->v6); reset_ip6(&pptrsv->v6); ((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(pptrsv->v6.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->v6.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_src, &sample->ipsrc.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_dst, &sample->ipdst.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->v6.iph_ptr)->ip6_nxt, &dcd_ipProtocol, 1); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->v6.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->v6.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->v6.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->v6.lm_mask_src = sample->srcMask; pptrsv->v6.lm_mask_dst = sample->dstMask; pptrsv->v6.lm_method_src = NF_NET_KEEP; pptrsv->v6.lm_method_dst = NF_NET_KEEP; pptrsv->v6.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->v6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->v6, &pptrsv->v6.bta, &pptrsv->v6.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->v6, &pptrsv->v6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->v6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->v6, &pptrsv->v6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->v6, &pptrsv->v6.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->v6, &pptrsv->v6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->v6); exec_plugins(&pptrsv->v6, req); break; case PM_FTYPE_VLAN_IPV4: memcpy(&pptrsv->vlan4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac_vlan(&pptrsv->vlan4); reset_ip4(&pptrsv->vlan4); memcpy(pptrsv->vlan4.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->vlan4.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); memcpy(pptrsv->vlan4.vlan_ptr, &vlan, 2); ((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_src, &sample->dcd_srcIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_dst, &sample->dcd_dstIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_p, &dcd_ipProtocol, 1); memcpy(&((struct pm_iphdr *)pptrsv->vlan4.iph_ptr)->ip_tos, &dcd_ipTos, 1); memcpy(&((struct pm_tlhdr *)pptrsv->vlan4.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->vlan4.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->vlan4.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->vlan4.lm_mask_src = sample->srcMask; pptrsv->vlan4.lm_mask_dst = sample->dstMask; pptrsv->vlan4.lm_method_src = NF_NET_KEEP; pptrsv->vlan4.lm_method_dst = NF_NET_KEEP; pptrsv->vlan4.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlan4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlan4, &pptrsv->vlan4.bta, &pptrsv->vlan4.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlan4, &pptrsv->vlan4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlan4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlan4, &pptrsv->vlan4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlan4, &pptrsv->vlan4.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlan4, &pptrsv->vlan4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlan4); exec_plugins(&pptrsv->vlan4, req); break; case PM_FTYPE_VLAN_IPV6: memcpy(&pptrsv->vlan6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { reset_mac_vlan(&pptrsv->vlan6); reset_ip6(&pptrsv->vlan6); memcpy(pptrsv->vlan6.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->vlan6.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); memcpy(pptrsv->vlan6.vlan_ptr, &vlan, 2); ((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_src, &sample->ipsrc.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_dst, &sample->ipdst.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->vlan6.iph_ptr)->ip6_nxt, &dcd_ipProtocol, 1); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->vlan6.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->vlan6.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->vlan6.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->vlan6.lm_mask_src = sample->srcMask; pptrsv->vlan6.lm_mask_dst = sample->dstMask; pptrsv->vlan6.lm_method_src = NF_NET_KEEP; pptrsv->vlan6.lm_method_dst = NF_NET_KEEP; pptrsv->vlan6.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlan6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlan6, &pptrsv->vlan6.bta, &pptrsv->vlan6.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlan6, &pptrsv->vlan6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlan6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlan6, &pptrsv->vlan6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlan6, &pptrsv->vlan6.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlan6, &pptrsv->vlan6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlan6); exec_plugins(&pptrsv->vlan6, req); break; case PM_FTYPE_MPLS_IPV4: memcpy(&pptrsv->mpls4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->mpls4.mpls_ptr; u_int32_t label, idx; /* XXX: fix caplen */ reset_mac(&pptrsv->mpls4); memcpy(pptrsv->mpls4.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->mpls4.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); for (idx = 0; idx <= sample->lstk.depth && idx < 10; idx++) { label = sample->lstk.stack[idx]; memcpy(ptr, &label, 4); ptr += 4; } stick_bosbit(ptr-4); pptrsv->mpls4.iph_ptr = ptr; pptrsv->mpls4.tlh_ptr = ptr + IP4HdrSz; reset_ip4(&pptrsv->mpls4); ((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_src, &sample->dcd_srcIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_dst, &sample->dcd_dstIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_p, &dcd_ipProtocol, 1); memcpy(&((struct pm_iphdr *)pptrsv->mpls4.iph_ptr)->ip_tos, &dcd_ipTos, 1); memcpy(&((struct pm_tlhdr *)pptrsv->mpls4.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->mpls4.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->mpls4.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->mpls4.lm_mask_src = sample->srcMask; pptrsv->mpls4.lm_mask_dst = sample->dstMask; pptrsv->mpls4.lm_method_src = NF_NET_KEEP; pptrsv->mpls4.lm_method_dst = NF_NET_KEEP; pptrsv->mpls4.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->mpls4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->mpls4, &pptrsv->mpls4.bta, &pptrsv->mpls4.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->mpls4, &pptrsv->mpls4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->mpls4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->mpls4, &pptrsv->mpls4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->mpls4, &pptrsv->mpls4.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->mpls4, &pptrsv->mpls4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->mpls4); exec_plugins(&pptrsv->mpls4, req); break; case PM_FTYPE_MPLS_IPV6: memcpy(&pptrsv->mpls6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->mpls6.mpls_ptr; u_int32_t label, idx; /* XXX: fix caplen */ reset_mac(&pptrsv->mpls6); memcpy(pptrsv->mpls6.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->mpls6.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); for (idx = 0; idx <= sample->lstk.depth && idx < 10; idx++) { label = sample->lstk.stack[idx]; memcpy(ptr, &label, 4); ptr += 4; } stick_bosbit(ptr-4); pptrsv->mpls6.iph_ptr = ptr; pptrsv->mpls6.tlh_ptr = ptr + IP6HdrSz; reset_ip6(&pptrsv->mpls6); ((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_src, &sample->ipsrc.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_dst, &sample->ipdst.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->mpls6.iph_ptr)->ip6_nxt, &dcd_ipProtocol, 1); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->mpls6.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->mpls6.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->mpls6.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->mpls6.lm_mask_src = sample->srcMask; pptrsv->mpls6.lm_mask_dst = sample->dstMask; pptrsv->mpls6.lm_method_src = NF_NET_KEEP; pptrsv->mpls6.lm_method_dst = NF_NET_KEEP; pptrsv->mpls6.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->mpls6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->mpls6, &pptrsv->mpls6.bta, &pptrsv->mpls6.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->mpls6, &pptrsv->mpls6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->mpls6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->mpls6, &pptrsv->mpls6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->mpls6, &pptrsv->mpls6.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->mpls6, &pptrsv->mpls6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->mpls6); exec_plugins(&pptrsv->mpls6, req); break; case PM_FTYPE_VLAN_MPLS_IPV4: memcpy(&pptrsv->vlanmpls4.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->vlanmpls4.mpls_ptr; u_int32_t label, idx; /* XXX: fix caplen */ reset_mac_vlan(&pptrsv->vlanmpls4); memcpy(pptrsv->vlanmpls4.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->vlanmpls4.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); memcpy(pptrsv->vlanmpls4.vlan_ptr, &vlan, 2); for (idx = 0; idx <= sample->lstk.depth && idx < 10; idx++) { label = sample->lstk.stack[idx]; memcpy(ptr, &label, 4); ptr += 4; } stick_bosbit(ptr-4); pptrsv->vlanmpls4.iph_ptr = ptr; pptrsv->vlanmpls4.tlh_ptr = ptr + IP4HdrSz; reset_ip4(&pptrsv->vlanmpls4); ((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_vhl = 0x45; memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_src, &sample->dcd_srcIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_dst, &sample->dcd_dstIP, 4); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_p, &dcd_ipProtocol, 1); memcpy(&((struct pm_iphdr *)pptrsv->vlanmpls4.iph_ptr)->ip_tos, &dcd_ipTos, 1); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls4.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls4.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->vlanmpls4.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->vlanmpls4.lm_mask_src = sample->srcMask; pptrsv->vlanmpls4.lm_mask_dst = sample->dstMask; pptrsv->vlanmpls4.lm_method_src = NF_NET_KEEP; pptrsv->vlanmpls4.lm_method_dst = NF_NET_KEEP; pptrsv->vlanmpls4.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlanmpls4); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bta, &pptrsv->vlanmpls4.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlanmpls4, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlanmpls4, &pptrsv->vlanmpls4.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlanmpls4); exec_plugins(&pptrsv->vlanmpls4, req); break; case PM_FTYPE_VLAN_MPLS_IPV6: memcpy(&pptrsv->vlanmpls6.flow_type, &pptrs->flow_type, sizeof(struct flow_chars)); if (req->bpf_filter) { u_char *ptr = pptrsv->vlanmpls6.mpls_ptr; u_int32_t label, idx; /* XXX: fix caplen */ reset_mac_vlan(&pptrsv->vlanmpls6); memcpy(pptrsv->vlanmpls6.mac_ptr+ETH_ADDR_LEN, &sample->eth_src, ETH_ADDR_LEN); memcpy(pptrsv->vlanmpls6.mac_ptr, &sample->eth_dst, ETH_ADDR_LEN); memcpy(pptrsv->vlanmpls6.vlan_ptr, &vlan, 2); for (idx = 0; idx <= sample->lstk.depth && idx < 10; idx++) { label = sample->lstk.stack[idx]; memcpy(ptr, &label, 4); ptr += 4; } stick_bosbit(ptr-4); pptrsv->vlanmpls6.iph_ptr = ptr; pptrsv->vlanmpls6.tlh_ptr = ptr + IP6HdrSz; reset_ip6(&pptrsv->vlanmpls6); ((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_ctlun.ip6_un2_vfc = 0x60; memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_src, &sample->ipsrc.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_dst, &sample->ipdst.address.ip_v6, IP6AddrSz); memcpy(&((struct ip6_hdr *)pptrsv->vlanmpls6.iph_ptr)->ip6_nxt, &dcd_ipProtocol, 1); /* XXX: class ID ? */ memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls6.tlh_ptr)->src_port, &dcd_sport, 2); memcpy(&((struct pm_tlhdr *)pptrsv->vlanmpls6.tlh_ptr)->dst_port, &dcd_dport, 2); memcpy(&((struct pm_tcphdr *)pptrsv->vlanmpls6.tlh_ptr)->th_flags, &dcd_tcpFlags, 1); } pptrsv->vlanmpls6.lm_mask_src = sample->srcMask; pptrsv->vlanmpls6.lm_mask_dst = sample->dstMask; pptrsv->vlanmpls6.lm_method_src = NF_NET_KEEP; pptrsv->vlanmpls6.lm_method_dst = NF_NET_KEEP; pptrsv->vlanmpls6.l4_proto = sample->dcd_ipProtocol; if (config.nfacctd_isis) isis_srcdst_lookup(&pptrsv->vlanmpls6); if (config.bgp_daemon_to_xflow_agent_map) BTA_find_id((struct id_table *)pptrs->bta_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bta, &pptrsv->vlanmpls6.bta2); if (config.nfacctd_flow_to_rd_map) SF_find_id((struct id_table *)pptrs->bitr_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bitr, NULL); if (config.bgp_daemon) bgp_srcdst_lookup(&pptrsv->vlanmpls6, FUNC_TYPE_BGP); if (config.bgp_daemon_peer_as_src_map) SF_find_id((struct id_table *)pptrs->bpas_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) SF_find_id((struct id_table *)pptrs->blp_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.blp, NULL); if (config.bgp_daemon_src_med_map) SF_find_id((struct id_table *)pptrs->bmed_table, &pptrsv->vlanmpls6, &pptrsv->vlanmpls6.bmed, NULL); if (config.bmp_daemon) bmp_srcdst_lookup(&pptrsv->vlanmpls6); exec_plugins(&pptrsv->vlanmpls6, req); break; default: break; } } } int SF_find_id(struct id_table *t, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2) { struct sockaddr sa_local; struct sockaddr_in *sa4 = (struct sockaddr_in *) &sa_local; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &sa_local; SFSample *sample = (SFSample *)pptrs->f_data; int x, begin = 0, end = 0; pm_id_t ret = 0; if (!t) return 0; /* The id_table is shared between by IPv4 and IPv6 sFlow collectors. IPv4 ones are in the lower part (0..x), IPv6 ones are in the upper part (x+1..end) */ pretag_init_vars(pptrs, t); if (tag) *tag = 0; if (tag2) *tag2 = 0; if (pptrs) { pptrs->have_tag = FALSE; pptrs->have_tag2 = FALSE; } /* If we have any index defined, let's use it */ if (config.maps_index && pretag_index_have_one(t)) { struct id_entry *index_results[ID_TABLE_INDEX_RESULTS]; u_int32_t iterator, num_results; num_results = pretag_index_lookup(t, pptrs, index_results, ID_TABLE_INDEX_RESULTS); for (iterator = 0; index_results[iterator] && iterator < num_results; iterator++) { ret = pretag_entry_process(index_results[iterator], pptrs, tag, tag2); if (!(ret & PRETAG_MAP_RCODE_JEQ)) return ret; } /* done */ return ret; } if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V4) { begin = 0; end = t->ipv4_num; sa_local.sa_family = AF_INET; sa4->sin_addr.s_addr = sample->agent_addr.address.ip_v4.s_addr; } else if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V6) { begin = t->num-t->ipv6_num; end = t->num; sa_local.sa_family = AF_INET6; ip6_addr_cpy(&sa6->sin6_addr, &sample->agent_addr.address.ip_v6); } for (x = begin; x < end; x++) { if (host_addr_mask_sa_cmp(&t->e[x].key.agent_ip.a, &t->e[x].key.agent_mask, &sa_local) == 0) { ret = pretag_entry_process(&t->e[x], pptrs, tag, tag2); if (!ret || ret > TRUE) { if (ret & PRETAG_MAP_RCODE_JEQ) { x = t->e[x].jeq.ptr->pos; x--; // yes, it will be automagically incremented by the for() cycle } else break; } } } return ret; } u_int8_t SF_evaluate_flow_type(struct packet_ptrs *pptrs) { SFSample *sample = (SFSample *)pptrs->f_data; u_int8_t ret = FALSE; if (sample->in_vlan || sample->out_vlan) ret += PM_FTYPE_VLAN; if (sample->lstk.depth > 0) ret += PM_FTYPE_MPLS; if (sample->gotIPV4) ret += PM_FTYPE_IPV4; else if (sample->gotIPV6) ret += PM_FTYPE_IPV6; return ret; } void set_vector_sample_type(struct packet_ptrs_vector *pptrsv, u_int32_t sample_type) { pptrsv->v4.sample_type = sample_type; pptrsv->vlan4.sample_type = sample_type; pptrsv->mpls4.sample_type = sample_type; pptrsv->vlanmpls4.sample_type = sample_type; pptrsv->v6.sample_type = sample_type; pptrsv->vlan6.sample_type = sample_type; pptrsv->mpls6.sample_type = sample_type; pptrsv->vlanmpls6.sample_type = sample_type; } void reset_mac(struct packet_ptrs *pptrs) { memset(pptrs->mac_ptr, 0, 2*ETH_ADDR_LEN); } void reset_mac_vlan(struct packet_ptrs *pptrs) { memset(pptrs->mac_ptr, 0, 2*ETH_ADDR_LEN); memset(pptrs->vlan_ptr, 0, 2); } void reset_ip4(struct packet_ptrs *pptrs) { memset(pptrs->iph_ptr, 0, IP4TlSz); Assign8(((struct pm_iphdr *)pptrs->iph_ptr)->ip_vhl, 5); } void reset_ip6(struct packet_ptrs *pptrs) { memset(pptrs->iph_ptr, 0, IP6TlSz); Assign16(((struct ip6_hdr *)pptrs->iph_ptr)->ip6_plen, htons(100)); ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_hlim = 64; } struct xflow_status_entry *sfv245_check_status(SFSample *spp, struct packet_ptrs *pptrs, struct sockaddr *sa) { struct sockaddr salocal; u_int32_t aux1 = spp->agentSubId; struct xflow_status_entry *entry = NULL; int hash; memcpy(&salocal, sa, sizeof(struct sockaddr)); /* Let's copy the IPv4 sFlow agent address; family is defined just in case the remote peer IP address was reported as IPv4-mapped IPv6 address */ salocal.sa_family = AF_INET; ( (struct sockaddr_in *)&salocal )->sin_addr = spp->agent_addr.address.ip_v4; hash = hash_status_table(aux1, &salocal, XFLOW_STATUS_TABLE_SZ); if (hash >= 0) { entry = search_status_table(&xflow_status_table, &salocal, aux1, 0, hash, XFLOW_STATUS_TABLE_MAX_ENTRIES); if (entry) { update_status_table(entry, spp->sequenceNo, pptrs->f_len); entry->inc = 1; } } return entry; } void sfv245_check_counter_log_init(struct packet_ptrs *pptrs) { struct xflow_status_entry *entry = NULL; struct bgp_peer *peer; if (!pptrs) return; entry = (struct xflow_status_entry *) pptrs->f_status; if (entry) { if (!entry->sf_cnt) { entry->sf_cnt = malloc(sizeof(struct bgp_peer)); if (!entry->sf_cnt) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to malloc() xflow_status_entry sFlow counters log structure. Exiting.\n", config.name); exit_gracefully(1); } memset(entry->sf_cnt, 0, sizeof(struct bgp_peer)); } peer = (struct bgp_peer *) entry->sf_cnt; if (!peer->log) { memcpy(&peer->addr, &entry->agent_addr, sizeof(struct host_addr)); addr_to_str(peer->addr_str, &peer->addr); bgp_peer_log_init(peer, NULL, config.sfacctd_counter_output, FUNC_TYPE_SFLOW_COUNTER); } } } int sf_cnt_log_msg(struct bgp_peer *peer, SFSample *sample, int version, u_int32_t len, char *event_type, int output, u_int32_t tag) { struct bgp_misc_structs *bms = bgp_select_misc_db(FUNC_TYPE_SFLOW_COUNTER); int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = BGP_LOGDUMP_ET_NONE; (void)etype; if (!bms || !peer || !sample || !event_type) { skipBytes(sample, len); return ret; } if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP; else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG; #ifdef WITH_RABBITMQ if (config.sfacctd_counter_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif #ifdef WITH_KAFKA if (config.sfacctd_counter_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); /* no need for seq and timestamp for "dump" event_type */ if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t) bgp_peer_log_seq_get(&bms->log_seq))); bgp_peer_log_seq_increment(&bms->log_seq); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); } addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, "peer_ip_src", json_string(ip_address)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); json_object_set_new_nocheck(obj, "source_id_index", json_integer((json_int_t)sample->ds_index)); json_object_set_new_nocheck(obj, "sflow_seq", json_integer((json_int_t)sample->sequenceNo)); json_object_set_new_nocheck(obj, "sflow_cnt_seq", json_integer((json_int_t)sample->cntSequenceNo)); if (version == 5) { switch (tag) { case SFLCOUNTERS_GENERIC: readCounters_generic(peer, sample, "log", config.sfacctd_counter_output, obj); break; case SFLCOUNTERS_ETHERNET: readCounters_ethernet(peer, sample, "log", config.sfacctd_counter_output, obj); break; case SFLCOUNTERS_VLAN: readCounters_vlan(peer, sample, "log", config.sfacctd_counter_output, obj); break; default: skipBytes(sample, len); break; } } else if (version < 5) { switch (tag) { case INMCOUNTERSVERSION_GENERIC: case INMCOUNTERSVERSION_ETHERNET: readCounters_generic(peer, sample, "log", config.sfacctd_counter_output, obj); break; case INMCOUNTERSVERSION_VLAN: /* nothing here */ break; default: skipBytes(sample, len); break; } /* now see if there are any specific counter blocks to add */ switch (tag) { case INMCOUNTERSVERSION_GENERIC: /* nothing more */ break; case INMCOUNTERSVERSION_ETHERNET: readCounters_ethernet(peer, sample, "log", config.sfacctd_counter_output, obj); break; case INMCOUNTERSVERSION_VLAN: readCounters_vlan(peer, sample, "log", config.sfacctd_counter_output, obj); break; default: /* nothing more; already skipped */ break; } } else skipBytes(sample, len); if (config.sfacctd_counter_file && etype == BGP_LOGDUMP_ET_LOG) write_and_free_json(peer->log->fd, obj); #ifdef WITH_RABBITMQ if (config.sfacctd_counter_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) { amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (config.sfacctd_counter_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) { kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } else skipBytes(sample, len); return (ret | amqp_ret | kafka_ret); } int readCounters_generic(struct bgp_peer *peer, SFSample *sample, char *event_type, int output, void *vobj) { int ret = 0; #ifdef WITH_JANSSON char msg_type[] = "sflow_cnt_generic"; json_t *obj = (json_t *) vobj; /* parse sFlow first and foremost */ sample->ifCounters.ifIndex = getData32(sample); sample->ifCounters.ifType = getData32(sample); sample->ifCounters.ifSpeed = getData64(sample); sample->ifCounters.ifDirection = getData32(sample); sample->ifCounters.ifStatus = getData32(sample); // the generic counters always come first sample->ifCounters.ifInOctets = getData64(sample); sample->ifCounters.ifInUcastPkts = getData32(sample); sample->ifCounters.ifInMulticastPkts = getData32(sample); sample->ifCounters.ifInBroadcastPkts = getData32(sample); sample->ifCounters.ifInDiscards = getData32(sample); sample->ifCounters.ifInErrors = getData32(sample); sample->ifCounters.ifInUnknownProtos = getData32(sample); sample->ifCounters.ifOutOctets = getData64(sample); sample->ifCounters.ifOutUcastPkts = getData32(sample); sample->ifCounters.ifOutMulticastPkts = getData32(sample); sample->ifCounters.ifOutBroadcastPkts = getData32(sample); sample->ifCounters.ifOutDiscards = getData32(sample); sample->ifCounters.ifOutErrors = getData32(sample); sample->ifCounters.ifPromiscuousMode = getData32(sample); if (!peer || !sample || !vobj) return ret; json_object_set_new_nocheck(obj, "sf_cnt_type", json_string(msg_type)); json_object_set_new_nocheck(obj, "ifIndex", json_integer((json_int_t)sample->ifCounters.ifIndex)); json_object_set_new_nocheck(obj, "ifType", json_integer((json_int_t)sample->ifCounters.ifType)); json_object_set_new_nocheck(obj, "ifSpeed", json_integer((json_int_t)sample->ifCounters.ifSpeed)); json_object_set_new_nocheck(obj, "ifDirection", json_integer((json_int_t)sample->ifCounters.ifDirection)); json_object_set_new_nocheck(obj, "ifStatus", json_integer((json_int_t)sample->ifCounters.ifStatus)); json_object_set_new_nocheck(obj, "ifInOctets", json_integer((json_int_t)sample->ifCounters.ifInOctets)); json_object_set_new_nocheck(obj, "ifInUcastPkts", json_integer((json_int_t)sample->ifCounters.ifInUcastPkts)); json_object_set_new_nocheck(obj, "ifInMulticastPkts", json_integer((json_int_t)sample->ifCounters.ifInMulticastPkts)); json_object_set_new_nocheck(obj, "ifInBroadcastPkts", json_integer((json_int_t)sample->ifCounters.ifInBroadcastPkts)); json_object_set_new_nocheck(obj, "ifInDiscards", json_integer((json_int_t)sample->ifCounters.ifInDiscards)); json_object_set_new_nocheck(obj, "ifInErrors", json_integer((json_int_t)sample->ifCounters.ifInErrors)); json_object_set_new_nocheck(obj, "ifInUnknownProtos", json_integer((json_int_t)sample->ifCounters.ifInUnknownProtos)); json_object_set_new_nocheck(obj, "ifOutOctets", json_integer((json_int_t)sample->ifCounters.ifOutOctets)); json_object_set_new_nocheck(obj, "ifOutUcastPkts", json_integer((json_int_t)sample->ifCounters.ifOutUcastPkts)); json_object_set_new_nocheck(obj, "ifOutMulticastPkts", json_integer((json_int_t)sample->ifCounters.ifOutMulticastPkts)); json_object_set_new_nocheck(obj, "ifOutBroadcastPkts", json_integer((json_int_t)sample->ifCounters.ifOutBroadcastPkts)); json_object_set_new_nocheck(obj, "ifOutDiscards", json_integer((json_int_t)sample->ifCounters.ifOutDiscards)); json_object_set_new_nocheck(obj, "ifOutErrors", json_integer((json_int_t)sample->ifCounters.ifOutErrors)); json_object_set_new_nocheck(obj, "ifPromiscuousMode", json_integer((json_int_t)sample->ifCounters.ifPromiscuousMode)); #endif return ret; } int readCounters_ethernet(struct bgp_peer *peer, SFSample *sample, char *event_type, int output, void *vobj) { int ret = 0; #ifdef WITH_JANSSON char msg_type[] = "sflow_cnt_ethernet"; json_t *obj = (json_t *) vobj; u_int32_t m32_1, m32_2, m32_3, m32_4, m32_5; u_int32_t m32_6, m32_7, m32_8, m32_9, m32_10; u_int32_t m32_11, m32_12, m32_13; /* parse sFlow first and foremost */ m32_1 = getData32(sample); /* dot3StatsAlignmentErrors */ m32_2 = getData32(sample); /* dot3StatsFCSErrors */ m32_3 = getData32(sample); /* dot3StatsSingleCollisionFrames */ m32_4 = getData32(sample); /* dot3StatsMultipleCollisionFrames */ m32_5 = getData32(sample); /* dot3StatsSQETestErrors */ m32_6 = getData32(sample); /* dot3StatsDeferredTransmissions */ m32_7 = getData32(sample); /* dot3StatsLateCollisions */ m32_8 = getData32(sample); /* dot3StatsExcessiveCollisions */ m32_9 = getData32(sample); /* dot3StatsInternalMacTransmitErrors */ m32_10 = getData32(sample); /* dot3StatsCarrierSenseErrors */ m32_11 = getData32(sample); /* dot3StatsFrameTooLongs */ m32_12 = getData32(sample); /* dot3StatsInternalMacReceiveErrors */ m32_13 = getData32(sample); /* dot3StatsSymbolErrors */ if (!peer || !sample || !vobj) return ret; json_object_set_new_nocheck(obj, "sf_cnt_type", json_string(msg_type)); json_object_set_new_nocheck(obj, "dot3StatsAlignmentErrors", json_integer((json_int_t)m32_1)); json_object_set_new_nocheck(obj, "dot3StatsFCSErrors", json_integer((json_int_t)m32_2)); json_object_set_new_nocheck(obj, "dot3StatsSingleCollisionFrames", json_integer((json_int_t)m32_3)); json_object_set_new_nocheck(obj, "dot3StatsMultipleCollisionFrames", json_integer((json_int_t)m32_4)); json_object_set_new_nocheck(obj, "dot3StatsSQETestErrors", json_integer((json_int_t)m32_5)); json_object_set_new_nocheck(obj, "dot3StatsDeferredTransmissions", json_integer((json_int_t)m32_6)); json_object_set_new_nocheck(obj, "dot3StatsLateCollisions", json_integer((json_int_t)m32_7)); json_object_set_new_nocheck(obj, "dot3StatsExcessiveCollisions", json_integer((json_int_t)m32_8)); json_object_set_new_nocheck(obj, "dot3StatsInternalMacTransmitErrors", json_integer((json_int_t)m32_9)); json_object_set_new_nocheck(obj, "dot3StatsCarrierSenseErrors", json_integer((json_int_t)m32_10)); json_object_set_new_nocheck(obj, "dot3StatsFrameTooLongs", json_integer((json_int_t)m32_11)); json_object_set_new_nocheck(obj, "dot3StatsInternalMacReceiveErrors", json_integer((json_int_t)m32_12)); json_object_set_new_nocheck(obj, "dot3StatsSymbolErrors", json_integer((json_int_t)m32_13)); #endif return ret; } int readCounters_vlan(struct bgp_peer *peer, SFSample *sample, char *event_type, int output, void *vobj) { int ret = 0; #ifdef WITH_JANSSON char msg_type[] = "sflow_cnt_vlan"; json_t *obj = (json_t *) vobj; u_int64_t m64_1; u_int32_t m32_1, m32_2, m32_3, m32_4; /* parse sFlow first and foremost */ sample->in_vlan = getData32(sample); m64_1 = getData64(sample); /* octets */ m32_1 = getData32(sample); /* ucastPkts */ m32_2 = getData32(sample); /* multicastPkts */ m32_3 = getData32(sample); /* broadcastPkts */ m32_4 = getData32(sample); /* discards */ if (!peer || !sample || !vobj) return ret; json_object_set_new_nocheck(obj, "sf_cnt_type", json_string(msg_type)); json_object_set_new_nocheck(obj, "octets", json_integer((json_int_t)m64_1)); json_object_set_new_nocheck(obj, "ucastPkts", json_integer((json_int_t)m32_1)); json_object_set_new_nocheck(obj, "multicastPkts", json_integer((json_int_t)m32_2)); json_object_set_new_nocheck(obj, "broadcastPkts", json_integer((json_int_t)m32_3)); json_object_set_new_nocheck(obj, "discards", json_integer((json_int_t)m32_4)); json_object_set_new_nocheck(obj, "vlan", json_integer((json_int_t)sample->in_vlan)); #endif return ret; } #if defined WITH_RABBITMQ void sfacctd_counter_init_amqp_host() { p_amqp_init_host(&sfacctd_counter_amqp_host); if (!config.sfacctd_counter_amqp_user) config.sfacctd_counter_amqp_user = rabbitmq_user; if (!config.sfacctd_counter_amqp_passwd) config.sfacctd_counter_amqp_passwd = rabbitmq_pwd; if (!config.sfacctd_counter_amqp_exchange) config.sfacctd_counter_amqp_exchange = default_amqp_exchange; if (!config.sfacctd_counter_amqp_exchange_type) config.sfacctd_counter_amqp_exchange_type = default_amqp_exchange_type; if (!config.sfacctd_counter_amqp_host) config.sfacctd_counter_amqp_host = default_amqp_host; if (!config.sfacctd_counter_amqp_vhost) config.sfacctd_counter_amqp_vhost = default_amqp_vhost; if (!config.sfacctd_counter_amqp_retry) config.sfacctd_counter_amqp_retry = AMQP_DEFAULT_RETRY; p_amqp_set_user(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_user); p_amqp_set_passwd(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_passwd); p_amqp_set_exchange(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_exchange); p_amqp_set_exchange_type(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_exchange_type); p_amqp_set_host(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_host); p_amqp_set_vhost(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_vhost); p_amqp_set_persistent_msg(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_persistent_msg); p_amqp_set_frame_max(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_frame_max); p_amqp_set_content_type_json(&sfacctd_counter_amqp_host); p_amqp_set_heartbeat_interval(&sfacctd_counter_amqp_host, config.sfacctd_counter_amqp_heartbeat_interval); P_broker_timers_set_retry_interval(&sfacctd_counter_amqp_host.btimers, config.sfacctd_counter_amqp_retry); } #else void sfacctd_counter_init_amqp_host() { } #endif #if defined WITH_KAFKA int sfacctd_counter_init_kafka_host() { int ret; p_kafka_init_host(&sfacctd_counter_kafka_host, config.sfacctd_counter_kafka_config_file); ret = p_kafka_connect_to_produce(&sfacctd_counter_kafka_host); if (!config.sfacctd_counter_kafka_broker_host) config.sfacctd_counter_kafka_broker_host = default_kafka_broker_host; if (!config.sfacctd_counter_kafka_broker_port) config.sfacctd_counter_kafka_broker_port = default_kafka_broker_port; if (!config.sfacctd_counter_kafka_retry) config.sfacctd_counter_kafka_retry = PM_KAFKA_DEFAULT_RETRY; p_kafka_set_broker(&sfacctd_counter_kafka_host, config.sfacctd_counter_kafka_broker_host, config.sfacctd_counter_kafka_broker_port); p_kafka_set_topic(&sfacctd_counter_kafka_host, config.sfacctd_counter_kafka_topic); p_kafka_set_partition(&sfacctd_counter_kafka_host, config.sfacctd_counter_kafka_partition); p_kafka_set_key(&sfacctd_counter_kafka_host, config.sfacctd_counter_kafka_partition_key, config.sfacctd_counter_kafka_partition_keylen); p_kafka_set_content_type(&sfacctd_counter_kafka_host, PM_KAFKA_CNT_TYPE_STR); P_broker_timers_set_retry_interval(&sfacctd_counter_kafka_host.btimers, config.sfacctd_counter_kafka_retry); return ret; } #else int sfacctd_counter_init_kafka_host() { return ERR; } #endif void sf_cnt_link_misc_structs(struct bgp_misc_structs *bms) { #if defined WITH_RABBITMQ bms->msglog_amqp_host = &sfacctd_counter_amqp_host; #endif #if defined WITH_KAFKA bms->msglog_kafka_host = &sfacctd_counter_kafka_host; #endif bms->max_peers = config.sfacctd_counter_max_nodes; bms->msglog_file = config.sfacctd_counter_file; bms->msglog_amqp_routing_key = config.sfacctd_counter_amqp_routing_key; bms->msglog_kafka_topic = config.sfacctd_counter_kafka_topic; bms->peer_str = malloc(strlen("peer_src_ip") + 1); strcpy(bms->peer_str, "peer_src_ip"); bms->peer_port_str = NULL; /* dump not supported */ } /* XXX: unify decoding flow sample header, now done twice if DPI or custom primitives are enabled */ void sf_flow_sample_hdr_decode(SFSample *sample) { struct packet_ptrs *pptrs = &sample->hdr_ptrs; /* cleanups */ reset_index_pkt_ptrs(pptrs); pptrs->pkthdr = NULL; pptrs->packet_ptr = pptrs->mac_ptr = pptrs->vlan_ptr = pptrs->mpls_ptr = NULL; pptrs->iph_ptr = pptrs->tlh_ptr = pptrs->payload_ptr = NULL; pptrs->l3_proto = pptrs->l4_proto = FALSE; #if defined (WITH_NDPI) memset(&sample->ndpi_class, 0, sizeof(pm_class2_t)); #endif if (sample->header && sample->headerLen) { memset(&sample->hdr_pcap, 0, sizeof(struct pcap_pkthdr)); sample->hdr_pcap.caplen = sample->headerLen; pptrs->pkthdr = (struct pcap_pkthdr *) &sample->hdr_pcap; pptrs->packet_ptr = (u_char *) sample->header; if (sample->headerProtocol == SFLHEADER_ETHERNET_ISO8023) { eth_handler(&sample->hdr_pcap, pptrs); if (pptrs->iph_ptr) { if ((*pptrs->l3_handler)(pptrs)) { #if defined (WITH_NDPI) if (config.classifier_ndpi && pm_ndpi_wfl) { sample->ndpi_class = pm_ndpi_workflow_process_packet(pm_ndpi_wfl, pptrs); } #endif set_index_pkt_ptrs(pptrs); } } } } } #ifdef WITH_KAFKA void SF_init_kafka_host(void *kh) { struct p_kafka_host *kafka_host = kh; p_kafka_init_host(kafka_host, config.nfacctd_kafka_config_file); p_kafka_connect_to_consume(kafka_host); p_kafka_set_broker(kafka_host, config.nfacctd_kafka_broker_host, config.nfacctd_kafka_broker_port); p_kafka_set_topic(kafka_host, config.nfacctd_kafka_topic); p_kafka_set_content_type(kafka_host, PM_KAFKA_CNT_TYPE_BIN); p_kafka_manage_consumer(kafka_host, TRUE); } #endif #ifdef WITH_ZMQ void SF_init_zmq_host(void *zh, int *pipe_fd) { struct p_zmq_host *zmq_host = zh; char log_id[SHORTBUFLEN]; p_zmq_init_pull(zmq_host); snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_zmq_set_log_id(zmq_host, log_id); p_zmq_set_address(zmq_host, config.nfacctd_zmq_address); p_zmq_set_hwm(zmq_host, PM_ZMQ_DEFAULT_FLOW_HWM); p_zmq_pull_setup(zmq_host); p_zmq_set_retry_timeout(zmq_host, PM_ZMQ_DEFAULT_RETRY); if (pipe_fd) (*pipe_fd) = p_zmq_get_fd(zmq_host); } #endif pmacct-1.7.8/src/memory.c0000644000175000017500000001055614354105275014264 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "imt_plugin.h" /* rules: first pool descriptor id is 1 */ /* functions */ void init_memory_pool_table() { if (config.num_memory_pools) { mpd = (unsigned char *) map_shared(0, (config.num_memory_pools+1)*sizeof(struct memory_pool_desc), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); memset(mpd, 0, (config.num_memory_pools+1)*sizeof(struct memory_pool_desc)); } else { mpd = (unsigned char *) map_shared(0, (NUM_MEMORY_POOLS+1)*sizeof(struct memory_pool_desc), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); memset(mpd, 0, (NUM_MEMORY_POOLS+1)*sizeof(struct memory_pool_desc)); } current_pool = (struct memory_pool_desc *) mpd; } void clear_memory_pool_table() { struct memory_pool_desc *pool_ptr; pool_ptr = (struct memory_pool_desc *) mpd; while (pool_ptr->next) { memset(pool_ptr->base_ptr, 0, pool_ptr->len); pool_ptr->id = 0; pool_ptr = pool_ptr->next; } /* clearing last memory pool and rewinding stuff */ memset(pool_ptr->base_ptr, 0, pool_ptr->len); current_pool = (struct memory_pool_desc *) mpd; } struct memory_pool_desc *request_memory_pool(int size) { int new_id; unsigned char *memptr; struct memory_pool_desc *new_pool; /* trying to find resource already allocated but currently unused */ if (current_pool->next) { if (!current_pool->id) { new_pool = current_pool; new_pool->id = 1; } else { new_pool = current_pool->next; new_pool->id = current_pool->id+1; } if (size <= new_pool->len) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): using an already allocated memory segment.\n", config.name, config.type); memset(new_pool->base_ptr, 0, size); new_pool->ptr = new_pool->base_ptr; new_pool->space_left = size; return new_pool; } } /* we didn't find allocated resources; requesting new news and registering them in memory pool descriptors table */ new_id = current_pool->id+1; Log(LOG_DEBUG, "DEBUG ( %s/%s ): allocating a new memory segment.\n", config.name, config.type); if (config.num_memory_pools) { if (new_id > config.num_memory_pools) return NULL; new_pool = (struct memory_pool_desc *) mpd+(new_id-1); } else { if (new_id > NUM_MEMORY_POOLS) { /* XXX: this malloc() is a quick workaround because of some mallopt() SEGV when trying to allocate chuncks < 1024; i'm not figuring out where is the *real* problem. First experienced with: gcc version 3.3.3 (Debian 20040320) / glibc 2.3.2 */ // new_pool = (struct memory_pool_desc *) malloc(sizeof(struct memory_pool_desc)); new_pool = (struct memory_pool_desc *) map_shared(0, 1024, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (new_pool == MAP_FAILED) return NULL; memset(new_pool, 0, sizeof(struct memory_pool_desc)); } else new_pool = (struct memory_pool_desc *) mpd+(new_id-1); } if (current_pool->id) current_pool->next = new_pool; /* We found a free room in mpd table; now we have allocate needed memory */ memptr = (unsigned char *) map_shared(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (memptr == MAP_FAILED) { Log(LOG_WARNING, "WARN ( %s/%s ): memory sold out ! Please, clear in-memory stats !\n", config.name, config.type); return NULL; } memset(memptr, 0, size); new_pool->id = new_id; new_pool->base_ptr = memptr; new_pool->ptr = memptr; new_pool->space_left = size; new_pool->len = size; return new_pool; } pmacct-1.7.8/src/preprocess-data.h0000644000175000017500000000242714354105275016053 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static const struct _preprocess_dictionary_line sql_prep_dict[] = { {"qnum"}, {"minp"}, {"minf"}, {"minb"}, {"maxp"}, {"maxf"}, {"maxb"}, {"minbpp"}, {"minppf"}, {"maxbpp"}, {"maxppf"}, {"fss"}, {"fsrc"}, {"usrf"}, {"adjb"}, {"recover"}, {""} }; static const struct _preprocess_dictionary_line print_prep_dict[] = { {"minp"}, {"minf"}, {"minb"}, {"maxp"}, {"maxf"}, {"maxb"}, {"minbpp"}, {"minppf"}, {""} }; pmacct-1.7.8/src/pmtelemetryd.h0000644000175000017500000000203114354105275015461 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PMTELEMETRYD_H #define PMTELEMETRYD_H /* includes */ /* defines */ /* prototypes */ extern void usage_daemon(char *); extern void compute_once(); /* global variables */ #endif //PMTELEMETRYD_H pmacct-1.7.8/src/Makefile.in0000644000175000017500000033675214354105415014662 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_EXTERNAL_DEPS_TRUE@am__append_1 = external_libs sbin_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ $(am__EXEEXT_5) $(am__EXEEXT_6) bin_PROGRAMS = $(am__EXEEXT_1) EXTRA_PROGRAMS = @WITH_JANSSON_TRUE@am__append_2 = @JANSSON_LIBS@ @WITH_AVRO_TRUE@am__append_3 = @AVRO_LIBS@ @WITH_MYSQL_TRUE@am__append_4 = mysql_plugin.c @WITH_MYSQL_TRUE@am__append_5 = @MYSQL_LIBS@ @WITH_MYSQL_TRUE@am__append_6 = @MYSQL_CFLAGS@ @WITH_PGSQL_TRUE@am__append_7 = pgsql_plugin.c @WITH_PGSQL_TRUE@am__append_8 = @PGSQL_LIBS@ @WITH_PGSQL_TRUE@am__append_9 = @PGSQL_CFLAGS@ @WITH_MONGODB_TRUE@am__append_10 = mongodb_plugin.c @WITH_MONGODB_TRUE@am__append_11 = @MONGODB_LIBS@ @WITH_MONGODB_TRUE@am__append_12 = @MONGODB_CFLAGS@ @WITH_SQLITE3_TRUE@am__append_13 = sqlite3_plugin.c @WITH_SQLITE3_TRUE@am__append_14 = @SQLITE3_LIBS@ @WITH_SQLITE3_TRUE@am__append_15 = @SQLITE3_CFLAGS@ @WITH_JANSSON_TRUE@am__append_16 = plugin_cmn_json.c @WITH_JANSSON_TRUE@am__append_17 = @JANSSON_LIBS@ @WITH_JANSSON_TRUE@am__append_18 = @JANSSON_CFLAGS@ @WITH_AVRO_TRUE@am__append_19 = plugin_cmn_avro.c @WITH_AVRO_TRUE@am__append_20 = @AVRO_LIBS@ @WITH_AVRO_TRUE@am__append_21 = @AVRO_CFLAGS@ @WITH_AVRO_TRUE@@WITH_SERDES_TRUE@am__append_22 = @SERDES_LIBS@ @WITH_AVRO_TRUE@@WITH_SERDES_TRUE@am__append_23 = @SERDES_CFLAGS@ @WITH_NDPI_TRUE@am__append_24 = ndpi @WITH_NDPI_TRUE@am__append_25 = ndpi/libndpi_support.la @NDPI_LIBS@ @WITH_NDPI_TRUE@am__append_26 = @NDPI_CFLAGS@ @WITH_RABBITMQ_TRUE@am__append_27 = amqp_common.c amqp_plugin.c @WITH_RABBITMQ_TRUE@am__append_28 = @RABBITMQ_LIBS@ @WITH_RABBITMQ_TRUE@am__append_29 = @RABBITMQ_CFLAGS@ @WITH_ZMQ_TRUE@am__append_30 = zmq_common.c @WITH_ZMQ_TRUE@am__append_31 = @ZMQ_LIBS@ @WITH_ZMQ_TRUE@am__append_32 = @ZMQ_CFLAGS@ @WITH_KAFKA_TRUE@am__append_33 = kafka_common.c kafka_plugin.c @WITH_KAFKA_TRUE@am__append_34 = @KAFKA_LIBS@ @WITH_KAFKA_TRUE@am__append_35 = @KAFKA_CFLAGS@ @USING_SQL_TRUE@am__append_36 = sql_common.c sql_handlers.c sql_common_m.c @USING_SQL_TRUE@am__append_37 = -Wno-error=pointer-sign @USING_SQL_TRUE@am__append_38 = -lm -lz @WITH_REDIS_TRUE@am__append_39 = redis_common.c @WITH_REDIS_TRUE@am__append_40 = @REDIS_LIBS@ @WITH_REDIS_TRUE@am__append_41 = @REDIS_CFLAGS@ @WITH_GNUTLS_TRUE@am__append_42 = @GNUTLS_LIBS@ @WITH_GNUTLS_TRUE@am__append_43 = @GNUTLS_CFLAGS@ @WITH_UNYTE_UDP_NOTIF_TRUE@am__append_44 = @UNYTE_UDP_NOTIF_LIBS@ @WITH_UNYTE_UDP_NOTIF_TRUE@am__append_45 = @UNYTE_UDP_NOTIF_CFLAGS@ @WITH_EBPF_TRUE@am__append_46 = @EBPF_LIBS@ @WITH_EBPF_TRUE@am__append_47 = @EBPF_CFLAGS@ @USING_TRAFFIC_BINS_TRUE@am__append_48 = pmacctd nfacctd sfacctd @USING_TRAFFIC_BINS_TRUE@am__append_49 = pmacct @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@am__append_50 = uacctd @USING_ST_BINS_TRUE@am__append_51 = pmtelemetryd @USING_BGP_BINS_TRUE@am__append_52 = pmbgpd @USING_BMP_BINS_TRUE@am__append_53 = pmbmpd subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = pmacct-version.h CONFIG_CLEAN_VPATH_FILES = @USING_TRAFFIC_BINS_TRUE@am__EXEEXT_1 = pmacct$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" @USING_TRAFFIC_BINS_TRUE@am__EXEEXT_2 = pmacctd$(EXEEXT) \ @USING_TRAFFIC_BINS_TRUE@ nfacctd$(EXEEXT) sfacctd$(EXEEXT) @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@am__EXEEXT_3 = \ @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@ uacctd$(EXEEXT) @USING_ST_BINS_TRUE@am__EXEEXT_4 = pmtelemetryd$(EXEEXT) @USING_BGP_BINS_TRUE@am__EXEEXT_5 = pmbgpd$(EXEEXT) @USING_BMP_BINS_TRUE@am__EXEEXT_6 = pmbmpd$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) LTLIBRARIES = $(noinst_LTLIBRARIES) libcommon_la_DEPENDENCIES = am_libcommon_la_OBJECTS = libcommon_la-strlcpy.lo libcommon_la-addr.lo libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libcommon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcommon_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = @WITH_NDPI_TRUE@am__DEPENDENCIES_2 = ndpi/libndpi_support.la libdaemons_la_DEPENDENCIES = nfprobe_plugin/libnfprobe_plugin.la \ sfprobe_plugin/libsfprobe_plugin.la bmp/libpmbmp.la \ bgp/libpmbgp.la rpki/libpmrpki.la filters/libpmfilters.la \ tee_plugin/libtee_plugin.la isis/libpmisis.la \ telemetry/libpmtelemetry.la ebpf/libpmebpf.la libcommon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__libdaemons_la_SOURCES_DIST = signals.c util.c plugin_hooks.c \ server.c acct.c memory.c cfg.c imt_plugin.c log.c \ pkt_handlers.c cfg_handlers.c net_aggr.c print_plugin.c \ pretag.c ip_frag.c pretag_handlers.c ip_flow.c setproctitle.c \ classifier.c conntrack.c xflow_status.c plugin_common.c \ preprocess.c ll.c nl.c base64.c pmsearch.c linklist.c \ thread_pool.c plugin_cmn_custom.c network.c pmacct-globals.c \ mysql_plugin.c pgsql_plugin.c mongodb_plugin.c \ sqlite3_plugin.c plugin_cmn_json.c plugin_cmn_avro.c \ amqp_common.c amqp_plugin.c zmq_common.c kafka_common.c \ kafka_plugin.c sql_common.c sql_handlers.c sql_common_m.c \ redis_common.c @WITH_MYSQL_TRUE@am__objects_1 = libdaemons_la-mysql_plugin.lo @WITH_PGSQL_TRUE@am__objects_2 = libdaemons_la-pgsql_plugin.lo @WITH_MONGODB_TRUE@am__objects_3 = libdaemons_la-mongodb_plugin.lo @WITH_SQLITE3_TRUE@am__objects_4 = libdaemons_la-sqlite3_plugin.lo @WITH_JANSSON_TRUE@am__objects_5 = libdaemons_la-plugin_cmn_json.lo @WITH_AVRO_TRUE@am__objects_6 = libdaemons_la-plugin_cmn_avro.lo @WITH_RABBITMQ_TRUE@am__objects_7 = libdaemons_la-amqp_common.lo \ @WITH_RABBITMQ_TRUE@ libdaemons_la-amqp_plugin.lo @WITH_ZMQ_TRUE@am__objects_8 = libdaemons_la-zmq_common.lo @WITH_KAFKA_TRUE@am__objects_9 = libdaemons_la-kafka_common.lo \ @WITH_KAFKA_TRUE@ libdaemons_la-kafka_plugin.lo @USING_SQL_TRUE@am__objects_10 = libdaemons_la-sql_common.lo \ @USING_SQL_TRUE@ libdaemons_la-sql_handlers.lo \ @USING_SQL_TRUE@ libdaemons_la-sql_common_m.lo @WITH_REDIS_TRUE@am__objects_11 = libdaemons_la-redis_common.lo am_libdaemons_la_OBJECTS = libdaemons_la-signals.lo \ libdaemons_la-util.lo libdaemons_la-plugin_hooks.lo \ libdaemons_la-server.lo libdaemons_la-acct.lo \ libdaemons_la-memory.lo libdaemons_la-cfg.lo \ libdaemons_la-imt_plugin.lo libdaemons_la-log.lo \ libdaemons_la-pkt_handlers.lo libdaemons_la-cfg_handlers.lo \ libdaemons_la-net_aggr.lo libdaemons_la-print_plugin.lo \ libdaemons_la-pretag.lo libdaemons_la-ip_frag.lo \ libdaemons_la-pretag_handlers.lo libdaemons_la-ip_flow.lo \ libdaemons_la-setproctitle.lo libdaemons_la-classifier.lo \ libdaemons_la-conntrack.lo libdaemons_la-xflow_status.lo \ libdaemons_la-plugin_common.lo libdaemons_la-preprocess.lo \ libdaemons_la-ll.lo libdaemons_la-nl.lo \ libdaemons_la-base64.lo libdaemons_la-pmsearch.lo \ libdaemons_la-linklist.lo libdaemons_la-thread_pool.lo \ libdaemons_la-plugin_cmn_custom.lo libdaemons_la-network.lo \ libdaemons_la-pmacct-globals.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) libdaemons_la_OBJECTS = $(am_libdaemons_la_OBJECTS) libdaemons_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libdaemons_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__nfacctd_SOURCES_DIST = nfacctd.c nfv9_template.c @USING_TRAFFIC_BINS_TRUE@am_nfacctd_OBJECTS = nfacctd.$(OBJEXT) \ @USING_TRAFFIC_BINS_TRUE@ nfv9_template.$(OBJEXT) nfacctd_OBJECTS = $(am_nfacctd_OBJECTS) @USING_TRAFFIC_BINS_TRUE@nfacctd_DEPENDENCIES = libdaemons.la am__pmacct_SOURCES_DIST = pmacct.c @USING_TRAFFIC_BINS_TRUE@am_pmacct_OBJECTS = pmacct.$(OBJEXT) pmacct_OBJECTS = $(am_pmacct_OBJECTS) @USING_TRAFFIC_BINS_TRUE@pmacct_DEPENDENCIES = libcommon.la \ @USING_TRAFFIC_BINS_TRUE@ libdaemons.la am__pmacctd_SOURCES_DIST = pmacctd.c @USING_TRAFFIC_BINS_TRUE@am_pmacctd_OBJECTS = pmacctd.$(OBJEXT) pmacctd_OBJECTS = $(am_pmacctd_OBJECTS) @USING_TRAFFIC_BINS_TRUE@pmacctd_DEPENDENCIES = libdaemons.la am__pmbgpd_SOURCES_DIST = pmbgpd.c @USING_BGP_BINS_TRUE@am_pmbgpd_OBJECTS = pmbgpd.$(OBJEXT) pmbgpd_OBJECTS = $(am_pmbgpd_OBJECTS) @USING_BGP_BINS_TRUE@pmbgpd_DEPENDENCIES = libdaemons.la pmbgpd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmbgpd_LDFLAGS) $(LDFLAGS) -o $@ am__pmbmpd_SOURCES_DIST = pmbmpd.c @USING_BMP_BINS_TRUE@am_pmbmpd_OBJECTS = pmbmpd.$(OBJEXT) pmbmpd_OBJECTS = $(am_pmbmpd_OBJECTS) @USING_BMP_BINS_TRUE@pmbmpd_DEPENDENCIES = libdaemons.la pmbmpd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmbmpd_LDFLAGS) $(LDFLAGS) -o $@ am__pmtelemetryd_SOURCES_DIST = pmtelemetryd.c @USING_ST_BINS_TRUE@am_pmtelemetryd_OBJECTS = pmtelemetryd.$(OBJEXT) pmtelemetryd_OBJECTS = $(am_pmtelemetryd_OBJECTS) @USING_ST_BINS_TRUE@pmtelemetryd_DEPENDENCIES = libdaemons.la pmtelemetryd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmtelemetryd_LDFLAGS) $(LDFLAGS) -o $@ am__sfacctd_SOURCES_DIST = sfacctd.c sflow.c sfv5_module.c @USING_TRAFFIC_BINS_TRUE@am_sfacctd_OBJECTS = sfacctd.$(OBJEXT) \ @USING_TRAFFIC_BINS_TRUE@ sflow.$(OBJEXT) sfv5_module.$(OBJEXT) sfacctd_OBJECTS = $(am_sfacctd_OBJECTS) @USING_TRAFFIC_BINS_TRUE@sfacctd_DEPENDENCIES = libdaemons.la am__uacctd_SOURCES_DIST = uacctd.c @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@am_uacctd_OBJECTS = uacctd-uacctd.$(OBJEXT) uacctd_OBJECTS = $(am_uacctd_OBJECTS) @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@uacctd_DEPENDENCIES = \ @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@ libdaemons.la uacctd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(uacctd_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libcommon_la-addr.Plo \ ./$(DEPDIR)/libcommon_la-strlcpy.Plo \ ./$(DEPDIR)/libdaemons_la-acct.Plo \ ./$(DEPDIR)/libdaemons_la-amqp_common.Plo \ ./$(DEPDIR)/libdaemons_la-amqp_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-base64.Plo \ ./$(DEPDIR)/libdaemons_la-cfg.Plo \ ./$(DEPDIR)/libdaemons_la-cfg_handlers.Plo \ ./$(DEPDIR)/libdaemons_la-classifier.Plo \ ./$(DEPDIR)/libdaemons_la-conntrack.Plo \ ./$(DEPDIR)/libdaemons_la-imt_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-ip_flow.Plo \ ./$(DEPDIR)/libdaemons_la-ip_frag.Plo \ ./$(DEPDIR)/libdaemons_la-kafka_common.Plo \ ./$(DEPDIR)/libdaemons_la-kafka_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-linklist.Plo \ ./$(DEPDIR)/libdaemons_la-ll.Plo \ ./$(DEPDIR)/libdaemons_la-log.Plo \ ./$(DEPDIR)/libdaemons_la-memory.Plo \ ./$(DEPDIR)/libdaemons_la-mongodb_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-mysql_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-net_aggr.Plo \ ./$(DEPDIR)/libdaemons_la-network.Plo \ ./$(DEPDIR)/libdaemons_la-nl.Plo \ ./$(DEPDIR)/libdaemons_la-pgsql_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-pkt_handlers.Plo \ ./$(DEPDIR)/libdaemons_la-plugin_cmn_avro.Plo \ ./$(DEPDIR)/libdaemons_la-plugin_cmn_custom.Plo \ ./$(DEPDIR)/libdaemons_la-plugin_cmn_json.Plo \ ./$(DEPDIR)/libdaemons_la-plugin_common.Plo \ ./$(DEPDIR)/libdaemons_la-plugin_hooks.Plo \ ./$(DEPDIR)/libdaemons_la-pmacct-globals.Plo \ ./$(DEPDIR)/libdaemons_la-pmsearch.Plo \ ./$(DEPDIR)/libdaemons_la-preprocess.Plo \ ./$(DEPDIR)/libdaemons_la-pretag.Plo \ ./$(DEPDIR)/libdaemons_la-pretag_handlers.Plo \ ./$(DEPDIR)/libdaemons_la-print_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-redis_common.Plo \ ./$(DEPDIR)/libdaemons_la-server.Plo \ ./$(DEPDIR)/libdaemons_la-setproctitle.Plo \ ./$(DEPDIR)/libdaemons_la-signals.Plo \ ./$(DEPDIR)/libdaemons_la-sql_common.Plo \ ./$(DEPDIR)/libdaemons_la-sql_common_m.Plo \ ./$(DEPDIR)/libdaemons_la-sql_handlers.Plo \ ./$(DEPDIR)/libdaemons_la-sqlite3_plugin.Plo \ ./$(DEPDIR)/libdaemons_la-thread_pool.Plo \ ./$(DEPDIR)/libdaemons_la-util.Plo \ ./$(DEPDIR)/libdaemons_la-xflow_status.Plo \ ./$(DEPDIR)/libdaemons_la-zmq_common.Plo \ ./$(DEPDIR)/nfacctd.Po ./$(DEPDIR)/nfv9_template.Po \ ./$(DEPDIR)/pmacct.Po ./$(DEPDIR)/pmacctd.Po \ ./$(DEPDIR)/pmbgpd.Po ./$(DEPDIR)/pmbmpd.Po \ ./$(DEPDIR)/pmtelemetryd.Po ./$(DEPDIR)/sfacctd.Po \ ./$(DEPDIR)/sflow.Po ./$(DEPDIR)/sfv5_module.Po \ ./$(DEPDIR)/uacctd-uacctd.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcommon_la_SOURCES) $(libdaemons_la_SOURCES) \ $(nfacctd_SOURCES) $(pmacct_SOURCES) $(pmacctd_SOURCES) \ $(pmbgpd_SOURCES) $(pmbmpd_SOURCES) $(pmtelemetryd_SOURCES) \ $(sfacctd_SOURCES) $(uacctd_SOURCES) DIST_SOURCES = $(libcommon_la_SOURCES) \ $(am__libdaemons_la_SOURCES_DIST) $(am__nfacctd_SOURCES_DIST) \ $(am__pmacct_SOURCES_DIST) $(am__pmacctd_SOURCES_DIST) \ $(am__pmbgpd_SOURCES_DIST) $(am__pmbmpd_SOURCES_DIST) \ $(am__pmtelemetryd_SOURCES_DIST) $(am__sfacctd_SOURCES_DIST) \ $(am__uacctd_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = external_libs nfprobe_plugin sfprobe_plugin bgp \ tee_plugin isis bmp telemetry rpki filters ebpf ndpi am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/pmacct-version.h.in \ $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = $(am__append_1) nfprobe_plugin sfprobe_plugin bgp tee_plugin \ isis bmp telemetry rpki filters ebpf $(am__append_24) AM_LDFLAGS = @GEOIP_LIBS@ @GEOIPV2_LIBS@ $(am__append_2) \ $(am__append_3) AM_CFLAGS = $(PMACCT_CFLAGS) #Build string autogen BUILT_SOURCES = pmacct-build.h_h .PHONY = pmacct-build.h noinst_LTLIBRARIES = libdaemons.la libcommon.la libcommon_la_SOURCES = strlcpy.c addr.c libdaemons_la_SOURCES = signals.c util.c plugin_hooks.c server.c \ acct.c memory.c cfg.c imt_plugin.c log.c pkt_handlers.c \ cfg_handlers.c net_aggr.c print_plugin.c pretag.c ip_frag.c \ pretag_handlers.c ip_flow.c setproctitle.c classifier.c \ conntrack.c xflow_status.c plugin_common.c preprocess.c ll.c \ nl.c base64.c pmsearch.c linklist.c thread_pool.c \ plugin_cmn_custom.c network.c pmacct-globals.c $(am__append_4) \ $(am__append_7) $(am__append_10) $(am__append_13) \ $(am__append_16) $(am__append_19) $(am__append_27) \ $(am__append_30) $(am__append_33) $(am__append_36) \ $(am__append_39) libcommon_la_LIBADD = libcommon_la_CFLAGS = $(AM_CFLAGS) # Builtin plugins libdaemons_la_LIBADD = nfprobe_plugin/libnfprobe_plugin.la \ sfprobe_plugin/libsfprobe_plugin.la bmp/libpmbmp.la \ bgp/libpmbgp.la rpki/libpmrpki.la filters/libpmfilters.la \ tee_plugin/libtee_plugin.la isis/libpmisis.la \ telemetry/libpmtelemetry.la ebpf/libpmebpf.la libcommon.la \ $(am__append_5) $(am__append_8) $(am__append_11) \ $(am__append_14) $(am__append_17) $(am__append_20) \ $(am__append_22) $(am__append_25) $(am__append_28) \ $(am__append_31) $(am__append_34) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_46) libdaemons_la_CFLAGS = $(AM_CFLAGS) $(am__append_6) $(am__append_9) \ $(am__append_12) $(am__append_15) $(am__append_18) \ $(am__append_21) $(am__append_23) $(am__append_26) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_37) $(am__append_41) $(am__append_43) \ $(am__append_45) $(am__append_47) @USING_TRAFFIC_BINS_TRUE@pmacctd_SOURCES = pmacctd.c @USING_TRAFFIC_BINS_TRUE@pmacctd_LDADD = libdaemons.la @USING_TRAFFIC_BINS_TRUE@nfacctd_SOURCES = nfacctd.c nfv9_template.c @USING_TRAFFIC_BINS_TRUE@nfacctd_LDADD = libdaemons.la @USING_TRAFFIC_BINS_TRUE@sfacctd_SOURCES = sfacctd.c sflow.c sfv5_module.c @USING_TRAFFIC_BINS_TRUE@sfacctd_LDADD = libdaemons.la @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@uacctd_SOURCES = uacctd.c @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@uacctd_CFLAGS = $(AM_CFLAGS) @NFLOG_CFLAGS@ -Wno-error=pointer-sign @USING_TRAFFIC_BINS_TRUE@@WITH_NFLOG_TRUE@uacctd_LDADD = libdaemons.la @NFLOG_LIBS@ @USING_TRAFFIC_BINS_TRUE@pmacct_SOURCES = pmacct.c @USING_TRAFFIC_BINS_TRUE@pmacct_LDADD = libcommon.la libdaemons.la @USING_ST_BINS_TRUE@pmtelemetryd_SOURCES = pmtelemetryd.c @USING_ST_BINS_TRUE@pmtelemetryd_LDFLAGS = $(DEFS) @USING_ST_BINS_TRUE@pmtelemetryd_LDADD = libdaemons.la @USING_BGP_BINS_TRUE@pmbgpd_SOURCES = pmbgpd.c @USING_BGP_BINS_TRUE@pmbgpd_LDFLAGS = $(DEFS) @USING_BGP_BINS_TRUE@pmbgpd_LDADD = libdaemons.la @USING_BMP_BINS_TRUE@pmbmpd_SOURCES = pmbmpd.c @USING_BMP_BINS_TRUE@pmbmpd_LDFLAGS = $(DEFS) @USING_BMP_BINS_TRUE@pmbmpd_LDADD = libdaemons.la all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): pmacct-version.h: $(top_builddir)/config.status $(srcdir)/pmacct-version.h.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES) $(AM_V_CCLD)$(libcommon_la_LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) libdaemons.la: $(libdaemons_la_OBJECTS) $(libdaemons_la_DEPENDENCIES) $(EXTRA_libdaemons_la_DEPENDENCIES) $(AM_V_CCLD)$(libdaemons_la_LINK) $(libdaemons_la_OBJECTS) $(libdaemons_la_LIBADD) $(LIBS) nfacctd$(EXEEXT): $(nfacctd_OBJECTS) $(nfacctd_DEPENDENCIES) $(EXTRA_nfacctd_DEPENDENCIES) @rm -f nfacctd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(nfacctd_OBJECTS) $(nfacctd_LDADD) $(LIBS) pmacct$(EXEEXT): $(pmacct_OBJECTS) $(pmacct_DEPENDENCIES) $(EXTRA_pmacct_DEPENDENCIES) @rm -f pmacct$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pmacct_OBJECTS) $(pmacct_LDADD) $(LIBS) pmacctd$(EXEEXT): $(pmacctd_OBJECTS) $(pmacctd_DEPENDENCIES) $(EXTRA_pmacctd_DEPENDENCIES) @rm -f pmacctd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pmacctd_OBJECTS) $(pmacctd_LDADD) $(LIBS) pmbgpd$(EXEEXT): $(pmbgpd_OBJECTS) $(pmbgpd_DEPENDENCIES) $(EXTRA_pmbgpd_DEPENDENCIES) @rm -f pmbgpd$(EXEEXT) $(AM_V_CCLD)$(pmbgpd_LINK) $(pmbgpd_OBJECTS) $(pmbgpd_LDADD) $(LIBS) pmbmpd$(EXEEXT): $(pmbmpd_OBJECTS) $(pmbmpd_DEPENDENCIES) $(EXTRA_pmbmpd_DEPENDENCIES) @rm -f pmbmpd$(EXEEXT) $(AM_V_CCLD)$(pmbmpd_LINK) $(pmbmpd_OBJECTS) $(pmbmpd_LDADD) $(LIBS) pmtelemetryd$(EXEEXT): $(pmtelemetryd_OBJECTS) $(pmtelemetryd_DEPENDENCIES) $(EXTRA_pmtelemetryd_DEPENDENCIES) @rm -f pmtelemetryd$(EXEEXT) $(AM_V_CCLD)$(pmtelemetryd_LINK) $(pmtelemetryd_OBJECTS) $(pmtelemetryd_LDADD) $(LIBS) sfacctd$(EXEEXT): $(sfacctd_OBJECTS) $(sfacctd_DEPENDENCIES) $(EXTRA_sfacctd_DEPENDENCIES) @rm -f sfacctd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sfacctd_OBJECTS) $(sfacctd_LDADD) $(LIBS) uacctd$(EXEEXT): $(uacctd_OBJECTS) $(uacctd_DEPENDENCIES) $(EXTRA_uacctd_DEPENDENCIES) @rm -f uacctd$(EXEEXT) $(AM_V_CCLD)$(uacctd_LINK) $(uacctd_OBJECTS) $(uacctd_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-addr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-strlcpy.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-acct.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-amqp_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-amqp_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-base64.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-cfg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-cfg_handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-classifier.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-conntrack.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-imt_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-ip_flow.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-ip_frag.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-kafka_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-kafka_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-linklist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-ll.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-log.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-memory.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-mongodb_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-mysql_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-net_aggr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-network.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-nl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pgsql_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pkt_handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-plugin_cmn_avro.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-plugin_cmn_custom.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-plugin_cmn_json.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-plugin_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-plugin_hooks.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pmacct-globals.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pmsearch.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-preprocess.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pretag.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-pretag_handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-print_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-redis_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-server.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-setproctitle.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-signals.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-sql_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-sql_common_m.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-sql_handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-sqlite3_plugin.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-thread_pool.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-util.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-xflow_status.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdaemons_la-zmq_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfacctd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfv9_template.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmacct.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmacctd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmbgpd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmbmpd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmtelemetryd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sfacctd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sflow.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sfv5_module.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uacctd-uacctd.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libcommon_la-strlcpy.lo: strlcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-strlcpy.lo -MD -MP -MF $(DEPDIR)/libcommon_la-strlcpy.Tpo -c -o libcommon_la-strlcpy.lo `test -f 'strlcpy.c' || echo '$(srcdir)/'`strlcpy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_la-strlcpy.Tpo $(DEPDIR)/libcommon_la-strlcpy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strlcpy.c' object='libcommon_la-strlcpy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-strlcpy.lo `test -f 'strlcpy.c' || echo '$(srcdir)/'`strlcpy.c libcommon_la-addr.lo: addr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-addr.lo -MD -MP -MF $(DEPDIR)/libcommon_la-addr.Tpo -c -o libcommon_la-addr.lo `test -f 'addr.c' || echo '$(srcdir)/'`addr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_la-addr.Tpo $(DEPDIR)/libcommon_la-addr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='addr.c' object='libcommon_la-addr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-addr.lo `test -f 'addr.c' || echo '$(srcdir)/'`addr.c libdaemons_la-signals.lo: signals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-signals.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-signals.Tpo -c -o libdaemons_la-signals.lo `test -f 'signals.c' || echo '$(srcdir)/'`signals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-signals.Tpo $(DEPDIR)/libdaemons_la-signals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='signals.c' object='libdaemons_la-signals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-signals.lo `test -f 'signals.c' || echo '$(srcdir)/'`signals.c libdaemons_la-util.lo: util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-util.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-util.Tpo -c -o libdaemons_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-util.Tpo $(DEPDIR)/libdaemons_la-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='libdaemons_la-util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c libdaemons_la-plugin_hooks.lo: plugin_hooks.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-plugin_hooks.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-plugin_hooks.Tpo -c -o libdaemons_la-plugin_hooks.lo `test -f 'plugin_hooks.c' || echo '$(srcdir)/'`plugin_hooks.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-plugin_hooks.Tpo $(DEPDIR)/libdaemons_la-plugin_hooks.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_hooks.c' object='libdaemons_la-plugin_hooks.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-plugin_hooks.lo `test -f 'plugin_hooks.c' || echo '$(srcdir)/'`plugin_hooks.c libdaemons_la-server.lo: server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-server.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-server.Tpo -c -o libdaemons_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-server.Tpo $(DEPDIR)/libdaemons_la-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='libdaemons_la-server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c libdaemons_la-acct.lo: acct.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-acct.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-acct.Tpo -c -o libdaemons_la-acct.lo `test -f 'acct.c' || echo '$(srcdir)/'`acct.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-acct.Tpo $(DEPDIR)/libdaemons_la-acct.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acct.c' object='libdaemons_la-acct.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-acct.lo `test -f 'acct.c' || echo '$(srcdir)/'`acct.c libdaemons_la-memory.lo: memory.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-memory.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-memory.Tpo -c -o libdaemons_la-memory.lo `test -f 'memory.c' || echo '$(srcdir)/'`memory.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-memory.Tpo $(DEPDIR)/libdaemons_la-memory.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='memory.c' object='libdaemons_la-memory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-memory.lo `test -f 'memory.c' || echo '$(srcdir)/'`memory.c libdaemons_la-cfg.lo: cfg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-cfg.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-cfg.Tpo -c -o libdaemons_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-cfg.Tpo $(DEPDIR)/libdaemons_la-cfg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cfg.c' object='libdaemons_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c libdaemons_la-imt_plugin.lo: imt_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-imt_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-imt_plugin.Tpo -c -o libdaemons_la-imt_plugin.lo `test -f 'imt_plugin.c' || echo '$(srcdir)/'`imt_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-imt_plugin.Tpo $(DEPDIR)/libdaemons_la-imt_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imt_plugin.c' object='libdaemons_la-imt_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-imt_plugin.lo `test -f 'imt_plugin.c' || echo '$(srcdir)/'`imt_plugin.c libdaemons_la-log.lo: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-log.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-log.Tpo -c -o libdaemons_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-log.Tpo $(DEPDIR)/libdaemons_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='libdaemons_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c libdaemons_la-pkt_handlers.lo: pkt_handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pkt_handlers.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pkt_handlers.Tpo -c -o libdaemons_la-pkt_handlers.lo `test -f 'pkt_handlers.c' || echo '$(srcdir)/'`pkt_handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pkt_handlers.Tpo $(DEPDIR)/libdaemons_la-pkt_handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pkt_handlers.c' object='libdaemons_la-pkt_handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pkt_handlers.lo `test -f 'pkt_handlers.c' || echo '$(srcdir)/'`pkt_handlers.c libdaemons_la-cfg_handlers.lo: cfg_handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-cfg_handlers.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-cfg_handlers.Tpo -c -o libdaemons_la-cfg_handlers.lo `test -f 'cfg_handlers.c' || echo '$(srcdir)/'`cfg_handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-cfg_handlers.Tpo $(DEPDIR)/libdaemons_la-cfg_handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cfg_handlers.c' object='libdaemons_la-cfg_handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-cfg_handlers.lo `test -f 'cfg_handlers.c' || echo '$(srcdir)/'`cfg_handlers.c libdaemons_la-net_aggr.lo: net_aggr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-net_aggr.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-net_aggr.Tpo -c -o libdaemons_la-net_aggr.lo `test -f 'net_aggr.c' || echo '$(srcdir)/'`net_aggr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-net_aggr.Tpo $(DEPDIR)/libdaemons_la-net_aggr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net_aggr.c' object='libdaemons_la-net_aggr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-net_aggr.lo `test -f 'net_aggr.c' || echo '$(srcdir)/'`net_aggr.c libdaemons_la-print_plugin.lo: print_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-print_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-print_plugin.Tpo -c -o libdaemons_la-print_plugin.lo `test -f 'print_plugin.c' || echo '$(srcdir)/'`print_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-print_plugin.Tpo $(DEPDIR)/libdaemons_la-print_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='print_plugin.c' object='libdaemons_la-print_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-print_plugin.lo `test -f 'print_plugin.c' || echo '$(srcdir)/'`print_plugin.c libdaemons_la-pretag.lo: pretag.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pretag.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pretag.Tpo -c -o libdaemons_la-pretag.lo `test -f 'pretag.c' || echo '$(srcdir)/'`pretag.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pretag.Tpo $(DEPDIR)/libdaemons_la-pretag.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pretag.c' object='libdaemons_la-pretag.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pretag.lo `test -f 'pretag.c' || echo '$(srcdir)/'`pretag.c libdaemons_la-ip_frag.lo: ip_frag.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-ip_frag.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-ip_frag.Tpo -c -o libdaemons_la-ip_frag.lo `test -f 'ip_frag.c' || echo '$(srcdir)/'`ip_frag.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-ip_frag.Tpo $(DEPDIR)/libdaemons_la-ip_frag.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ip_frag.c' object='libdaemons_la-ip_frag.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-ip_frag.lo `test -f 'ip_frag.c' || echo '$(srcdir)/'`ip_frag.c libdaemons_la-pretag_handlers.lo: pretag_handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pretag_handlers.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pretag_handlers.Tpo -c -o libdaemons_la-pretag_handlers.lo `test -f 'pretag_handlers.c' || echo '$(srcdir)/'`pretag_handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pretag_handlers.Tpo $(DEPDIR)/libdaemons_la-pretag_handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pretag_handlers.c' object='libdaemons_la-pretag_handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pretag_handlers.lo `test -f 'pretag_handlers.c' || echo '$(srcdir)/'`pretag_handlers.c libdaemons_la-ip_flow.lo: ip_flow.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-ip_flow.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-ip_flow.Tpo -c -o libdaemons_la-ip_flow.lo `test -f 'ip_flow.c' || echo '$(srcdir)/'`ip_flow.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-ip_flow.Tpo $(DEPDIR)/libdaemons_la-ip_flow.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ip_flow.c' object='libdaemons_la-ip_flow.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-ip_flow.lo `test -f 'ip_flow.c' || echo '$(srcdir)/'`ip_flow.c libdaemons_la-setproctitle.lo: setproctitle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-setproctitle.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-setproctitle.Tpo -c -o libdaemons_la-setproctitle.lo `test -f 'setproctitle.c' || echo '$(srcdir)/'`setproctitle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-setproctitle.Tpo $(DEPDIR)/libdaemons_la-setproctitle.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='setproctitle.c' object='libdaemons_la-setproctitle.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-setproctitle.lo `test -f 'setproctitle.c' || echo '$(srcdir)/'`setproctitle.c libdaemons_la-classifier.lo: classifier.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-classifier.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-classifier.Tpo -c -o libdaemons_la-classifier.lo `test -f 'classifier.c' || echo '$(srcdir)/'`classifier.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-classifier.Tpo $(DEPDIR)/libdaemons_la-classifier.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='classifier.c' object='libdaemons_la-classifier.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-classifier.lo `test -f 'classifier.c' || echo '$(srcdir)/'`classifier.c libdaemons_la-conntrack.lo: conntrack.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-conntrack.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-conntrack.Tpo -c -o libdaemons_la-conntrack.lo `test -f 'conntrack.c' || echo '$(srcdir)/'`conntrack.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-conntrack.Tpo $(DEPDIR)/libdaemons_la-conntrack.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conntrack.c' object='libdaemons_la-conntrack.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-conntrack.lo `test -f 'conntrack.c' || echo '$(srcdir)/'`conntrack.c libdaemons_la-xflow_status.lo: xflow_status.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-xflow_status.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-xflow_status.Tpo -c -o libdaemons_la-xflow_status.lo `test -f 'xflow_status.c' || echo '$(srcdir)/'`xflow_status.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-xflow_status.Tpo $(DEPDIR)/libdaemons_la-xflow_status.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xflow_status.c' object='libdaemons_la-xflow_status.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-xflow_status.lo `test -f 'xflow_status.c' || echo '$(srcdir)/'`xflow_status.c libdaemons_la-plugin_common.lo: plugin_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-plugin_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-plugin_common.Tpo -c -o libdaemons_la-plugin_common.lo `test -f 'plugin_common.c' || echo '$(srcdir)/'`plugin_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-plugin_common.Tpo $(DEPDIR)/libdaemons_la-plugin_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_common.c' object='libdaemons_la-plugin_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-plugin_common.lo `test -f 'plugin_common.c' || echo '$(srcdir)/'`plugin_common.c libdaemons_la-preprocess.lo: preprocess.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-preprocess.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-preprocess.Tpo -c -o libdaemons_la-preprocess.lo `test -f 'preprocess.c' || echo '$(srcdir)/'`preprocess.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-preprocess.Tpo $(DEPDIR)/libdaemons_la-preprocess.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='preprocess.c' object='libdaemons_la-preprocess.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-preprocess.lo `test -f 'preprocess.c' || echo '$(srcdir)/'`preprocess.c libdaemons_la-ll.lo: ll.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-ll.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-ll.Tpo -c -o libdaemons_la-ll.lo `test -f 'll.c' || echo '$(srcdir)/'`ll.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-ll.Tpo $(DEPDIR)/libdaemons_la-ll.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ll.c' object='libdaemons_la-ll.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-ll.lo `test -f 'll.c' || echo '$(srcdir)/'`ll.c libdaemons_la-nl.lo: nl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-nl.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-nl.Tpo -c -o libdaemons_la-nl.lo `test -f 'nl.c' || echo '$(srcdir)/'`nl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-nl.Tpo $(DEPDIR)/libdaemons_la-nl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nl.c' object='libdaemons_la-nl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-nl.lo `test -f 'nl.c' || echo '$(srcdir)/'`nl.c libdaemons_la-base64.lo: base64.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-base64.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-base64.Tpo -c -o libdaemons_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-base64.Tpo $(DEPDIR)/libdaemons_la-base64.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='base64.c' object='libdaemons_la-base64.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c libdaemons_la-pmsearch.lo: pmsearch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pmsearch.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pmsearch.Tpo -c -o libdaemons_la-pmsearch.lo `test -f 'pmsearch.c' || echo '$(srcdir)/'`pmsearch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pmsearch.Tpo $(DEPDIR)/libdaemons_la-pmsearch.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmsearch.c' object='libdaemons_la-pmsearch.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pmsearch.lo `test -f 'pmsearch.c' || echo '$(srcdir)/'`pmsearch.c libdaemons_la-linklist.lo: linklist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-linklist.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-linklist.Tpo -c -o libdaemons_la-linklist.lo `test -f 'linklist.c' || echo '$(srcdir)/'`linklist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-linklist.Tpo $(DEPDIR)/libdaemons_la-linklist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linklist.c' object='libdaemons_la-linklist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-linklist.lo `test -f 'linklist.c' || echo '$(srcdir)/'`linklist.c libdaemons_la-thread_pool.lo: thread_pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-thread_pool.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-thread_pool.Tpo -c -o libdaemons_la-thread_pool.lo `test -f 'thread_pool.c' || echo '$(srcdir)/'`thread_pool.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-thread_pool.Tpo $(DEPDIR)/libdaemons_la-thread_pool.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread_pool.c' object='libdaemons_la-thread_pool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-thread_pool.lo `test -f 'thread_pool.c' || echo '$(srcdir)/'`thread_pool.c libdaemons_la-plugin_cmn_custom.lo: plugin_cmn_custom.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-plugin_cmn_custom.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-plugin_cmn_custom.Tpo -c -o libdaemons_la-plugin_cmn_custom.lo `test -f 'plugin_cmn_custom.c' || echo '$(srcdir)/'`plugin_cmn_custom.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-plugin_cmn_custom.Tpo $(DEPDIR)/libdaemons_la-plugin_cmn_custom.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_cmn_custom.c' object='libdaemons_la-plugin_cmn_custom.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-plugin_cmn_custom.lo `test -f 'plugin_cmn_custom.c' || echo '$(srcdir)/'`plugin_cmn_custom.c libdaemons_la-network.lo: network.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-network.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-network.Tpo -c -o libdaemons_la-network.lo `test -f 'network.c' || echo '$(srcdir)/'`network.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-network.Tpo $(DEPDIR)/libdaemons_la-network.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='network.c' object='libdaemons_la-network.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-network.lo `test -f 'network.c' || echo '$(srcdir)/'`network.c libdaemons_la-pmacct-globals.lo: pmacct-globals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pmacct-globals.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pmacct-globals.Tpo -c -o libdaemons_la-pmacct-globals.lo `test -f 'pmacct-globals.c' || echo '$(srcdir)/'`pmacct-globals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pmacct-globals.Tpo $(DEPDIR)/libdaemons_la-pmacct-globals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmacct-globals.c' object='libdaemons_la-pmacct-globals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pmacct-globals.lo `test -f 'pmacct-globals.c' || echo '$(srcdir)/'`pmacct-globals.c libdaemons_la-mysql_plugin.lo: mysql_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-mysql_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-mysql_plugin.Tpo -c -o libdaemons_la-mysql_plugin.lo `test -f 'mysql_plugin.c' || echo '$(srcdir)/'`mysql_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-mysql_plugin.Tpo $(DEPDIR)/libdaemons_la-mysql_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mysql_plugin.c' object='libdaemons_la-mysql_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-mysql_plugin.lo `test -f 'mysql_plugin.c' || echo '$(srcdir)/'`mysql_plugin.c libdaemons_la-pgsql_plugin.lo: pgsql_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-pgsql_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-pgsql_plugin.Tpo -c -o libdaemons_la-pgsql_plugin.lo `test -f 'pgsql_plugin.c' || echo '$(srcdir)/'`pgsql_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-pgsql_plugin.Tpo $(DEPDIR)/libdaemons_la-pgsql_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pgsql_plugin.c' object='libdaemons_la-pgsql_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-pgsql_plugin.lo `test -f 'pgsql_plugin.c' || echo '$(srcdir)/'`pgsql_plugin.c libdaemons_la-mongodb_plugin.lo: mongodb_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-mongodb_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-mongodb_plugin.Tpo -c -o libdaemons_la-mongodb_plugin.lo `test -f 'mongodb_plugin.c' || echo '$(srcdir)/'`mongodb_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-mongodb_plugin.Tpo $(DEPDIR)/libdaemons_la-mongodb_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mongodb_plugin.c' object='libdaemons_la-mongodb_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-mongodb_plugin.lo `test -f 'mongodb_plugin.c' || echo '$(srcdir)/'`mongodb_plugin.c libdaemons_la-sqlite3_plugin.lo: sqlite3_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-sqlite3_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-sqlite3_plugin.Tpo -c -o libdaemons_la-sqlite3_plugin.lo `test -f 'sqlite3_plugin.c' || echo '$(srcdir)/'`sqlite3_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-sqlite3_plugin.Tpo $(DEPDIR)/libdaemons_la-sqlite3_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sqlite3_plugin.c' object='libdaemons_la-sqlite3_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-sqlite3_plugin.lo `test -f 'sqlite3_plugin.c' || echo '$(srcdir)/'`sqlite3_plugin.c libdaemons_la-plugin_cmn_json.lo: plugin_cmn_json.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-plugin_cmn_json.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-plugin_cmn_json.Tpo -c -o libdaemons_la-plugin_cmn_json.lo `test -f 'plugin_cmn_json.c' || echo '$(srcdir)/'`plugin_cmn_json.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-plugin_cmn_json.Tpo $(DEPDIR)/libdaemons_la-plugin_cmn_json.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_cmn_json.c' object='libdaemons_la-plugin_cmn_json.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-plugin_cmn_json.lo `test -f 'plugin_cmn_json.c' || echo '$(srcdir)/'`plugin_cmn_json.c libdaemons_la-plugin_cmn_avro.lo: plugin_cmn_avro.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-plugin_cmn_avro.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-plugin_cmn_avro.Tpo -c -o libdaemons_la-plugin_cmn_avro.lo `test -f 'plugin_cmn_avro.c' || echo '$(srcdir)/'`plugin_cmn_avro.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-plugin_cmn_avro.Tpo $(DEPDIR)/libdaemons_la-plugin_cmn_avro.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_cmn_avro.c' object='libdaemons_la-plugin_cmn_avro.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-plugin_cmn_avro.lo `test -f 'plugin_cmn_avro.c' || echo '$(srcdir)/'`plugin_cmn_avro.c libdaemons_la-amqp_common.lo: amqp_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-amqp_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-amqp_common.Tpo -c -o libdaemons_la-amqp_common.lo `test -f 'amqp_common.c' || echo '$(srcdir)/'`amqp_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-amqp_common.Tpo $(DEPDIR)/libdaemons_la-amqp_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='amqp_common.c' object='libdaemons_la-amqp_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-amqp_common.lo `test -f 'amqp_common.c' || echo '$(srcdir)/'`amqp_common.c libdaemons_la-amqp_plugin.lo: amqp_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-amqp_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-amqp_plugin.Tpo -c -o libdaemons_la-amqp_plugin.lo `test -f 'amqp_plugin.c' || echo '$(srcdir)/'`amqp_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-amqp_plugin.Tpo $(DEPDIR)/libdaemons_la-amqp_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='amqp_plugin.c' object='libdaemons_la-amqp_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-amqp_plugin.lo `test -f 'amqp_plugin.c' || echo '$(srcdir)/'`amqp_plugin.c libdaemons_la-zmq_common.lo: zmq_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-zmq_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-zmq_common.Tpo -c -o libdaemons_la-zmq_common.lo `test -f 'zmq_common.c' || echo '$(srcdir)/'`zmq_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-zmq_common.Tpo $(DEPDIR)/libdaemons_la-zmq_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zmq_common.c' object='libdaemons_la-zmq_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-zmq_common.lo `test -f 'zmq_common.c' || echo '$(srcdir)/'`zmq_common.c libdaemons_la-kafka_common.lo: kafka_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-kafka_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-kafka_common.Tpo -c -o libdaemons_la-kafka_common.lo `test -f 'kafka_common.c' || echo '$(srcdir)/'`kafka_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-kafka_common.Tpo $(DEPDIR)/libdaemons_la-kafka_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kafka_common.c' object='libdaemons_la-kafka_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-kafka_common.lo `test -f 'kafka_common.c' || echo '$(srcdir)/'`kafka_common.c libdaemons_la-kafka_plugin.lo: kafka_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-kafka_plugin.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-kafka_plugin.Tpo -c -o libdaemons_la-kafka_plugin.lo `test -f 'kafka_plugin.c' || echo '$(srcdir)/'`kafka_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-kafka_plugin.Tpo $(DEPDIR)/libdaemons_la-kafka_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kafka_plugin.c' object='libdaemons_la-kafka_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-kafka_plugin.lo `test -f 'kafka_plugin.c' || echo '$(srcdir)/'`kafka_plugin.c libdaemons_la-sql_common.lo: sql_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-sql_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-sql_common.Tpo -c -o libdaemons_la-sql_common.lo `test -f 'sql_common.c' || echo '$(srcdir)/'`sql_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-sql_common.Tpo $(DEPDIR)/libdaemons_la-sql_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sql_common.c' object='libdaemons_la-sql_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-sql_common.lo `test -f 'sql_common.c' || echo '$(srcdir)/'`sql_common.c libdaemons_la-sql_handlers.lo: sql_handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-sql_handlers.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-sql_handlers.Tpo -c -o libdaemons_la-sql_handlers.lo `test -f 'sql_handlers.c' || echo '$(srcdir)/'`sql_handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-sql_handlers.Tpo $(DEPDIR)/libdaemons_la-sql_handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sql_handlers.c' object='libdaemons_la-sql_handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-sql_handlers.lo `test -f 'sql_handlers.c' || echo '$(srcdir)/'`sql_handlers.c libdaemons_la-sql_common_m.lo: sql_common_m.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-sql_common_m.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-sql_common_m.Tpo -c -o libdaemons_la-sql_common_m.lo `test -f 'sql_common_m.c' || echo '$(srcdir)/'`sql_common_m.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-sql_common_m.Tpo $(DEPDIR)/libdaemons_la-sql_common_m.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sql_common_m.c' object='libdaemons_la-sql_common_m.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-sql_common_m.lo `test -f 'sql_common_m.c' || echo '$(srcdir)/'`sql_common_m.c libdaemons_la-redis_common.lo: redis_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -MT libdaemons_la-redis_common.lo -MD -MP -MF $(DEPDIR)/libdaemons_la-redis_common.Tpo -c -o libdaemons_la-redis_common.lo `test -f 'redis_common.c' || echo '$(srcdir)/'`redis_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdaemons_la-redis_common.Tpo $(DEPDIR)/libdaemons_la-redis_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='redis_common.c' object='libdaemons_la-redis_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdaemons_la_CFLAGS) $(CFLAGS) -c -o libdaemons_la-redis_common.lo `test -f 'redis_common.c' || echo '$(srcdir)/'`redis_common.c uacctd-uacctd.o: uacctd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uacctd_CFLAGS) $(CFLAGS) -MT uacctd-uacctd.o -MD -MP -MF $(DEPDIR)/uacctd-uacctd.Tpo -c -o uacctd-uacctd.o `test -f 'uacctd.c' || echo '$(srcdir)/'`uacctd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uacctd-uacctd.Tpo $(DEPDIR)/uacctd-uacctd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uacctd.c' object='uacctd-uacctd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uacctd_CFLAGS) $(CFLAGS) -c -o uacctd-uacctd.o `test -f 'uacctd.c' || echo '$(srcdir)/'`uacctd.c uacctd-uacctd.obj: uacctd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uacctd_CFLAGS) $(CFLAGS) -MT uacctd-uacctd.obj -MD -MP -MF $(DEPDIR)/uacctd-uacctd.Tpo -c -o uacctd-uacctd.obj `if test -f 'uacctd.c'; then $(CYGPATH_W) 'uacctd.c'; else $(CYGPATH_W) '$(srcdir)/uacctd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uacctd-uacctd.Tpo $(DEPDIR)/uacctd-uacctd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uacctd.c' object='uacctd-uacctd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uacctd_CFLAGS) $(CFLAGS) -c -o uacctd-uacctd.obj `if test -f 'uacctd.c'; then $(CYGPATH_W) 'uacctd.c'; else $(CYGPATH_W) '$(srcdir)/uacctd.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstLTLIBRARIES clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/libcommon_la-addr.Plo -rm -f ./$(DEPDIR)/libcommon_la-strlcpy.Plo -rm -f ./$(DEPDIR)/libdaemons_la-acct.Plo -rm -f ./$(DEPDIR)/libdaemons_la-amqp_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-amqp_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-base64.Plo -rm -f ./$(DEPDIR)/libdaemons_la-cfg.Plo -rm -f ./$(DEPDIR)/libdaemons_la-cfg_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-classifier.Plo -rm -f ./$(DEPDIR)/libdaemons_la-conntrack.Plo -rm -f ./$(DEPDIR)/libdaemons_la-imt_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ip_flow.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ip_frag.Plo -rm -f ./$(DEPDIR)/libdaemons_la-kafka_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-kafka_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-linklist.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ll.Plo -rm -f ./$(DEPDIR)/libdaemons_la-log.Plo -rm -f ./$(DEPDIR)/libdaemons_la-memory.Plo -rm -f ./$(DEPDIR)/libdaemons_la-mongodb_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-mysql_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-net_aggr.Plo -rm -f ./$(DEPDIR)/libdaemons_la-network.Plo -rm -f ./$(DEPDIR)/libdaemons_la-nl.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pgsql_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pkt_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_avro.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_custom.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_json.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_hooks.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pmacct-globals.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pmsearch.Plo -rm -f ./$(DEPDIR)/libdaemons_la-preprocess.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pretag.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pretag_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-print_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-redis_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-server.Plo -rm -f ./$(DEPDIR)/libdaemons_la-setproctitle.Plo -rm -f ./$(DEPDIR)/libdaemons_la-signals.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_common_m.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sqlite3_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-thread_pool.Plo -rm -f ./$(DEPDIR)/libdaemons_la-util.Plo -rm -f ./$(DEPDIR)/libdaemons_la-xflow_status.Plo -rm -f ./$(DEPDIR)/libdaemons_la-zmq_common.Plo -rm -f ./$(DEPDIR)/nfacctd.Po -rm -f ./$(DEPDIR)/nfv9_template.Po -rm -f ./$(DEPDIR)/pmacct.Po -rm -f ./$(DEPDIR)/pmacctd.Po -rm -f ./$(DEPDIR)/pmbgpd.Po -rm -f ./$(DEPDIR)/pmbmpd.Po -rm -f ./$(DEPDIR)/pmtelemetryd.Po -rm -f ./$(DEPDIR)/sfacctd.Po -rm -f ./$(DEPDIR)/sflow.Po -rm -f ./$(DEPDIR)/sfv5_module.Po -rm -f ./$(DEPDIR)/uacctd-uacctd.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-sbinPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libcommon_la-addr.Plo -rm -f ./$(DEPDIR)/libcommon_la-strlcpy.Plo -rm -f ./$(DEPDIR)/libdaemons_la-acct.Plo -rm -f ./$(DEPDIR)/libdaemons_la-amqp_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-amqp_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-base64.Plo -rm -f ./$(DEPDIR)/libdaemons_la-cfg.Plo -rm -f ./$(DEPDIR)/libdaemons_la-cfg_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-classifier.Plo -rm -f ./$(DEPDIR)/libdaemons_la-conntrack.Plo -rm -f ./$(DEPDIR)/libdaemons_la-imt_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ip_flow.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ip_frag.Plo -rm -f ./$(DEPDIR)/libdaemons_la-kafka_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-kafka_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-linklist.Plo -rm -f ./$(DEPDIR)/libdaemons_la-ll.Plo -rm -f ./$(DEPDIR)/libdaemons_la-log.Plo -rm -f ./$(DEPDIR)/libdaemons_la-memory.Plo -rm -f ./$(DEPDIR)/libdaemons_la-mongodb_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-mysql_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-net_aggr.Plo -rm -f ./$(DEPDIR)/libdaemons_la-network.Plo -rm -f ./$(DEPDIR)/libdaemons_la-nl.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pgsql_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pkt_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_avro.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_custom.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_cmn_json.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-plugin_hooks.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pmacct-globals.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pmsearch.Plo -rm -f ./$(DEPDIR)/libdaemons_la-preprocess.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pretag.Plo -rm -f ./$(DEPDIR)/libdaemons_la-pretag_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-print_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-redis_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-server.Plo -rm -f ./$(DEPDIR)/libdaemons_la-setproctitle.Plo -rm -f ./$(DEPDIR)/libdaemons_la-signals.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_common.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_common_m.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sql_handlers.Plo -rm -f ./$(DEPDIR)/libdaemons_la-sqlite3_plugin.Plo -rm -f ./$(DEPDIR)/libdaemons_la-thread_pool.Plo -rm -f ./$(DEPDIR)/libdaemons_la-util.Plo -rm -f ./$(DEPDIR)/libdaemons_la-xflow_status.Plo -rm -f ./$(DEPDIR)/libdaemons_la-zmq_common.Plo -rm -f ./$(DEPDIR)/nfacctd.Po -rm -f ./$(DEPDIR)/nfv9_template.Po -rm -f ./$(DEPDIR)/pmacct.Po -rm -f ./$(DEPDIR)/pmacctd.Po -rm -f ./$(DEPDIR)/pmbgpd.Po -rm -f ./$(DEPDIR)/pmbmpd.Po -rm -f ./$(DEPDIR)/pmtelemetryd.Po -rm -f ./$(DEPDIR)/sfacctd.Po -rm -f ./$(DEPDIR)/sflow.Po -rm -f ./$(DEPDIR)/sfv5_module.Po -rm -f ./$(DEPDIR)/uacctd-uacctd.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS .MAKE: $(am__recursive_targets) all check install install-am \ install-exec install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-sbinPROGRAMS .PRECIOUS: Makefile pmacct-build.h_h: @if [ ! -f ".pmacct-build.h" ] || [ "`cat .pmacct-build.h`" != "`git rev-parse HEAD 2> /dev/null`" ]; then \ echo "#ifndef PMACCT_BUILD_STR" > pmacct-build.h; \ echo "#define PMACCT_BUILD_STR" >> pmacct-build.h; \ if [ "x`git rev-parse --is-inside-work-tree 2> /dev/null`" == "xtrue" ]; then \ echo "`git rev-parse HEAD`" > .pmacct-build.h; \ BUILD_DATE="`git log -1 --date=short --pretty=format:%ad | tr -d "-"`"; \ BUILD_AUX="`git log -1 --date=short --pretty=format:%ad`";\ BUILD_COMMITS="`git log --date=short --pretty=format:%ad | sort | uniq -c | grep $$BUILD_AUX | awk '{print $$1}'`"; \ BUILD_COMMITS="$$(($$BUILD_COMMITS - 1))"; \ BUILD_HASH_SHORT="`git rev-parse --short HEAD`"; \ echo "#define PMACCT_BUILD \"$$BUILD_DATE-$$BUILD_COMMITS ($$BUILD_HASH_SHORT)\"" >> pmacct-build.h; \ else \ echo "#define PMACCT_BUILD \"RELEASE\"" >> pmacct-build.h; \ fi;\ echo "#endif" >> pmacct-build.h; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/nfprobe_plugin/0000755000175000017500000000000014354105416015607 5ustar paolopaolopmacct-1.7.8/src/nfprobe_plugin/nfprobe_plugin.h0000644000175000017500000001765214354105275021007 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* * Originally based on softflowd which is: * * Copyright (c) 2002 Damien Miller. 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 THE AUTHOR ``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 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 NFPROBE_PLUGIN_H #define NFPROBE_PLUGIN_H #include "common.h" #include "sys-tree.h" #include "treetype.h" /* * Capture length for libpcap: Must fit the link layer header, plus * a maximally sized ip/ipv6 header and most of a TCP header */ #define LIBPCAP_SNAPLEN_V4 96 #define LIBPCAP_SNAPLEN_V6 160 /* * Timeouts */ #define DEFAULT_TCP_TIMEOUT 3600 #define DEFAULT_TCP_RST_TIMEOUT 120 #define DEFAULT_TCP_FIN_TIMEOUT 300 #define DEFAULT_UDP_TIMEOUT 300 #define DEFAULT_ICMP_TIMEOUT 300 #define DEFAULT_GENERAL_TIMEOUT 3600 #define DEFAULT_MAXIMUM_LIFETIME (3600*24*7) #define DEFAULT_EXPIRY_INTERVAL 60 /* * Default maximum number of flow to track simultaneously * 8192 corresponds to just under 1Mb of flow data */ #define DEFAULT_MAX_FLOWS 8192 #define DEFAULT_BUCKETS 256 /* Return values from process_packet */ #define PP_OK 0 #define PP_BAD_PACKET -2 #define PP_MALLOC_FAIL -3 /* Store a couple of statistics, maybe more in the future */ struct STATISTIC { double min, mean, max; }; /* * This structure is the root of the flow tracking system. * It holds the root of the tree of active flows and the head of the * tree of expiry events. It also collects miscellaneous statistics */ struct FLOWTRACK { /* The flows and their expiry events */ FLOW_HEAD(FLOWS, FLOW) flows; /* Top of flow tree */ EXPIRY_HEAD(EXPIRIES, EXPIRY) expiries; /* Top of expiries tree */ unsigned int num_flows; /* # of active flows */ u_int64_t next_flow_seq; /* Next flow ID */ u_int32_t next_datagram_seq; /* Stuff related to flow export */ struct timeval system_boot_time; /* SysUptime */ /* Flow timeouts */ int tcp_timeout; /* Open TCP connections */ int tcp_rst_timeout; /* TCP flows after RST */ int tcp_fin_timeout; /* TCP flows after bidi FIN */ int udp_timeout; /* UDP flows */ int icmp_timeout; /* ICMP flows */ int general_timeout; /* Everything else */ int maximum_lifetime; /* Maximum life for flows */ int expiry_interval; /* Interval between expiries */ /* Statistics */ u_int64_t total_packets; /* # of good packets */ u_int64_t frag_packets; /* # of fragmented packets */ u_int64_t non_ip_packets; /* # of not-IP packets */ u_int64_t bad_packets; /* # of bad packets */ u_int64_t flows_expired; /* # expired */ u_int64_t flows_exported; /* # of flows sent */ u_int64_t flows_dropped; /* # of flows dropped */ u_int64_t flows_force_expired; /* # of flows forced out */ u_int64_t packets_sent; /* # netflow packets sent */ struct STATISTIC duration; /* Flow duration */ struct STATISTIC octets; /* Bytes (bidir) */ struct STATISTIC packets; /* Packets (bidir) */ /* Per protocol statistics */ u_int64_t flows_pp[DEFAULT_BUCKETS]; u_int64_t octets_pp[DEFAULT_BUCKETS]; u_int64_t packets_pp[DEFAULT_BUCKETS]; struct STATISTIC duration_pp[DEFAULT_BUCKETS]; /* Timeout statistics */ u_int64_t expired_general; u_int64_t expired_tcp; u_int64_t expired_tcp_rst; u_int64_t expired_tcp_fin; u_int64_t expired_udp; u_int64_t expired_icmp; u_int64_t expired_maxlife; u_int64_t expired_overbytes; u_int64_t expired_maxflows; u_int64_t expired_flush; }; /* * This structure is an entry in the tree of flows that we are * currently tracking. * * Because flows are matched _bi-directionally_, they must be stored in * a canonical format: the numerically lowest address and port number must * be stored in the first address and port array slot respectively. */ struct FLOW { /* Housekeeping */ struct EXPIRY *expiry; /* Pointer to expiry record */ FLOW_ENTRY(FLOW) trp; /* Tree pointer */ /* Flow identity (all are in network byte order) */ int af; /* Address family of flow */ u_int8_t direction[2]; /* Flow direction */ u_int32_t ip6_flowlabel[2]; /* IPv6 Flowlabel */ union { struct in_addr v4; struct in6_addr v6; } addr[2]; /* Endpoint addresses */ u_int8_t mask[2]; /* Network masks */ u_int16_t port[2]; /* Endpoint ports */ u_int8_t tcp_flags[2]; /* Cumulative OR of flags */ u_int8_t protocol; /* Protocol */ u_int8_t tos[2]; /* ToS/DSCP */ /* ASN/BGP stuff */ as_t as[2]; /* Autonomous System numbers */ union { struct in_addr v4; struct in6_addr v6; } bgp_next_hop[2]; /* L2 stuff */ u_int8_t mac[2][6]; /* Endpoint L2/Ethernet MAC addresses */ u_int16_t vlan; /* VLAN ID */ u_int32_t mpls_label[2]; /* MPLS top label */ u_int32_t ifindex[2]; /* input/output ifindex */ /* classification stuff */ pm_class_t class; /* Classification internal ID */ #if defined (WITH_NDPI) pm_class2_t ndpi_class; /* nDPI classification internal ID */ #endif pm_id_t tag[2]; /* Tag */ pm_id_t tag2[2]; /* Tag2 */ /* Per-flow statistics (all in _host_ byte order) */ u_int64_t flow_seq; /* Flow ID */ struct timeval flow_start; /* Time of creation */ struct timeval flow_last; /* Time of last traffic */ /* Per-endpoint statistics (all in _host_ byte order) */ u_int64_t octets[2]; /* Octets so far */ u_int64_t packets[2]; /* Packets so far */ u_int64_t flows[2]; /* Flows so far */ u_char *pcust[2]; /* space for custom-defined primitives */ struct pkt_vlen_hdr_primitives *pvlen[2]; /* space for vlen primitives */ }; /* * This is an entry in the tree of expiry events. The tree is used to * avoid traversion the whole tree of active flows looking for ones to * expire. "expires_at" is the time at which the flow should be discarded, * or zero if it is scheduled for immediate disposal. * * When a flow which hasn't been scheduled for immediate expiry registers * traffic, it is deleted from its current position in the tree and * re-inserted (subject to its updated timeout). * * Expiry scans operate by starting at the head of the tree and expiring * each entry with expires_at < now * */ struct EXPIRY { EXPIRY_ENTRY(EXPIRY) trp; /* Tree pointer */ struct FLOW *flow; /* pointer to flow */ u_int32_t expires_at; /* time_t */ enum { R_GENERAL, R_TCP, R_TCP_RST, R_TCP_FIN, R_UDP, R_ICMP, R_MAXLIFE, R_OVERBYTES, R_OVERFLOWS, R_FLUSH } reason; }; /* Prototype for functions shared from softflowd.c */ u_int32_t timeval_sub_ms(const struct timeval *, const struct timeval *); /* Prototypes for functions to send NetFlow packets, from netflow*.c */ int send_netflow_v5(struct FLOW **, int, int, void *, u_int64_t *, struct timeval *, int, u_int8_t, u_int32_t); int send_netflow_v9(struct FLOW **, int, int, void *, u_int64_t *, struct timeval *, int, u_int8_t, u_int32_t); #endif /* NFPROBE_PLUGIN_H */ pmacct-1.7.8/src/nfprobe_plugin/convtime.c0000644000175000017500000000425114354105275017604 0ustar paolopaolo/* * Copyright (c) 2001 Kevin Steves. 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 THE AUTHOR ``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 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. */ #include "common.h" #include "convtime.h" #define SECONDS 1 #define MINUTES (SECONDS * 60) #define HOURS (MINUTES * 60) #define DAYS (HOURS * 24) #define WEEKS (DAYS * 7) long int convtime(const char *s) { long total, secs; const char *p; char *endp; errno = 0; total = 0; p = s; if (p == NULL || *p == '\0') return -1; while (*p) { secs = strtol(p, &endp, 10); if (p == endp || (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || secs < 0) return -1; switch (*endp++) { case '\0': endp--; case 's': case 'S': break; case 'm': case 'M': secs *= MINUTES; break; case 'h': case 'H': secs *= HOURS; break; case 'd': case 'D': secs *= DAYS; break; case 'w': case 'W': secs *= WEEKS; break; default: return -1; } total += secs; if (total < 0) return -1; p = endp; } return total; } pmacct-1.7.8/src/nfprobe_plugin/nfprobe_plugin.c0000644000175000017500000015153214354105275020776 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* * Originally based on softflowd which is: * * Copyright 2002 Damien Miller 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 THE AUTHOR ``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 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. */ /* * This is software implementation of Cisco's NetFlow(tm) traffic * reporting system. It operates by listening (via libpcap) on a * promiscuous interface and tracking traffic flows. * * Traffic flows are recorded by source/destination/protocol IP address or, in the * case of TCP and UDP, by src_addr:src_port/dest_addr:dest_port/protocol * * Flows expire automatically after a period of inactivity (default: 1 hour) * They may also be evicted (in order of age) in situations where there are * more flows than slots available. * * Netflow version 1 compatible packets are sent to a specified target * host upon flow expiry. * * As this implementation watches traffic promiscuously, it is likely to * place significant load on hosts or gateways on which it is installed. */ #include "common.h" #include "addr.h" #include "sys-tree.h" #include "convtime.h" #include "nfacctd.h" #include "nfprobe_plugin.h" #include "treetype.h" #include "pmacct-data.h" #include "net_aggr.h" #include "plugin_hooks.h" #include "plugin_common.h" /* Global variables */ static int verbose_flag = 0; /* Debugging flag */ static int timeout = 0; struct FLOWTRACK *glob_flowtrack = NULL; /* Prototypes */ static void force_expire(struct FLOWTRACK *, u_int32_t); /* Signal handler flags */ static int graceful_shutdown_request = 0; /* Context for libpcap callback functions */ struct CB_CTXT { struct FLOWTRACK *ft; int linktype; int fatal; int want_v6; }; /* Netflow send functions */ typedef int (netflow_send_func_t)(struct FLOW **, int, int, void *, u_int64_t *, struct timeval *, int, u_int8_t, u_int32_t); struct NETFLOW_SENDER { int version; netflow_send_func_t *func; int v6_capable; }; /* Array of NetFlow export function that we know of. NB. nf[0] is default */ static const struct NETFLOW_SENDER nf[] = { { 5, send_netflow_v5, 0 }, { 9, send_netflow_v9, 1 }, { 10, send_netflow_v9, 1 }, { -1, NULL, 0 }, }; /* Describes a location where we send NetFlow packets to */ struct NETFLOW_TARGET { int fd; void *dtls; const struct NETFLOW_SENDER *dialect; }; void nfprobe_exit_gracefully(int signum) { signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); if (config.pcap_savefile) timeout = 3*1000; graceful_shutdown_request = TRUE; } /* * This is the flow comparison function. */ static int flow_compare(struct FLOW *a, struct FLOW *b) { /* Be careful to avoid signed vs unsigned issues here */ int r; if (a->af != b->af) return (a->af > b->af ? 1 : -1); if ((r = memcmp(&a->addr[0], &b->addr[0], sizeof(a->addr[0]))) != 0) return (r > 0 ? 1 : -1); if ((r = memcmp(&a->addr[1], &b->addr[1], sizeof(a->addr[1]))) != 0) return (r > 0 ? 1 : -1); #ifdef notyet if (a->ip6_flowlabel[0] != 0 && b->ip6_flowlabel[0] != 0 && a->ip6_flowlabel[0] != b->ip6_flowlabel[0]) return (a->ip6_flowlabel[0] > b->ip6_flowlabel[0] ? 1 : -1); if (a->ip6_flowlabel[1] != 0 && b->ip6_flowlabel[1] != 0 && a->ip6_flowlabel[1] != b->ip6_flowlabel[1]) return (a->ip6_flowlabel[1] > b->ip6_flowlabel[1] ? 1 : -1); #endif if (a->protocol != b->protocol) return (a->protocol > b->protocol ? 1 : -1); if (a->port[0] != b->port[0]) return (ntohs(a->port[0]) > ntohs(b->port[0]) ? 1 : -1); if (a->port[1] != b->port[1]) return (ntohs(a->port[1]) > ntohs(b->port[1]) ? 1 : -1); if (a->ifindex[0] != b->ifindex[0]) return (a->ifindex[0] > b->ifindex[0] ? 1 : -1); if (a->ifindex[1] != b->ifindex[1]) return (a->ifindex[1] > b->ifindex[1] ? 1 : -1); return (0); } /* Generate functions for flow tree */ FLOW_PROTOTYPE(FLOWS, FLOW, trp, flow_compare); FLOW_GENERATE(FLOWS, FLOW, trp, flow_compare); /* * This is the expiry comparison function. */ static int expiry_compare(struct EXPIRY *a, struct EXPIRY *b) { if (a->expires_at != b->expires_at) return (a->expires_at > b->expires_at ? 1 : -1); /* Make expiry entries unique by comparing flow sequence */ if (a->flow->flow_seq != b->flow->flow_seq) return (a->flow->flow_seq > b->flow->flow_seq ? 1 : -1); return (0); } /* Generate functions for flow tree */ EXPIRY_PROTOTYPE(EXPIRIES, EXPIRY, trp, expiry_compare); EXPIRY_GENERATE(EXPIRIES, EXPIRY, trp, expiry_compare); /* Format a time in an ISOish format */ static const char * format_time(time_t t) { static char buf[32]; pm_strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S$tzone", &t, config.timestamps_utc); return (buf); } /* Format a flow in a verbose and ugly way */ static const char * format_flow(struct FLOW *flow) { char addr1[64], addr2[64], stime[20], ftime[20]; static char buf[1024]; inet_ntop(flow->af, &flow->addr[0], addr1, sizeof(addr1)); inet_ntop(flow->af, &flow->addr[1], addr2, sizeof(addr2)); snprintf(stime, sizeof(ftime), "%s", format_time(flow->flow_start.tv_sec)); snprintf(ftime, sizeof(ftime), "%s", format_time(flow->flow_last.tv_sec)); snprintf(buf, sizeof(buf), "seq:%" PRIu64 " [%s]:%u <> [%s]:%u proto:%u " "octets>:%" PRIu64 " packets>:%" PRIu64 " octets<:%" PRIu64 " packets<:%" PRIu64 " " "start:%s.%03u finish:%s.%03u tcp>:%02x tcp<:%02x " "flowlabel>:%08x flowlabel<:%08x ", flow->flow_seq, addr1, ntohs(flow->port[0]), addr2, ntohs(flow->port[1]), (int)flow->protocol, flow->octets[0], flow->packets[0], flow->octets[1], flow->packets[1], stime, (unsigned int)((flow->flow_start.tv_usec + 500) / 1000), ftime, (unsigned int)((flow->flow_last.tv_usec + 500) / 1000), flow->tcp_flags[0], flow->tcp_flags[1], flow->ip6_flowlabel[0], flow->ip6_flowlabel[1]); return (buf); } /* Format a flow in a brief way */ static const char * format_flow_brief(struct FLOW *flow) { char addr1[64], addr2[64]; static char buf[1024]; inet_ntop(flow->af, &flow->addr[0], addr1, sizeof(addr1)); inet_ntop(flow->af, &flow->addr[1], addr2, sizeof(addr2)); snprintf(buf, sizeof(buf), "seq:%" PRIu64 " [%s]:%hu <> [%s]:%hu proto:%u", flow->flow_seq, addr1, ntohs(flow->port[0]), addr2, ntohs(flow->port[1]), (int)flow->protocol); return (buf); } /* Need to preprocess data because packet handlers have automagically * swapped byte ordering for some primitives */ void handle_hostbyteorder_packet(struct pkt_data *data) { #if defined HAVE_L2 data->primitives.vlan_id = htons(data->primitives.vlan_id); #endif data->primitives.src_port = htons(data->primitives.src_port); data->primitives.dst_port = htons(data->primitives.dst_port); data->primitives.src_as = htonl(data->primitives.src_as); data->primitives.dst_as = htonl(data->primitives.dst_as); } /* Fill in transport-layer (tcp/udp) portions of flow record */ static int transport_to_flowrec(struct FLOW *flow, struct pkt_data *data, struct pkt_extras *extras, int protocol, int ndx) { struct pkt_primitives *p = &data->primitives; u_int8_t *icmp_ptr = NULL; /* * XXX to keep flow in proper canonical format, it may be necessary * to swap the array slots based on the order of the port numbers * does this matter in practice??? I don't think so - return flows will * always match, because of their symmetrical addr/ports */ switch (protocol) { case IPPROTO_TCP: /* Check for runt packet, but don't error out on short frags */ flow->port[ndx] = p->src_port; flow->port[ndx ^ 1] = p->dst_port; flow->tcp_flags[ndx] |= extras->tcp_flags; break; case IPPROTO_UDP: /* Check for runt packet, but don't error out on short frags */ flow->port[ndx] = p->src_port; flow->port[ndx ^ 1] = p->dst_port; break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: icmp_ptr = (u_int8_t *) &flow->port[ndx ^ 1]; icmp_ptr[0] = extras->icmp_type; icmp_ptr[1] = extras->icmp_code; break; } return (0); } static int l2_to_flowrec(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int ndx) { struct pkt_data *data = prim_ptrs->data; struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls; struct pkt_primitives *p = &data->primitives; int direction = 0; if (config.nfprobe_direction) { switch (config.nfprobe_direction) { case DIRECTION_IN: case DIRECTION_OUT: direction = config.nfprobe_direction; break; case DIRECTION_TAG: if (p->tag == 1) direction = DIRECTION_IN; else if (p->tag == 2) direction = DIRECTION_OUT; break; case DIRECTION_TAG2: if (p->tag2 == 1) direction = DIRECTION_IN; else if (p->tag2 == 2) direction = DIRECTION_OUT; break; } if (direction == DIRECTION_IN) { flow->direction[ndx] = DIRECTION_IN; flow->direction[ndx ^ 1] = 0; } else if (direction == DIRECTION_OUT) { flow->direction[ndx] = DIRECTION_OUT; flow->direction[ndx ^ 1] = 0; } } #if defined HAVE_L2 memcpy(&flow->mac[ndx][0], &p->eth_shost, 6); memcpy(&flow->mac[ndx ^ 1][0], &p->eth_dhost, 6); flow->vlan = p->vlan_id; #endif if (pmpls) flow->mpls_label[ndx] = pmpls->mpls_label_top; /* handling input interface */ flow->ifindex[ndx] = 0; if (p->ifindex_in) flow->ifindex[ndx] = p->ifindex_in; if (!flow->ifindex[ndx] || config.nfprobe_ifindex_override) { if (config.nfprobe_ifindex_type && direction == DIRECTION_IN) { switch (config.nfprobe_ifindex_type) { case IFINDEX_STATIC: if (config.nfprobe_ifindex) { flow->ifindex[ndx] = config.nfprobe_ifindex; } break; case IFINDEX_TAG: if (p->tag) { flow->ifindex[ndx] = p->tag; } break; case IFINDEX_TAG2: if (p->tag2) { flow->ifindex[ndx] = p->tag2; } break; } } } /* handling output interface */ flow->ifindex[ndx ^ 1] = 0; if (p->ifindex_out) flow->ifindex[ndx ^ 1] = p->ifindex_out; if (!flow->ifindex[ndx ^ 1] || config.nfprobe_ifindex_override) { if (config.nfprobe_ifindex_type && direction == DIRECTION_OUT) { switch (config.nfprobe_ifindex_type) { case IFINDEX_STATIC: if (config.nfprobe_ifindex) { flow->ifindex[ndx ^ 1] = config.nfprobe_ifindex; } break; case IFINDEX_TAG: if (p->tag) { flow->ifindex[ndx ^ 1] = p->tag; } break; case IFINDEX_TAG2: if (p->tag2) { flow->ifindex[ndx ^ 1] = p->tag2; } break; } } } return (0); } static int l2_to_flowrec_update(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int ndx) { struct pkt_data *data = prim_ptrs->data; struct pkt_primitives *p = &data->primitives; int direction = 0; if (config.nfprobe_direction) { switch (config.nfprobe_direction) { case DIRECTION_TAG: if (p->tag == 1) direction = DIRECTION_IN; else if (p->tag == 2) direction = DIRECTION_OUT; break; case DIRECTION_TAG2: if (p->tag2 == 1) direction = DIRECTION_IN; else if (p->tag2 == 2) direction = DIRECTION_OUT; break; } if (direction == DIRECTION_IN) { if (!flow->direction[ndx]) flow->direction[ndx] = DIRECTION_IN; } else if (direction == DIRECTION_OUT) { if (!flow->direction[ndx]) flow->direction[ndx] = DIRECTION_OUT; } } return (0); } static int ASN_to_flowrec(struct FLOW *flow, struct pkt_data *data, int ndx) { struct pkt_primitives *p = &data->primitives; flow->as[ndx] = p->src_as; flow->as[ndx ^ 1] = p->dst_as; return (0); } static int cust_to_flowrec(struct FLOW *flow, u_char *pcust, int ndx) { if (pcust) { if (!flow->pcust[ndx]) flow->pcust[ndx] = malloc(config.cpptrs.len); if (flow->pcust[ndx]) memcpy(flow->pcust[ndx], pcust, config.cpptrs.len); else { Log(LOG_WARNING, "WARN ( %s/%s ): Finished memory for flow entries.\n", config.name, config.type); return PP_MALLOC_FAIL; } } else { if (flow->pcust[ndx]) free(flow->pcust[ndx]); flow->pcust[ndx] = NULL; } return (0); } static int vlen_to_flowrec(struct FLOW *flow, struct pkt_vlen_hdr_primitives *pvlen, int ndx) { if (pvlen) { /* XXX: naive and un-efficient approach copied from cache-based plugins */ if (flow->pvlen[ndx]) { vlen_prims_free(flow->pvlen[ndx]); flow->pvlen[ndx] = NULL; } flow->pvlen[ndx] = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen); } return (0); } /* Convert a IPv4 packet to a partial flow record (used for comparison) */ static int ipv4_to_flowrec(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int *isfrag, int af) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_extras *extras = prim_ptrs->pextras; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct pkt_primitives *p = &data->primitives; int ndx; /* Prepare to store flow in canonical format */ ndx = memcmp(&p->src_ip.address.ipv4, &p->dst_ip.address.ipv4, sizeof(p->src_ip.address.ipv4)) > 0 ? 1 : 0; flow->af = af; flow->addr[ndx].v4 = p->src_ip.address.ipv4; flow->addr[ndx ^ 1].v4 = p->dst_ip.address.ipv4; if (pbgp) flow->bgp_next_hop[ndx].v4 = pbgp->peer_dst_ip.address.ipv4; flow->mask[ndx] = p->src_nmask; flow->mask[ndx ^ 1] = p->dst_nmask; flow->tos[ndx] = p->tos; flow->protocol = p->proto; flow->octets[ndx] = data->pkt_len; flow->packets[ndx] = data->pkt_num; flow->flows[ndx] = data->flo_num; flow->class = p->class; #if defined (WITH_NDPI) memcpy(&flow->ndpi_class, &p->ndpi_class, sizeof(pm_class2_t)); #endif flow->tag[ndx] = p->tag; flow->tag2[ndx] = p->tag2; *isfrag = 0; l2_to_flowrec(flow, prim_ptrs, ndx); ASN_to_flowrec(flow, data, ndx); cust_to_flowrec(flow, pcust, ndx); vlen_to_flowrec(flow, pvlen, ndx); return (transport_to_flowrec(flow, data, extras, p->proto, ndx)); } static int ipv4_to_flowrec_update(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int *isfrag, int af) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct pkt_primitives *p = &data->primitives; int ndx; /* Prepare to store flow in canonical format */ ndx = memcmp(&p->src_ip.address.ipv4, &p->dst_ip.address.ipv4, sizeof(p->src_ip.address.ipv4)) > 0 ? 1 : 0; if (pbgp && !flow->bgp_next_hop[ndx].v4.s_addr) flow->bgp_next_hop[ndx].v4 = pbgp->peer_dst_ip.address.ipv4; l2_to_flowrec_update(flow, prim_ptrs, ndx); cust_to_flowrec(flow, pcust, ndx); vlen_to_flowrec(flow, pvlen, ndx); return (0); } /* Convert a IPv6 packet to a partial flow record (used for comparison) */ static int ipv6_to_flowrec(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int *isfrag, int af) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; struct pkt_extras *extras = prim_ptrs->pextras; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct pkt_primitives *p = &data->primitives; int ndx; /* Prepare to store flow in canonical format */ ndx = memcmp(&p->src_ip.address.ipv6, &p->dst_ip.address.ipv6, sizeof(p->src_ip.address.ipv6)) > 0 ? 1 : 0; flow->af = af; /* XXX: flow->ip6_flowlabel[ndx] = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; */ flow->ip6_flowlabel[ndx] = 0; flow->addr[ndx].v6 = p->src_ip.address.ipv6; flow->addr[ndx ^ 1].v6 = p->dst_ip.address.ipv6; if (pbgp) flow->bgp_next_hop[ndx].v6 = pbgp->peer_dst_ip.address.ipv6; flow->mask[ndx] = p->src_nmask; flow->mask[ndx ^ 1] = p->dst_nmask; flow->protocol = p->proto; flow->octets[ndx] = data->pkt_len; flow->packets[ndx] = data->pkt_num; flow->flows[ndx] = data->flo_num; flow->class = p->class; #if defined (WITH_NDPI) memcpy(&flow->ndpi_class, &p->ndpi_class, sizeof(pm_class2_t)); #endif flow->tag[ndx] = p->tag; flow->tag2[ndx] = p->tag2; *isfrag = 0; l2_to_flowrec(flow, prim_ptrs, ndx); ASN_to_flowrec(flow, data, ndx); cust_to_flowrec(flow, pcust, ndx); vlen_to_flowrec(flow, pvlen, ndx); return (transport_to_flowrec(flow, data, extras, p->proto, ndx)); } static int ipv6_to_flowrec_update(struct FLOW *flow, struct primitives_ptrs *prim_ptrs, int *isfrag, int af) { struct pkt_data *data = prim_ptrs->data; struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp; u_char *pcust = prim_ptrs->pcust; struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen; struct pkt_primitives *p = &data->primitives; struct in6_addr dummy_ipv6; int ndx; /* Prepare to store flow in canonical format */ memset(&dummy_ipv6, 0, sizeof(dummy_ipv6)); ndx = memcmp(&p->src_ip.address.ipv6, &p->dst_ip.address.ipv6, sizeof(p->src_ip.address.ipv6)) > 0 ? 1 : 0; if (pbgp && !memcmp(&dummy_ipv6, &flow->bgp_next_hop[ndx].v6, sizeof(dummy_ipv6))) flow->bgp_next_hop[ndx].v6 = pbgp->peer_dst_ip.address.ipv6; l2_to_flowrec_update(flow, prim_ptrs, ndx); cust_to_flowrec(flow, pcust, ndx); vlen_to_flowrec(flow, pvlen, ndx); return (0); } static void flow_update_expiry(struct FLOWTRACK *ft, struct FLOW *flow) { EXPIRY_REMOVE(EXPIRIES, &ft->expiries, flow->expiry); if (config.nfprobe_version == 9 || config.nfprobe_version == 10) { if (flow->octets[0] > (1ULL << 63) || flow->octets[1] > (1ULL << 63)) { flow->expiry->expires_at = 0; flow->expiry->reason = R_OVERBYTES; goto out; } } else { if (flow->octets[0] > (1U << 31) || flow->octets[1] > (1U << 31)) { flow->expiry->expires_at = 0; flow->expiry->reason = R_OVERBYTES; goto out; } } /* Flows over maximum life seconds */ if (ft->maximum_lifetime != 0 && flow->flow_last.tv_sec - flow->flow_start.tv_sec > ft->maximum_lifetime) { flow->expiry->expires_at = 0; flow->expiry->reason = R_MAXLIFE; goto out; } if (flow->protocol == IPPROTO_TCP) { /* Reset TCP flows */ if (ft->tcp_rst_timeout != 0 && ((flow->tcp_flags[0] & TH_RST) || (flow->tcp_flags[1] & TH_RST))) { flow->expiry->expires_at = flow->flow_last.tv_sec + ft->tcp_rst_timeout; flow->expiry->reason = R_TCP_RST; goto out; } /* Finished TCP flows */ if (ft->tcp_fin_timeout != 0 && ((flow->tcp_flags[0] & TH_FIN) && (flow->tcp_flags[1] & TH_FIN))) { flow->expiry->expires_at = flow->flow_last.tv_sec + ft->tcp_fin_timeout; flow->expiry->reason = R_TCP_FIN; goto out; } /* TCP flows */ if (ft->tcp_timeout != 0) { flow->expiry->expires_at = flow->flow_last.tv_sec + ft->tcp_timeout; flow->expiry->reason = R_TCP; goto out; } } if (ft->udp_timeout != 0 && flow->protocol == IPPROTO_UDP) { /* UDP flows */ flow->expiry->expires_at = flow->flow_last.tv_sec + ft->udp_timeout; flow->expiry->reason = R_UDP; goto out; } if (ft->icmp_timeout != 0 && ((flow->af == AF_INET && flow->protocol == IPPROTO_ICMP) || ((flow->af == AF_INET6 && flow->protocol == IPPROTO_ICMPV6)) )) { /* UDP flows */ flow->expiry->expires_at = flow->flow_last.tv_sec + ft->icmp_timeout; flow->expiry->reason = R_ICMP; goto out; } /* Everything else */ flow->expiry->expires_at = flow->flow_last.tv_sec + ft->general_timeout; flow->expiry->reason = R_GENERAL; out: EXPIRY_INSERT(EXPIRIES, &ft->expiries, flow->expiry); } void free_flow_allocs(struct FLOW *flow) { if (flow->pcust[0]) free(flow->pcust[0]); if (flow->pcust[1]) free(flow->pcust[1]); if (flow->pvlen[0]) free(flow->pvlen[0]); if (flow->pvlen[1]) free(flow->pvlen[1]); } /* * Main per-packet processing function. Take a packet (provided by * libpcap) and attempt to find a matching flow. If no such flow exists, * then create one. * * Also marks flows for fast expiry, based on flow or packet attributes * (the actual expiry is performed elsewhere) */ static int process_packet(struct FLOWTRACK *ft, struct primitives_ptrs *prim_ptrs, const struct timeval *received_time) { struct pkt_data *data = prim_ptrs->data; struct FLOW tmp, *flow; int frag, af; ft->total_packets += data->pkt_num; af = (data->primitives.src_ip.family == 0 ? AF_INET : data->primitives.src_ip.family); /* Convert the IP packet to a flow identity */ memset(&tmp, 0, sizeof(tmp)); switch (af) { case AF_INET: if (ipv4_to_flowrec(&tmp, prim_ptrs, &frag, af) == -1) goto bad; break; case AF_INET6: if (ipv6_to_flowrec(&tmp, prim_ptrs, &frag, af) == -1) goto bad; break; default: bad: ft->bad_packets += data->pkt_num; free_flow_allocs(&tmp); return (PP_BAD_PACKET); } if (frag) ft->frag_packets += data->pkt_num; /* If a matching flow does not exist, create and insert one */ if (config.nfprobe_dont_cache || ((flow = FLOW_FIND(FLOWS, &ft->flows, &tmp)) == NULL)) { /* Allocate and fill in the flow */ if ((flow = malloc(sizeof(*flow))) == NULL) return (PP_MALLOC_FAIL); memcpy(flow, &tmp, sizeof(*flow)); memcpy(&flow->flow_start, received_time, sizeof(flow->flow_start)); flow->flow_seq = ft->next_flow_seq++; FLOW_INSERT(FLOWS, &ft->flows, flow); /* Allocate and fill in the associated expiry event */ if ((flow->expiry = malloc(sizeof(*flow->expiry))) == NULL) return (PP_MALLOC_FAIL); flow->expiry->flow = flow; /* Expiration note: 0 means expire immediately */ if (!config.nfprobe_dont_cache) flow->expiry->expires_at = 1; else flow->expiry->expires_at = 0; flow->expiry->reason = R_GENERAL; EXPIRY_INSERT(EXPIRIES, &ft->expiries, flow->expiry); if (data->flo_num) ft->num_flows += data->flo_num; else ft->num_flows++; if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): ADD FLOW %s\n", config.name, config.type, format_flow_brief(flow)); } else { /* Update flow statistics */ flow->packets[0] += tmp.packets[0]; flow->octets[0] += tmp.octets[0]; flow->flows[0] += tmp.flows[0]; flow->tcp_flags[0] |= tmp.tcp_flags[0]; flow->tos[0] = tmp.tos[0]; // XXX flow->packets[1] += tmp.packets[1]; flow->octets[1] += tmp.octets[1]; flow->flows[1] += tmp.flows[1]; flow->tcp_flags[1] |= tmp.tcp_flags[1]; flow->tos[1] = tmp.tos[1]; // XXX /* Address family dependent items to update */ switch (flow->af) { case AF_INET: ipv4_to_flowrec_update(flow, prim_ptrs, &frag, af); break; case AF_INET6: ipv6_to_flowrec_update(flow, prim_ptrs, &frag, af); break; } if (!flow->class) flow->class = tmp.class; #if defined (WITH_NDPI) if (!flow->ndpi_class.app_protocol) memcpy(&flow->ndpi_class, &tmp.ndpi_class, sizeof(pm_class2_t)); #endif if (!flow->tag[0]) flow->tag[0] = tmp.tag[0]; if (!flow->tag[1]) flow->tag[1] = tmp.tag[1]; if (!flow->tag2[0]) flow->tag2[0] = tmp.tag2[0]; if (!flow->tag2[1]) flow->tag2[1] = tmp.tag2[1]; free_flow_allocs(&tmp); } memcpy(&flow->flow_last, received_time, sizeof(flow->flow_last)); if (flow->expiry->expires_at != 0) flow_update_expiry(ft, flow); return (PP_OK); } /* * Subtract two timevals. Returns (t1 - t2) in milliseconds. */ u_int32_t timeval_sub_ms(const struct timeval *t1, const struct timeval *t2) { struct timeval res; res.tv_sec = t1->tv_sec - t2->tv_sec; res.tv_usec = t1->tv_usec - t2->tv_usec; if (res.tv_usec < 0) { res.tv_usec += 1000000L; res.tv_sec--; } return ((u_int32_t)res.tv_sec * 1000 + (u_int32_t)res.tv_usec / 1000); } static void update_statistic(struct STATISTIC *s, double new, double n) { if (n == 1.0) { s->min = s->mean = s->max = new; return; } s->min = MIN(s->min, new); s->max = MAX(s->max, new); s->mean = s->mean + ((new - s->mean) / n); } /* Update global statistics */ static void update_statistics(struct FLOWTRACK *ft, struct FLOW *flow) { double tmp; static double n = 1.0; ft->flows_expired++; ft->flows_pp[flow->protocol % DEFAULT_BUCKETS]++; tmp = (double)flow->flow_last.tv_sec + ((double)flow->flow_last.tv_usec / 1000000.0); tmp -= (double)flow->flow_start.tv_sec + ((double)flow->flow_start.tv_usec / 1000000.0); if (tmp < 0.0) tmp = 0.0; update_statistic(&ft->duration, tmp, n); update_statistic(&ft->duration_pp[flow->protocol], tmp, (double)ft->flows_pp[flow->protocol % DEFAULT_BUCKETS]); tmp = flow->octets[0] + flow->octets[1]; update_statistic(&ft->octets, tmp, n); ft->octets_pp[flow->protocol % DEFAULT_BUCKETS] += tmp; tmp = flow->packets[0] + flow->packets[1]; update_statistic(&ft->packets, tmp, n); ft->packets_pp[flow->protocol % DEFAULT_BUCKETS] += tmp; n++; } static void update_expiry_stats(struct FLOWTRACK *ft, struct EXPIRY *e) { switch (e->reason) { case R_GENERAL: ft->expired_general++; break; case R_TCP: ft->expired_tcp++; break; case R_TCP_RST: ft->expired_tcp_rst++; break; case R_TCP_FIN: ft->expired_tcp_fin++; break; case R_UDP: ft->expired_udp++; break; case R_ICMP: ft->expired_icmp++; break; case R_MAXLIFE: ft->expired_maxlife++; break; case R_OVERBYTES: ft->expired_overbytes++; break; case R_OVERFLOWS: ft->expired_maxflows++; break; case R_FLUSH: ft->expired_flush++; break; } } /* How long before the next expiry event in millisecond */ static int next_expire(struct FLOWTRACK *ft) { struct EXPIRY *expiry; struct timeval now; u_int32_t expires_at, ret, fudge; gettimeofday(&now, NULL); if ((expiry = EXPIRY_MIN(EXPIRIES, &ft->expiries)) == NULL) return (-1); /* indefinite */ expires_at = expiry->expires_at; /* Don't cluster urgent expiries */ if (expires_at == 0 && (expiry->reason == R_OVERBYTES || expiry->reason == R_OVERFLOWS || expiry->reason == R_FLUSH)) return (0); /* Now */ /* Cluster expiries by expiry_interval */ if (ft->expiry_interval > 1) { if ((fudge = expires_at % ft->expiry_interval) > 0) expires_at += ft->expiry_interval - fudge; } if (expires_at < now.tv_sec) return (0); /* Now */ ret = 999 + (expires_at - now.tv_sec) * 1000; return (ret); } /* * Scan the tree of expiry events and process expired flows. If zap_all * is set, then forcibly expire all flows. */ #define CE_EXPIRE_NORMAL 0 /* Normal expiry processing */ #define CE_EXPIRE_ALL -1 /* Expire all flows immediately */ #define CE_EXPIRE_FORCED 1 /* Only expire force-expired flows */ static int check_expired(struct FLOWTRACK *ft, struct NETFLOW_TARGET *target, int ex, u_int8_t engine_type, u_int32_t engine_id) { struct FLOW **expired_flows, **oldexp; int num_expired, i, r; struct timeval now; struct EXPIRY *expiry, *nexpiry; gettimeofday(&now, NULL); r = 0; num_expired = 0; expired_flows = NULL; if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Starting expiry scan: mode %d\n", config.name, config.type, ex); for(expiry = EXPIRY_MIN(EXPIRIES, &ft->expiries); expiry != NULL; expiry = nexpiry) { nexpiry = EXPIRY_NEXT(EXPIRIES, &ft->expiries, expiry); if ((expiry->expires_at == 0) || (ex == CE_EXPIRE_ALL) || (ex != CE_EXPIRE_FORCED && (expiry->expires_at < now.tv_sec))) { /* Flow has expired */ if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Queuing flow seq:%" PRIu64 " (%p) for expiry\n", config.name, config.type, expiry->flow->flow_seq, expiry->flow); /* Add to array of expired flows */ oldexp = expired_flows; expired_flows = realloc(expired_flows, sizeof(*expired_flows) * (num_expired + 1)); /* Don't fatal on realloc failures */ if (expired_flows == NULL) expired_flows = oldexp; else { expired_flows[num_expired] = expiry->flow; num_expired++; } if (ex == CE_EXPIRE_ALL) expiry->reason = R_FLUSH; update_expiry_stats(ft, expiry); /* Remove from flow tree, destroy expiry event */ FLOW_REMOVE(FLOWS, &ft->flows, expiry->flow); EXPIRY_REMOVE(EXPIRIES, &ft->expiries, expiry); expiry->flow->expiry = NULL; free(expiry); ft->num_flows--; } } if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Finished scan %d flow(s) to be evicted\n", config.name, config.type, num_expired); /* Processing for expired flows */ if (num_expired > 0) { if (target != NULL) { if (target->fd == -1) { Log(LOG_WARNING, "WARN ( %s/%s ): No connection to collector, discarding flows\n", config.name, config.type); for (i = 0; i < num_expired; i++) { free_flow_allocs(expired_flows[i]); free(expired_flows[i]); } free(expired_flows); return -1; } else { r = target->dialect->func(expired_flows, num_expired, target->fd, target->dtls, &ft->flows_exported, &ft->system_boot_time, verbose_flag, engine_type, engine_id); if (verbose_flag) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sent %d netflow packets\n", config.name, config.type, r); } if (r > 0) { ft->packets_sent += r; /* XXX what if r < num_expired * 2 ? */ } else { ft->flows_dropped += num_expired * 2; } } } for (i = 0; i < num_expired; i++) { if (verbose_flag) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): EXPIRED: %s (%p)\n", config.name, config.type, format_flow(expired_flows[i]), expired_flows[i]); } update_statistics(ft, expired_flows[i]); free_flow_allocs(expired_flows[i]); free(expired_flows[i]); } free(expired_flows); } return (r == -1 ? -1 : num_expired); } /* * Force expiry of num_to_expire flows (e.g. when flow table overfull) */ static void force_expire(struct FLOWTRACK *ft, u_int32_t num_to_expire) { struct EXPIRY *expiry, **expiryv; int i; /* XXX move all overflow processing here (maybe) */ if (verbose_flag) Log(LOG_INFO, "INFO ( %s/%s ): Forcing expiry of %d flows\n", config.name, config.type, num_to_expire); /* * Do this in two steps, as it is dangerous to change a key on * a tree entry without first removing it and then re-adding it. * It is even worse when this has to be done during a FOREACH :) * To get around this, we make a list of expired flows and _then_ * alter them */ if ((expiryv = malloc(sizeof(*expiryv) * num_to_expire)) == NULL) { /* * On malloc failure, expire ALL flows. I assume that * setting all the keys in a tree to the same value is * safe. */ Log(LOG_ERR, "ERROR ( %s/%s ): Out of memory while expiring flows\n", config.name, config.type); EXPIRY_FOREACH(expiry, EXPIRIES, &ft->expiries) { expiry->expires_at = 0; expiry->reason = R_OVERFLOWS; ft->flows_force_expired++; } return; } /* Make the list of flows to expire */ i = 0; EXPIRY_FOREACH(expiry, EXPIRIES, &ft->expiries) { if (i >= num_to_expire) break; expiryv[i++] = expiry; } if (i < num_to_expire) { Log(LOG_ERR, "ERROR ( %s/%s ): Needed to expire %d flows, but only %d active.\n", config.name, config.type, num_to_expire, i); num_to_expire = i; } for(i = 0; i < num_to_expire; i++) { EXPIRY_REMOVE(EXPIRIES, &ft->expiries, expiryv[i]); expiryv[i]->expires_at = 0; expiryv[i]->reason = R_OVERFLOWS; EXPIRY_INSERT(EXPIRIES, &ft->expiries, expiryv[i]); } ft->flows_force_expired += num_to_expire; free(expiryv); /* XXX - this is overcomplicated, perhaps use a separate queue */ } /* * Per-packet callback function from libpcap. Pass the packet (if it is IP) * sans datalink headers to process_packet. */ static void flow_cb(u_char *user_data, struct primitives_ptrs *prim_ptrs) { struct pkt_data *data = prim_ptrs->data; struct CB_CTXT *cb_ctxt = (struct CB_CTXT *)user_data; struct timeval tv; if (data) { tv.tv_sec = data->time_start.tv_sec; tv.tv_usec = data->time_start.tv_usec; if (process_packet(cb_ctxt->ft, prim_ptrs, &tv) == PP_MALLOC_FAIL) cb_ctxt->fatal = 1; } } static void print_timeouts(struct FLOWTRACK *ft) { Log(LOG_INFO, "INFO ( %s/%s ): TCP timeout: %ds\n", config.name, config.type, ft->tcp_timeout); Log(LOG_INFO, "INFO ( %s/%s ): TCP post-RST timeout: %ds\n", config.name, config.type, ft->tcp_rst_timeout); Log(LOG_INFO, "INFO ( %s/%s ): TCP post-FIN timeout: %ds\n", config.name, config.type, ft->tcp_fin_timeout); Log(LOG_INFO, "INFO ( %s/%s ): UDP timeout: %ds\n", config.name, config.type, ft->udp_timeout); Log(LOG_INFO, "INFO ( %s/%s ): ICMP timeout: %ds\n", config.name, config.type, ft->icmp_timeout); Log(LOG_INFO, "INFO ( %s/%s ): General timeout: %ds\n", config.name, config.type, ft->general_timeout); Log(LOG_INFO, "INFO ( %s/%s ): Maximum lifetime: %ds\n", config.name, config.type, ft->maximum_lifetime); Log(LOG_INFO, "INFO ( %s/%s ): Expiry interval: %ds\n", config.name, config.type, ft->expiry_interval); } static int connsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit) { int s, ret = 0; unsigned int h6; unsigned char h4; struct sockaddr_in *in4 = (struct sockaddr_in *)addr; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr; struct sockaddr ssource_ip; if (config.nfprobe_source_ip) { ret = str_to_addr(config.nfprobe_source_ip, &config.nfprobe_source_ha); addr_to_sa(&ssource_ip, &config.nfprobe_source_ha, 0); } if ((s = socket(addr->ss_family, SOCK_DGRAM, 0)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): socket() failed: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } if (config.nfprobe_ipprec) { int opt = config.nfprobe_ipprec << 5; int rc; rc = setsockopt(s, IPPROTO_IP, IP_TOS, &opt, (socklen_t) sizeof(opt)); if (rc < 0) Log(LOG_WARNING, "WARN ( %s/%s ): setsockopt() failed for IP_TOS: %s\n", config.name, config.type, strerror(errno)); } if (config.pipe_size) { int rc, value; value = MIN(config.pipe_size, INT_MAX); rc = Setsocksize(s, SOL_SOCKET, SO_SNDBUF, &value, (socklen_t) sizeof(value)); if (rc < 0) Log(LOG_WARNING, "WARN ( %s/%s ): setsockopt() failed for SOL_SNDBUF: %s\n", config.name, config.type, strerror(errno)); } if (ret && bind(s, (struct sockaddr *) &ssource_ip, sizeof(ssource_ip)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): bind() failed: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } if (connect(s, (struct sockaddr*)addr, len) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): connect() failed: %s\n", config.name, config.type, strerror(errno)); if (errno == ENETUNREACH) { close(s); return -1; } else exit_gracefully(1); } switch (addr->ss_family) { case AF_INET: /* Default to link-local TTL for multicast addresses */ if (hoplimit == -1 && IN_MULTICAST(in4->sin_addr.s_addr)) hoplimit = 1; if (hoplimit == -1) break; h4 = hoplimit; if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &h4, (socklen_t) sizeof(h4)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): setsockopt() failed for IP_MULTICAST_TTL: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } break; case AF_INET6: /* Default to link-local hoplimit for multicast addresses */ if (hoplimit == -1 && IN6_IS_ADDR_MULTICAST(&in6->sin6_addr)) hoplimit = 1; if (hoplimit == -1) break; h6 = hoplimit; if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &h6, (socklen_t) sizeof(h6)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): setsockopt() failed for IPV6_MULTICAST_HOPS: %s\n", config.name, config.type, strerror(errno)); exit_gracefully(1); } } return(s); } static void init_flowtrack(struct FLOWTRACK *ft) { /* Set up flow-tracking structure */ memset(ft, '\0', sizeof(*ft)); ft->next_flow_seq = 1; FLOW_INIT(&ft->flows); EXPIRY_INIT(&ft->expiries); ft->tcp_timeout = DEFAULT_TCP_TIMEOUT; ft->tcp_rst_timeout = DEFAULT_TCP_RST_TIMEOUT; ft->tcp_fin_timeout = DEFAULT_TCP_FIN_TIMEOUT; ft->udp_timeout = DEFAULT_UDP_TIMEOUT; ft->icmp_timeout = DEFAULT_ICMP_TIMEOUT; ft->general_timeout = DEFAULT_GENERAL_TIMEOUT; ft->maximum_lifetime = DEFAULT_MAXIMUM_LIFETIME; ft->expiry_interval = DEFAULT_EXPIRY_INTERVAL; } static void set_timeout(struct FLOWTRACK *ft, const char *to_spec) { char *name, *value; int timeout; if ((name = strdup(to_spec)) == NULL) return; if ((value = strchr(name, '=')) == NULL || *(++value) == '\0') goto bad; *(value - 1) = '\0'; timeout = convtime(value); if (timeout < 0) { Log(LOG_ERR, "ERROR ( %s/%s ): Invalid 'nfprobe_timeouts' value: '%s'\n", config.name, config.type, value); goto free_mem; } if (strcmp(name, "tcp") == 0) ft->tcp_timeout = timeout; else if (strcmp(name, "tcp.rst") == 0) ft->tcp_rst_timeout = timeout; else if (strcmp(name, "tcp.fin") == 0) ft->tcp_fin_timeout = timeout; else if (strcmp(name, "udp") == 0) ft->udp_timeout = timeout; else if (strcmp(name, "icmp") == 0) ft->icmp_timeout = timeout; else if (strcmp(name, "general") == 0) ft->general_timeout = timeout; else if (strcmp(name, "maxlife") == 0) ft->maximum_lifetime = timeout; else if (strcmp(name, "expint") == 0) ft->expiry_interval = timeout; else { bad: Log(LOG_ERR, "ERROR ( %s/%s ): Invalid nfprobe_timeouts option: '%s'\n", config.name, config.type, name); goto free_mem; } if (ft->general_timeout == 0) { Log(LOG_ERR, "ERROR ( %s/%s ): 'general' flow timeout must be greater than zero.\n", config.name, config.type); ft->general_timeout = DEFAULT_GENERAL_TIMEOUT; goto free_mem; } free_mem: free(name); } static void handle_timeouts(struct FLOWTRACK *ft, char *to_spec) { char *sep, *current = to_spec; trim_spaces(current); while ((sep = strchr(current, ':'))) { *sep = '\0'; set_timeout(ft, current); *sep = ':'; current = ++sep; } set_timeout(ft, current); } static void parse_engine(char *s, u_int8_t *engine_type, u_int32_t *engine_id) { char *delim, *ptr; trim_spaces(s); delim = strchr(s, ':'); /* NetFlow v5 case */ if (delim) { if (config.nfprobe_version != 5) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_engine(): engine_type:engine_id is only supported on NetFlow v5 export.\n", config.name, config.type); exit_gracefully(1); } *delim = '\0'; ptr = delim+1; *engine_type = atoi(s); *engine_id = atoi(ptr); *delim = ':'; } /* NetFlow v9 / IPFIX case */ else { if (config.nfprobe_version != 9 && config.nfprobe_version != 10) { Log(LOG_ERR, "ERROR ( %s/%s ): parse_engine(): source_id is only supported on NetFlow v9/IPFIX exports.\n", config.name, config.type); exit_gracefully(1); } *engine_id = strtoul(s, &delim, 10); } } void nfprobe_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_data *data, dummy; struct pkt_bgp_primitives dummy_pbgp; struct ports_table pt; struct protos_table prt, tost; struct pollfd pfd; unsigned char *pipebuf; int refresh_timeout, ret, num, recv_budget, poll_bypass; char default_receiver[] = "127.0.0.1:2100"; char default_engine_v5[] = "0:0", default_engine_v9[] = "0"; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; int datasize = ((struct channels_list_entry *)ptr)->datasize; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; struct networks_file_data nfd; unsigned char *rgptr, *dataptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; char *capfile = NULL; int linktype = 0, i, r, err, always_v6; int max_flows, hoplimit; struct FLOWTRACK flowtrack; struct NETFLOW_TARGET target; struct CB_CTXT cb_ctxt; u_int8_t engine_type = 0; u_int32_t engine_id; char dest_addr[SRVBUFLEN], dest_serv[SRVBUFLEN]; struct sockaddr_storage dest; socklen_t dest_len; struct extra_primitives extras; struct primitives_ptrs prim_ptrs; #ifdef WITH_ZMQ struct p_zmq_host *zmq_host = &((struct channels_list_entry *)ptr)->zmq_host; #else void *zmq_host = NULL; #endif #ifdef WITH_REDIS struct p_redis_host redis_host; #endif memcpy(&config, cfgptr, sizeof(struct configuration)); memcpy(&extras, &((struct channels_list_entry *)ptr)->extras, sizeof(struct extra_primitives)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "Netflow Probe Plugin", config.name); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); if (config.logfile) { fclose(config.logfile_fd); config.logfile_fd = open_output_file(config.logfile, "a", FALSE); } if (config.proc_priority) { int ret; ret = setpriority(PRIO_PROCESS, 0, config.proc_priority); if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno); else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0)); } Log(LOG_INFO, "INFO ( %s/%s ): NetFlow probe plugin is originally based on softflowd 0.9.7 software, Copyright 2002 Damien Miller All rights reserved.\n", config.name, config.type); reload_map = FALSE; /* signal handling */ signal(SIGINT, nfprobe_exit_gracefully); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, reload_maps); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); memset(&cb_ctxt, '\0', sizeof(cb_ctxt)); memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b)); init_flowtrack(&flowtrack); memset(&dest, '\0', sizeof(dest)); memset(&target, '\0', sizeof(target)); target.fd = -1; target.dialect = &nf[0]; always_v6 = 0; glob_flowtrack = &flowtrack; if (config.nfprobe_timeouts) handle_timeouts(&flowtrack, config.nfprobe_timeouts); refresh_timeout = flowtrack.expiry_interval * 1000; print_timeouts(&flowtrack); if (!config.nfprobe_hoplimit) hoplimit = -1; else hoplimit = config.nfprobe_hoplimit; if (!config.nfprobe_maxflows) max_flows = DEFAULT_MAX_FLOWS; else max_flows = config.nfprobe_maxflows; if (config.debug) verbose_flag = TRUE; if (config.pcap_savefile) capfile = config.pcap_savefile; #ifdef WITH_GNUTLS if (config.nfprobe_dtls && !config.dtls_path) { Log(LOG_ERR, "ERROR ( %s/%s ): 'nfprobe_dtls' specified but missing 'dtls_path'. Exiting.\n", config.name, config.type); exit_gracefully(1); } if (config.dtls_path) { pm_dtls_init(&config.dtls_globs, config.dtls_path); } #endif dest_len = sizeof(dest); if (!config.nfprobe_receiver) config.nfprobe_receiver = default_receiver; parse_hostport(config.nfprobe_receiver, (struct sockaddr *)&dest, &dest_len); sort_version: for (i = 0, r = config.nfprobe_version; nf[i].version != -1; i++) { if (nf[i].version == r) break; } if (nf[i].version == -1) { config.nfprobe_version = 10; /* default to IPFIX */ goto sort_version; } target.dialect = &nf[i]; if (!config.nfprobe_engine) { if (config.nfprobe_version == 5) config.nfprobe_engine = default_engine_v5; else if (config.nfprobe_version == 9 || config.nfprobe_version == 10) config.nfprobe_engine = default_engine_v9; } parse_engine(config.nfprobe_engine, &engine_type, &engine_id); /* Netflow send socket */ if (dest.ss_family != 0) { if ((err = getnameinfo((struct sockaddr *)&dest, dest_len, dest_addr, sizeof(dest_addr), dest_serv, sizeof(dest_serv), NI_NUMERICHOST)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): getnameinfo: %d\n", config.name, config.type, err); exit_gracefully(1); } target.fd = connsock(&dest, dest_len, hoplimit); if (target.fd != -1) { Log(LOG_INFO, "INFO ( %s/%s ): Exporting flows to [%s]:%s\n", config.name, config.type, dest_addr, dest_serv); #ifdef WITH_GNUTLS if (config.nfprobe_dtls) { target.dtls = malloc(sizeof(pm_dtls_peer_t)); } #endif } } /* Main processing loop */ gettimeofday(&flowtrack.system_boot_time, NULL); cb_ctxt.ft = &flowtrack; cb_ctxt.linktype = linktype; cb_ctxt.want_v6 = target.dialect->v6_capable || always_v6; memset(&nt, 0, sizeof(nt)); memset(&nc, 0, sizeof(nc)); memset(&pt, 0, sizeof(pt)); memset(&prt, 0, sizeof(prt)); memset(&tost, 0, sizeof(tost)); memset(&dummy, 0, sizeof(dummy)); memset(&dummy_pbgp, 0, sizeof(dummy_pbgp)); load_networks(config.networks_file, &nt, &nc); set_net_funcs(&nt); if (config.ports_file) load_ports(config.ports_file, &pt); if (config.protos_file) load_protos(config.protos_file, &prt); if (config.tos_file) load_tos(config.tos_file, &tost); pipebuf = (unsigned char *) pm_malloc(config.buffer_size); memset(pipebuf, 0, config.buffer_size); if (config.pipe_zmq) P_zmq_pipe_init(zmq_host, &pipe_fd, &seq); else setnonblocking(pipe_fd); memset(&prim_ptrs, 0, sizeof(prim_ptrs)); set_primptrs_funcs(&extras); /* In case of custom primitives, let's do a round of validation */ { struct custom_primitive_ptrs *cp_entry; int cp_idx; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { cp_entry = &config.cpptrs.primitive[cp_idx]; if (!cp_entry->ptr->field_type) { Log(LOG_ERR, "ERROR ( %s/%s ): custom primitive '%s' has null field_type\n", config.name, config.type, cp_entry->ptr->name); exit_gracefully(1); } } } #ifdef WITH_REDIS if (config.redis_host) { char log_id[SHORTBUFLEN]; snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_redis_init(&redis_host, log_id, p_redis_thread_produce_common_plugin_handler); } #endif for(;;) { status->wakeup = TRUE; poll_bypass = FALSE; pfd.fd = pipe_fd; pfd.events = POLLIN; ret = poll(&pfd, (pfd.fd == ERR ? 0 : 1), refresh_timeout); /* Flags set by signal handlers or control socket */ if (graceful_shutdown_request) { #ifdef WITH_GNUTLS if (config.nfprobe_dtls) { pm_dtls_peer_t *dtls_peer = target.dtls; if (dtls_peer->conn.do_reconnect && dtls_peer->conn.stage == PM_DTLS_STAGE_UP) { pm_dtls_client_bye(dtls_peer); } if (target.fd != ERR && dtls_peer->conn.stage != PM_DTLS_STAGE_UP) { pm_dtls_client_init(target.dtls, target.fd, &dest, dest_len, config.nfprobe_dtls_verify_cert); } } #endif Log(LOG_INFO, "INFO ( %s/%s ): Shutting down on user request.\n", config.name, config.type); check_expired(&flowtrack, &target, CE_EXPIRE_ALL, engine_type, engine_id); #ifdef WITH_GNUTLS if (config.nfprobe_dtls) { pm_dtls_peer_t *dtls_peer = target.dtls; pm_dtls_client_bye(dtls_peer); } #endif goto exit_lane; } if (ret < 0) continue; /* Fatal error from per-packet functions */ if (cb_ctxt.fatal) { Log(LOG_ERR, "ERROR ( %s/%s ): Fatal error - exiting immediately.\n", config.name, config.type); break; } poll_ops: if (reload_map) { load_networks(config.networks_file, &nt, &nc); load_ports(config.ports_file, &pt); load_protos(config.protos_file, &prt); load_tos(config.tos_file, &tost); reload_map = FALSE; } if (reload_log) { reload_logs(NULL); reload_log = FALSE; } recv_budget = 0; if (poll_bypass) { poll_bypass = FALSE; goto read_data; } if (ret > 0) { /* we received data */ read_data: if (recv_budget == DEFAULT_PLUGIN_COMMON_RECV_BUDGET) { poll_bypass = TRUE; goto poll_ops; } if (config.pipe_homegrown) { if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_gracefully(1); /* we exit silently; something happened at the write end */ } if ((rg->ptr + bufsz) > rg->end) rg->ptr = rg->base; if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto handle_flow_expiration; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected (plugin_buffer_size=%" PRIu64 " plugin_pipe_size=%" PRIu64 ").\n", config.name, config.type, config.buffer_size, config.pipe_size); Log(LOG_WARNING, "WARN ( %s/%s ): Increase values or look for plugin_buffer_size, plugin_pipe_size in CONFIG-KEYS document.\n\n", config.name, config.type); } rg->ptr = (rg->base + status->last_buf_off); seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); rg->ptr += bufsz; } #ifdef WITH_ZMQ else if (config.pipe_zmq) { ret = p_zmq_topic_recv(zmq_host, pipebuf, config.buffer_size); if (ret > 0) { if (seq && (((struct ch_buf_hdr *)pipebuf)->seq != ((seq + 1) % MAX_SEQNUM))) { Log(LOG_WARNING, "WARN ( %s/%s ): Missing data detected. Sequence received=%u expected=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->seq, ((seq + 1) % MAX_SEQNUM)); } seq = ((struct ch_buf_hdr *)pipebuf)->seq; } else goto handle_flow_expiration; } #endif data = (struct pkt_data *) (pipebuf+sizeof(struct ch_buf_hdr)); if (config.debug_internal_msg) Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer received len=%" PRIu64 " seq=%u num_entries=%u\n", config.name, config.type, ((struct ch_buf_hdr *)pipebuf)->len, seq, ((struct ch_buf_hdr *)pipebuf)->num); while (((struct ch_buf_hdr *)pipebuf)->num > 0) { for (num = 0; primptrs_funcs[num]; num++) (*primptrs_funcs[num])((u_char *)data, &extras, &prim_ptrs); for (num = 0; net_funcs[num]; num++) (*net_funcs[num])(&nt, &nc, &data->primitives, prim_ptrs.pbgp, &nfd); if (config.ports_file) { if (!pt.table[data->primitives.src_port]) data->primitives.src_port = PM_L4_PORT_OTHERS; if (!pt.table[data->primitives.dst_port]) data->primitives.dst_port = PM_L4_PORT_OTHERS; } if (config.protos_file) { if (!prt.table[data->primitives.proto]) data->primitives.proto = PM_IP_PROTO_OTHERS; } if (config.tos_file) { if (!tost.table[data->primitives.tos]) data->primitives.tos = PM_IP_TOS_OTHERS; } prim_ptrs.data = data; handle_hostbyteorder_packet(data); flow_cb((void *)&cb_ctxt, &prim_ptrs); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) data; if (!prim_ptrs.vlen_next_off) dataptr += datasize; else dataptr += prim_ptrs.vlen_next_off; data = (struct pkt_data *) dataptr; } } recv_budget++; goto read_data; } handle_flow_expiration: /* * Expiry processing happens every recheck_rate seconds * or whenever we have exceeded the maximum number of active * flows */ if (flowtrack.num_flows > max_flows || next_expire(&flowtrack) == 0) { expiry_check: #ifdef WITH_GNUTLS if (config.nfprobe_dtls) { pm_dtls_peer_t *dtls_peer = target.dtls; if (dtls_peer->conn.do_reconnect && dtls_peer->conn.stage == PM_DTLS_STAGE_UP) { pm_dtls_client_bye(dtls_peer); } if (target.fd != ERR && dtls_peer->conn.stage != PM_DTLS_STAGE_UP) { pm_dtls_client_init(target.dtls, target.fd, &dest, dest_len, config.nfprobe_dtls_verify_cert); } } #endif /* * If we are reading from a capture file, we never * expire flows based on time - instead we only * expire flows when the flow table is full. */ if (check_expired(&flowtrack, &target, capfile == NULL ? CE_EXPIRE_NORMAL : CE_EXPIRE_FORCED, engine_type, engine_id) < 0) { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to export flows.\n", config.name, config.type); /* Let's try to sleep a bit and re-open the NetFlow send socket */ if (dest.ss_family != 0) { if (target.fd != -1) close(target.fd); sleep(5); target.fd = connsock(&dest, dest_len, hoplimit); if (target.fd != -1) { Log(LOG_INFO, "INFO ( %s/%s ): Exporting flows to [%s]:%s\n", config.name, config.type, dest_addr, dest_serv); } } } #ifdef WITH_GNUTLS if (config.nfprobe_dtls) { pm_dtls_peer_t *dtls_peer = target.dtls; pm_dtls_client_bye(dtls_peer); } #endif /* * If we are over max_flows, force-expire the oldest * out first and immediately reprocess to evict them */ if (flowtrack.num_flows > max_flows) { force_expire(&flowtrack, flowtrack.num_flows - max_flows); goto expiry_check; } } } exit_lane: if (!graceful_shutdown_request) Log(LOG_ERR, "ERROR ( %s/%s ): Exiting immediately on internal error.\n", config.name, config.type); if (target.fd != -1) close(target.fd); } pmacct-1.7.8/src/nfprobe_plugin/common.h0000644000175000017500000000411314354105275017252 0ustar paolopaolo/* * Copyright (c) 2002 Damien Miller. 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 THE AUTHOR ``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 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 NFPROBE_COMMON_H #define NFPROBE_COMMON_H #include "pmacct.h" #include #include #include #include #include #include #include #include #include #include #include "../../include/ip6.h" #include "../../include/ah.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_NET_BPF_H) #include #elif defined(HAVE_PCAP_BPF_H) #include #endif #endif /* NFPROBE_COMMON_H */ pmacct-1.7.8/src/nfprobe_plugin/netflow5.c0000644000175000017500000001746714354105275017540 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* * Originally based on softflowd which is: * * Copyright 2002 Damien Miller 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 THE AUTHOR ``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 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$ */ #include "common.h" #include "treetype.h" #include "nfprobe_plugin.h" /* * This is the Cisco Netflow(tm) version 5 packet format */ struct NF5_HEADER { u_int16_t version, flows; u_int32_t uptime_ms, time_sec, time_nanosec, flow_sequence; u_int8_t engine_type, engine_id; u_int16_t sampling; }; struct NF5_FLOW { u_int32_t src_ip, dest_ip, nexthop_ip; u_int16_t if_index_in, if_index_out; u_int32_t flow_packets, flow_octets; u_int32_t flow_start, flow_finish; u_int16_t src_port, dest_port; u_int8_t pad1; u_int8_t tcp_flags, protocol, tos; u_int16_t src_as, dest_as; u_int8_t src_mask, dst_mask; u_int16_t pad2; }; #ifdef WITH_GNUTLS #define NF5_MAXFLOWS 20 #else #define NF5_MAXFLOWS 30 #endif #define NF5_MAXPACKET_SIZE (sizeof(struct NF5_HEADER) + \ (NF5_MAXFLOWS * sizeof(struct NF5_FLOW))) /* * Given an array of expired flows, send netflow v5 report packets * Returns number of packets sent or -1 on error */ int send_netflow_v5(struct FLOW **flows, int num_flows, int nfsock, void *dtls, u_int64_t *flows_exported, struct timeval *system_boot_time, int verbose_flag, u_int8_t engine_type, u_int32_t engine_id) { struct timeval now; u_int32_t uptime_ms; u_int8_t packet[NF5_MAXPACKET_SIZE]; /* Maximum allowed packet size (24 flows) */ struct NF5_HEADER *hdr = NULL; struct NF5_FLOW *flw = NULL; int i, j, offset, num_packets, err, ret; socklen_t errsz; #ifdef WITH_GNUTLS pm_dtls_peer_t *dtls_peer = dtls; #endif gettimeofday(&now, NULL); uptime_ms = timeval_sub_ms(&now, system_boot_time); hdr = (struct NF5_HEADER *)packet; for(num_packets = offset = j = i = 0; i < num_flows; i++) { if (j >= NF5_MAXFLOWS - 1) { if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending NetFlow v5 packet: len = %d\n", config.name, config.type, offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (!config.nfprobe_dtls) { ret = send(nfsock, packet, (size_t)offset, 0); if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): send() failed: %s\n", config.name, config.type, strerror(errno)); return ret; } } #ifdef WITH_GNUTLS else { ret = pm_dtls_client_send(dtls_peer, packet, (size_t)offset); if (ret < 0) return ret; } #endif *flows_exported += j; j = 0; num_packets++; } if (j == 0) { memset(&packet, '\0', sizeof(packet)); hdr->version = htons(5); hdr->flows = 0; /* Filled in as we go */ hdr->uptime_ms = htonl(uptime_ms); hdr->time_sec = htonl(now.tv_sec); hdr->time_nanosec = htonl(now.tv_usec * 1000); hdr->flow_sequence = htonl(*flows_exported); hdr->engine_type = engine_type; hdr->engine_id = engine_id; if (config.sampling_rate) hdr->sampling = htons(config.sampling_rate & 0x3FFF); else if (config.ext_sampling_rate) hdr->sampling = htons(config.ext_sampling_rate & 0x3FFF); if (hdr->sampling) hdr->sampling |= (htons(1) >> 2); offset = sizeof(*hdr); } flw = (struct NF5_FLOW *)(packet + offset); /* NetFlow v.5 doesn't do IPv6 */ if (flows[i]->af != AF_INET) continue; if (flows[i]->octets[0] > 0) { u_int32_t rec32; flw->src_ip = flows[i]->addr[0].v4.s_addr; flw->dest_ip = flows[i]->addr[1].v4.s_addr; flw->src_mask = flows[i]->mask[0]; flw->dst_mask = flows[i]->mask[1]; flw->src_port = flows[i]->port[0]; flw->dest_port = flows[i]->port[1]; flw->if_index_in = htons(flows[i]->ifindex[0]); flw->if_index_out = htons(flows[i]->ifindex[1]); { as_t tmp_as; tmp_as = ntohl(flows[i]->as[0]); if (tmp_as > 65535) flw->src_as = htons(23456); else flw->src_as = htons(tmp_as); tmp_as = ntohl(flows[i]->as[1]); if (tmp_as > 65535) flw->dest_as = htons(23456); else flw->dest_as = htons(tmp_as); } rec32 = flows[i]->packets[0]; flw->flow_packets = htonl(rec32); rec32 = flows[i]->octets[0]; flw->flow_octets = htonl(rec32); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[0]; flw->protocol = flows[i]->protocol; flw->tos = flows[i]->tos[0]; offset += sizeof(*flw); j++; hdr->flows++; } flw = (struct NF5_FLOW *)(packet + offset); if (flows[i]->octets[1] > 0) { u_int32_t rec32; flw->src_ip = flows[i]->addr[1].v4.s_addr; flw->dest_ip = flows[i]->addr[0].v4.s_addr; flw->src_mask = flows[i]->mask[1]; flw->dst_mask = flows[i]->mask[0]; flw->src_port = flows[i]->port[1]; flw->dest_port = flows[i]->port[0]; flw->if_index_in = htons(flows[i]->ifindex[1]); flw->if_index_out = htons(flows[i]->ifindex[0]); { as_t tmp_as; tmp_as = ntohl(flows[i]->as[1]); if (tmp_as > 65535) flw->src_as = htons(23456); else flw->src_as = htons(tmp_as); tmp_as = ntohl(flows[i]->as[0]); if (tmp_as > 65535) flw->dest_as = htons(23456); else flw->dest_as = htons(tmp_as); } rec32 = flows[i]->packets[1]; flw->flow_packets = htonl(rec32); rec32 = flows[i]->octets[1]; flw->flow_octets = htonl(rec32); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[1]; flw->protocol = flows[i]->protocol; flw->tos = flows[i]->tos[1]; offset += sizeof(*flw); j++; hdr->flows++; } } /* Send any leftovers */ if (j != 0) { if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending NetFlow v5 packet: len = %d\n", config.name, config.type, offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (!config.nfprobe_dtls) { ret = send(nfsock, packet, (size_t)offset, 0); if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): send() failed: %s\n", config.name, config.type, strerror(errno)); return ret; } } #ifdef WITH_GNUTLS else { ret = pm_dtls_client_send(dtls_peer, packet, (size_t)offset); if (ret < 0) return ret; } #endif num_packets++; } *flows_exported += j; return (num_packets); } pmacct-1.7.8/src/nfprobe_plugin/treetype.h0000644000175000017500000000564114354105275017632 0ustar paolopaolo/* * Copyright 2002 Damien Miller 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 THE AUTHOR ``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 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$ */ /* Select our tree types for various data structures */ #if defined(FLOW_RB) #define FLOW_HEAD RB_HEAD #define FLOW_ENTRY RB_ENTRY #define FLOW_PROTOTYPE RB_PROTOTYPE #define FLOW_GENERATE RB_GENERATE #define FLOW_INSERT RB_INSERT #define FLOW_FIND RB_FIND #define FLOW_REMOVE RB_REMOVE #define FLOW_FOREACH RB_FOREACH #define FLOW_MIN RB_MIN #define FLOW_NEXT RB_NEXT #define FLOW_INIT RB_INIT #elif defined(FLOW_SPLAY) #define FLOW_HEAD SPLAY_HEAD #define FLOW_ENTRY SPLAY_ENTRY #define FLOW_PROTOTYPE SPLAY_PROTOTYPE #define FLOW_GENERATE SPLAY_GENERATE #define FLOW_INSERT SPLAY_INSERT #define FLOW_FIND SPLAY_FIND #define FLOW_REMOVE SPLAY_REMOVE #define FLOW_FOREACH SPLAY_FOREACH #define FLOW_MIN SPLAY_MIN #define FLOW_NEXT SPLAY_NEXT #define FLOW_INIT SPLAY_INIT #else #error No flow tree type defined #endif #if defined(EXPIRY_RB) #define EXPIRY_HEAD RB_HEAD #define EXPIRY_ENTRY RB_ENTRY #define EXPIRY_PROTOTYPE RB_PROTOTYPE #define EXPIRY_GENERATE RB_GENERATE #define EXPIRY_INSERT RB_INSERT #define EXPIRY_FIND RB_FIND #define EXPIRY_REMOVE RB_REMOVE #define EXPIRY_FOREACH RB_FOREACH #define EXPIRY_MIN RB_MIN #define EXPIRY_NEXT RB_NEXT #define EXPIRY_INIT RB_INIT #elif defined(EXPIRY_SPLAY) #define EXPIRY_HEAD SPLAY_HEAD #define EXPIRY_ENTRY SPLAY_ENTRY #define EXPIRY_PROTOTYPE SPLAY_PROTOTYPE #define EXPIRY_GENERATE SPLAY_GENERATE #define EXPIRY_INSERT SPLAY_INSERT #define EXPIRY_FIND SPLAY_FIND #define EXPIRY_REMOVE SPLAY_REMOVE #define EXPIRY_FOREACH SPLAY_FOREACH #define EXPIRY_MIN SPLAY_MIN #define EXPIRY_NEXT SPLAY_NEXT #define EXPIRY_INIT SPLAY_INIT #else #error No expiry tree type defined #endif pmacct-1.7.8/src/nfprobe_plugin/sys-tree.h0000644000175000017500000005421314354105275017543 0ustar paolopaolo/* $OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $ */ /* * Copyright 2002 Niels Provos * 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 THE AUTHOR ``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 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 _SYS_TREE_H_ #define _SYS_TREE_H_ /* * This file defines data structures for different types of trees: * splay trees and red-black trees. * * A splay tree is a self-organizing data structure. Every operation * on the tree causes a splay to happen. The splay moves the requested * node to the root of the tree and partly rebalances it. * * This has the benefit that request locality causes faster lookups as * the requested nodes move to the top of the tree. On the other hand, * every lookup causes memory writes. * * The Balance Theorem bounds the total access time for m operations * and n inserts on an initially empty tree as O((m + n)lg n). The * amortized cost for a sequence of m accesses to a splay tree is O(lg n); * * A red-black tree is a binary search tree with the node color as an * extra attribute. It fulfills a set of conditions: * - every search path from the root to a leaf consists of the * same number of black nodes, * - each red node (except for the root) has a black parent, * - each leaf node is black. * * Every operation on a red-black tree is bounded as O(lg n). * The maximum height of a red-black tree is 2lg (n+1). */ #define SPLAY_HEAD(name, type) \ struct name { \ struct type *sph_root; /* root of the tree */ \ } #define SPLAY_INITIALIZER(root) \ { NULL } #define SPLAY_INIT(root) do { \ (root)->sph_root = NULL; \ } while (0) #define SPLAY_ENTRY(type) \ struct { \ struct type *spe_left; /* left element */ \ struct type *spe_right; /* right element */ \ } #define SPLAY_LEFT(elm, field) (elm)->field.spe_left #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right #define SPLAY_ROOT(head) (head)->sph_root #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (0) #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ SPLAY_LEFT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (0) #define SPLAY_LINKLEFT(head, tmp, field) do { \ SPLAY_LEFT(tmp, field) = (head)->sph_root; \ tmp = (head)->sph_root; \ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ } while (0) #define SPLAY_LINKRIGHT(head, tmp, field) do { \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ tmp = (head)->sph_root; \ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ } while (0) #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ } while (0) /* Generates prototypes and inline functions */ #define SPLAY_PROTOTYPE(name, type, field, cmp) \ void name##_SPLAY(struct name *, struct type *); \ void name##_SPLAY_MINMAX(struct name *, int); \ struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ \ /* Finds the node with the same key as elm */ \ static __inline struct type * \ name##_SPLAY_FIND(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) \ return(NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) \ return (head->sph_root); \ return (NULL); \ } \ \ __attribute__((unused)) static __inline struct type * \ name##_SPLAY_NEXT(struct name *head, struct type *elm) \ { \ name##_SPLAY(head, elm); \ if (SPLAY_RIGHT(elm, field) != NULL) { \ elm = SPLAY_RIGHT(elm, field); \ while (SPLAY_LEFT(elm, field) != NULL) { \ elm = SPLAY_LEFT(elm, field); \ } \ } else \ elm = NULL; \ return (elm); \ } \ \ __attribute__((unused)) static __inline struct type * \ name##_SPLAY_MIN_MAX(struct name *head, int val) \ { \ name##_SPLAY_MINMAX(head, val); \ return (SPLAY_ROOT(head)); \ } /* Main splay operation. * Moves node close to the key of elm to top */ #define SPLAY_GENERATE(name, type, field, cmp) \ struct type * \ name##_SPLAY_INSERT(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) { \ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ } else { \ int __comp; \ name##_SPLAY(head, elm); \ __comp = (cmp)(elm, (head)->sph_root); \ if(__comp < 0) { \ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ SPLAY_RIGHT(elm, field) = (head)->sph_root; \ SPLAY_LEFT((head)->sph_root, field) = NULL; \ } else if (__comp > 0) { \ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ SPLAY_LEFT(elm, field) = (head)->sph_root; \ SPLAY_RIGHT((head)->sph_root, field) = NULL; \ } else \ return ((head)->sph_root); \ } \ (head)->sph_root = (elm); \ return (NULL); \ } \ \ struct type * \ name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ { \ struct type *__tmp; \ if (SPLAY_EMPTY(head)) \ return (NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) { \ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ } else { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ name##_SPLAY(head, elm); \ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ } \ return (elm); \ } \ return (NULL); \ } \ \ void \ name##_SPLAY(struct name *head, struct type *elm) \ { \ struct type __node, *__left, *__right, *__tmp; \ int __comp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while ((__comp = (cmp)(elm, (head)->sph_root))) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) > 0){ \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } \ \ /* Splay with either the minimum or the maximum element \ * Used to find minimum or maximum element in tree. \ */ \ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ { \ struct type __node, *__left, *__right, *__tmp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while (1) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp > 0) { \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } #define SPLAY_NEGINF -1 #define SPLAY_INF 1 #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) #define SPLAY_FOREACH(x, name, head) \ for ((x) = SPLAY_MIN(name, head); \ (x) != NULL; \ (x) = SPLAY_NEXT(name, head, x)) /* Macros that define a red-back tree */ #define RB_HEAD(name, type) \ struct name { \ struct type *rbh_root; /* root of the tree */ \ } #define RB_INITIALIZER(root) \ { NULL } #define RB_INIT(root) do { \ (root)->rbh_root = NULL; \ } while (0) #define RB_BLACK 0 #define RB_RED 1 #define RB_ENTRY(type) \ struct { \ struct type *rbe_left; /* left element */ \ struct type *rbe_right; /* right element */ \ struct type *rbe_parent; /* parent element */ \ int rbe_color; /* node color */ \ } #define RB_LEFT(elm, field) (elm)->field.rbe_left #define RB_RIGHT(elm, field) (elm)->field.rbe_right #define RB_PARENT(elm, field) (elm)->field.rbe_parent #define RB_COLOR(elm, field) (elm)->field.rbe_color #define RB_ROOT(head) (head)->rbh_root #define RB_EMPTY(head) (RB_ROOT(head) == NULL) #define RB_SET(elm, parent, field) do { \ RB_PARENT(elm, field) = parent; \ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ RB_COLOR(elm, field) = RB_RED; \ } while (0) #define RB_SET_BLACKRED(black, red, field) do { \ RB_COLOR(black, field) = RB_BLACK; \ RB_COLOR(red, field) = RB_RED; \ } while (0) #ifndef RB_AUGMENT #define RB_AUGMENT(x) #endif #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ (tmp) = RB_RIGHT(elm, field); \ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ RB_AUGMENT(RB_PARENT(elm, field)); \ } else \ (head)->rbh_root = (tmp); \ RB_LEFT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ } while (0) #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ (tmp) = RB_LEFT(elm, field); \ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ RB_AUGMENT(RB_PARENT(elm, field)); \ } else \ (head)->rbh_root = (tmp); \ RB_RIGHT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ } while (0) /* Generates prototypes and inline functions */ #define RB_PROTOTYPE(name, type, field, cmp) \ void name##_RB_INSERT_COLOR(struct name *, struct type *); \ void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ struct type *name##_RB_REMOVE(struct name *, struct type *); \ struct type *name##_RB_INSERT(struct name *, struct type *); \ struct type *name##_RB_FIND(struct name *, struct type *); \ struct type *name##_RB_NEXT(struct name *, struct type *); \ struct type *name##_RB_MINMAX(struct name *, int); \ \ /* Main rb operation. * Moves node close to the key of elm to top */ #define RB_GENERATE(name, type, field, cmp) \ void \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ { \ struct type *parent, *gparent, *tmp; \ while ((parent = RB_PARENT(elm, field)) && \ RB_COLOR(parent, field) == RB_RED) { \ gparent = RB_PARENT(parent, field); \ if (parent == RB_LEFT(gparent, field)) { \ tmp = RB_RIGHT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_RIGHT(parent, field) == elm) { \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_RIGHT(head, gparent, tmp, field); \ } else { \ tmp = RB_LEFT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_LEFT(parent, field) == elm) { \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_LEFT(head, gparent, tmp, field); \ } \ } \ RB_COLOR(head->rbh_root, field) = RB_BLACK; \ } \ \ void \ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ { \ struct type *tmp; \ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ elm != RB_ROOT(head)) { \ if (RB_LEFT(parent, field) == elm) { \ tmp = RB_RIGHT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = RB_RIGHT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ struct type *oleft; \ if ((oleft = RB_LEFT(tmp, field)))\ RB_COLOR(oleft, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_RIGHT(head, tmp, oleft, field);\ tmp = RB_RIGHT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_RIGHT(tmp, field)) \ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_LEFT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } else { \ tmp = RB_LEFT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = RB_LEFT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ struct type *oright; \ if ((oright = RB_RIGHT(tmp, field)))\ RB_COLOR(oright, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_LEFT(head, tmp, oright, field);\ tmp = RB_LEFT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_LEFT(tmp, field)) \ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_RIGHT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } \ } \ if (elm) \ RB_COLOR(elm, field) = RB_BLACK; \ } \ \ struct type * \ name##_RB_REMOVE(struct name *head, struct type *elm) \ { \ struct type *child, *parent, *old = elm; \ int color; \ if (RB_LEFT(elm, field) == NULL) \ child = RB_RIGHT(elm, field); \ else if (RB_RIGHT(elm, field) == NULL) \ child = RB_LEFT(elm, field); \ else { \ struct type *left; \ elm = RB_RIGHT(elm, field); \ while ((left = RB_LEFT(elm, field))) \ elm = left; \ child = RB_RIGHT(elm, field); \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ if (RB_PARENT(elm, field) == old) \ parent = elm; \ (elm)->field = (old)->field; \ if (RB_PARENT(old, field)) { \ if (RB_LEFT(RB_PARENT(old, field), field) == old)\ RB_LEFT(RB_PARENT(old, field), field) = elm;\ else \ RB_RIGHT(RB_PARENT(old, field), field) = elm;\ RB_AUGMENT(RB_PARENT(old, field)); \ } else \ RB_ROOT(head) = elm; \ RB_PARENT(RB_LEFT(old, field), field) = elm; \ if (RB_RIGHT(old, field)) \ RB_PARENT(RB_RIGHT(old, field), field) = elm; \ if (parent) { \ left = parent; \ do { \ RB_AUGMENT(left); \ } while ((left = RB_PARENT(left, field))); \ } \ goto color; \ } \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ color: \ if (color == RB_BLACK) \ name##_RB_REMOVE_COLOR(head, parent, child); \ return (old); \ } \ \ /* Inserts a node into the RB tree */ \ struct type * \ name##_RB_INSERT(struct name *head, struct type *elm) \ { \ struct type *tmp; \ struct type *parent = NULL; \ int comp = 0; \ tmp = RB_ROOT(head); \ while (tmp) { \ parent = tmp; \ comp = (cmp)(elm, parent); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ RB_SET(elm, parent, field); \ if (parent != NULL) { \ if (comp < 0) \ RB_LEFT(parent, field) = elm; \ else \ RB_RIGHT(parent, field) = elm; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = elm; \ name##_RB_INSERT_COLOR(head, elm); \ return (NULL); \ } \ \ /* Finds the node with the same key as elm */ \ struct type * \ name##_RB_FIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (NULL); \ } \ \ struct type * \ name##_RB_NEXT(struct name *head, struct type *elm) \ { \ if (RB_RIGHT(elm, field)) { \ elm = RB_RIGHT(elm, field); \ while (RB_LEFT(elm, field)) \ elm = RB_LEFT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ struct type * \ name##_RB_MINMAX(struct name *head, int val) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *parent = NULL; \ while (tmp) { \ parent = tmp; \ if (val < 0) \ tmp = RB_LEFT(tmp, field); \ else \ tmp = RB_RIGHT(tmp, field); \ } \ return (parent); \ } #define RB_NEGINF -1 #define RB_INF 1 #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) #define RB_FIND(name, x, y) name##_RB_FIND(x, y) #define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) #define RB_FOREACH(x, name, head) \ for ((x) = RB_MIN(name, head); \ (x) != NULL; \ (x) = name##_RB_NEXT(head, x)) #endif /* _SYS_TREE_H_ */ pmacct-1.7.8/src/nfprobe_plugin/netflow9.c0000644000175000017500000030200414354105275017524 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* * Originally based on softflowd which is: * * Copyright 2002 Damien Miller 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 THE AUTHOR ``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 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$ */ #include "common.h" #include "treetype.h" #include "nfprobe_plugin.h" #include "ip_flow.h" #include "classifier.h" /* Netflow v.9 */ struct NF9_HEADER { u_int16_t version, flows; u_int32_t uptime_ms, time_sec; u_int32_t package_sequence, source_id; } __attribute__ ((packed)); struct IPFIX_HEADER { u_int16_t version, len; u_int32_t time_sec; u_int32_t package_sequence, source_id; } __attribute__ ((packed)); struct NF9_FLOWSET_HEADER_COMMON { u_int16_t flowset_id, length; } __attribute__ ((packed)); struct NF9_TEMPLATE_FLOWSET_HEADER { struct NF9_FLOWSET_HEADER_COMMON c; u_int16_t template_id, count; } __attribute__ ((packed)); struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER { struct NF9_FLOWSET_HEADER_COMMON c; u_int16_t template_id, scope_len; u_int16_t option_len; } __attribute__ ((packed)); struct NF9_TEMPLATE_FLOWSET_RECORD { u_int16_t type, length; } __attribute__ ((packed)); struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD { u_int16_t type; u_int16_t length; u_int32_t pen; } __attribute__ ((packed)); struct NF9_DATA_FLOWSET_HEADER { struct NF9_FLOWSET_HEADER_COMMON c; } __attribute__ ((packed)); #define NF9_TEMPLATE_FLOWSET_ID 0 #define NF9_OPTIONS_FLOWSET_ID 1 #define IPFIX_TEMPLATE_FLOWSET_ID 2 #define IPFIX_OPTIONS_FLOWSET_ID 3 #define IPFIX_VLEN_REC_SHORT 1 #define IPFIX_VLEN_REC_LONG 2 #define IPFIX_VLEN_REC_SHORT_MAXLEN 254 /* rfc 5101 says less than 255 octets */ #define NF9_MIN_RECORD_FLOWSET_ID 256 #define PMACCT_PEN 43874 #define IPFIX_PEN_LEN 4 #define IPFIX_TPL_EBIT 0x8000 /* IPFIX telmplate enterprise bit */ #define IPFIX_VARIABLE_LENGTH 65535 #define NULL_CHAR_LEN 1 /* Flowset record types the we care about */ #define NF9_IN_BYTES 1 #define NF9_IN_PACKETS 2 #define NF9_FLOWS 3 #define NF9_IN_PROTOCOL 4 #define NF9_SRC_TOS 5 #define NF9_TCP_FLAGS 6 #define NF9_L4_SRC_PORT 7 #define NF9_IPV4_SRC_ADDR 8 #define NF9_SRC_MASK 9 #define NF9_INPUT_SNMP 10 /* ... */ #define NF9_L4_DST_PORT 11 #define NF9_IPV4_DST_ADDR 12 #define NF9_DST_MASK 13 #define NF9_OUTPUT_SNMP 14 /* ... */ #define NF9_SRC_AS 16 #define NF9_DST_AS 17 #define NF9_BGP_IPV4_NEXT_HOP 18 /* ... */ #define NF9_LAST_SWITCHED 21 #define NF9_FIRST_SWITCHED 22 #define NF9_OUT_BYTES 23 #define NF9_OUT_PACKETS 24 /* ... */ #define NF9_IPV6_SRC_ADDR 27 #define NF9_IPV6_DST_ADDR 28 #define NF9_IPV6_SRC_MASK 29 #define NF9_IPV6_DST_MASK 30 /* ... */ #define NF9_FLOW_SAMPLER_ID 48 #define NF9_FLOW_SAMPLER_MODE 49 #define NF9_FLOW_SAMPLER_INTERVAL 50 #define NF9_IN_SRC_MAC 56 // #define NF9_OUT_DST_MAC 57 #define NF9_SRC_VLAN 58 #define NF9_DST_VLAN 59 #define NF9_IP_PROTOCOL_VERSION 60 #define NF9_DIRECTION 61 /* ... */ #define NF9_BGP_IPV6_NEXT_HOP 63 /* ... */ #define NF9_MPLS_LABEL_1 70 /* ... */ #define NF9_IN_DST_MAC 80 // #define NF9_OUT_SRC_MAC 81 /* ... */ #define NF9_FLOW_APPLICATION_DESC 94 #define NF9_FLOW_APPLICATION_ID 95 #define NF9_FLOW_APPLICATION_NAME 96 /* ... */ #define NF9_EXPORTER_IPV4_ADDRESS 130 #define NF9_EXPORTER_IPV6_ADDRESS 131 /* ... */ #define NF9_FLOW_EXPORTER 144 /* ... */ #define NF9_FIRST_SWITCHED_MSEC 152 #define NF9_LAST_SWITCHED_MSEC 153 #define NF9_FIRST_SWITCHED_USEC 154 #define NF9_LAST_SWITCHED_USEC 155 /* ... */ /* CUSTOM TYPES START HERE: supported in IPFIX only with pmacct PEN */ #define NF9_CUST_TAG 1 #define NF9_CUST_TAG2 2 #define NF9_CUST_LABEL 3 /* CUSTOM TYPES END HERE */ /* OPTION SCOPES */ #define NF9_OPT_SCOPE_SYSTEM 1 /* Stuff pertaining to the templates that softflowd uses */ #define NF9_SOFTFLOWD_TEMPLATE_NRECORDS 35 struct NF9_SOFTFLOWD_TEMPLATE { struct NF9_TEMPLATE_FLOWSET_HEADER h; struct NF9_TEMPLATE_FLOWSET_RECORD r[NF9_SOFTFLOWD_TEMPLATE_NRECORDS]; u_int16_t tot_len; } __attribute__ ((packed)); struct IPFIX_PEN_TEMPLATE_ADDENDUM { struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD r[NF9_SOFTFLOWD_TEMPLATE_NRECORDS]; u_int16_t tot_len; } __attribute__ ((packed)); #define NF9_OPTIONS_TEMPLATE_NRECORDS 4 struct NF9_OPTIONS_TEMPLATE { struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER h; struct NF9_TEMPLATE_FLOWSET_RECORD r[NF9_OPTIONS_TEMPLATE_NRECORDS]; u_int16_t tot_len; } __attribute__ ((packed)); typedef int (*flow_to_flowset_handler) (char *, const struct FLOW *, int, int); struct NF9_INTERNAL_TEMPLATE_RECORD { flow_to_flowset_handler handler; u_int16_t length; }; struct NF9_INTERNAL_TEMPLATE { struct NF9_INTERNAL_TEMPLATE_RECORD r[NF9_SOFTFLOWD_TEMPLATE_NRECORDS]; u_int16_t tot_rec_len; }; struct NF9_INTERNAL_OPTIONS_TEMPLATE { struct NF9_INTERNAL_TEMPLATE_RECORD r[NF9_OPTIONS_TEMPLATE_NRECORDS]; u_int16_t tot_rec_len; }; /* Local data: templates and counters */ #define NF9_SOFTFLOWD_MAX_PACKET_SIZE 512 #define NF9_SOFTFLOWD_V4_TEMPLATE_ID 1024 #define NF9_SOFTFLOWD_V6_TEMPLATE_ID 2048 #define NF9_OPTIONS_TEMPLATE_ID 4096 #define NF9_DEFAULT_TEMPLATE_INTERVAL 18 static struct NF9_SOFTFLOWD_TEMPLATE v4_template; static struct IPFIX_PEN_TEMPLATE_ADDENDUM v4_pen_template; static struct NF9_INTERNAL_TEMPLATE v4_int_template; static struct NF9_INTERNAL_TEMPLATE v4_pen_int_template; static struct NF9_SOFTFLOWD_TEMPLATE v4_template_out; static struct IPFIX_PEN_TEMPLATE_ADDENDUM v4_pen_template_out; static struct NF9_INTERNAL_TEMPLATE v4_int_template_out; static struct NF9_INTERNAL_TEMPLATE v4_pen_int_template_out; static struct NF9_SOFTFLOWD_TEMPLATE v6_template; static struct IPFIX_PEN_TEMPLATE_ADDENDUM v6_pen_template; static struct NF9_INTERNAL_TEMPLATE v6_int_template; static struct NF9_INTERNAL_TEMPLATE v6_pen_int_template; static struct NF9_SOFTFLOWD_TEMPLATE v6_template_out; static struct IPFIX_PEN_TEMPLATE_ADDENDUM v6_pen_template_out; static struct NF9_INTERNAL_TEMPLATE v6_int_template_out; static struct NF9_INTERNAL_TEMPLATE v6_pen_int_template_out; static struct NF9_OPTIONS_TEMPLATE sampling_option_template; static struct NF9_INTERNAL_OPTIONS_TEMPLATE sampling_option_int_template; static struct NF9_OPTIONS_TEMPLATE class_option_template; static struct NF9_INTERNAL_OPTIONS_TEMPLATE class_option_int_template; static struct NF9_OPTIONS_TEMPLATE exporter_option_template; static struct NF9_INTERNAL_OPTIONS_TEMPLATE exporter_option_int_template; static char ftoft_buf_0[NF9_SOFTFLOWD_MAX_PACKET_SIZE*2]; static char ftoft_buf_1[NF9_SOFTFLOWD_MAX_PACKET_SIZE*2]; static char packet[NF9_SOFTFLOWD_MAX_PACKET_SIZE]; static int nf9_pkts_until_template = -1; static u_int8_t send_options = FALSE; static u_int8_t send_sampling_option = FALSE; static u_int8_t send_class_option = FALSE; static u_int8_t send_exporter_option = FALSE; static int flow_to_flowset_input_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int32_t rec32, tmp32; rec32 = flow->ifindex[idx]; tmp32 = htonl(rec32); memcpy(flowset, &tmp32, size); return 0; } static int flow_to_flowset_output_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int32_t rec32, tmp32; rec32 = flow->ifindex[idx ^ 1]; tmp32 = htonl(rec32); memcpy(flowset, &tmp32, size); return 0; } static int flow_to_flowset_direction_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int8_t rec8; rec8 = flow->direction[idx] ? (flow->direction[idx]-1) : 0; memcpy(flowset, &rec8, size); return 0; } static int flow_to_flowset_flows_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int32_t rec32; rec32 = htonl(flow->flows[idx]); memcpy(flowset, &rec32, size); return 0; } static int flow_to_flowset_src_host_v4_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->addr[idx].v4, size); return 0; } static int flow_to_flowset_dst_host_v4_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->addr[idx ^ 1].v4, size); return 0; } static int flow_to_flowset_bgp_next_hop_v4_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->bgp_next_hop[idx].v4, size); return 0; } static int flow_to_flowset_src_nmask_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->mask[idx], size); return 0; } static int flow_to_flowset_dst_nmask_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->mask[idx ^ 1], size); return 0; } static int flow_to_flowset_src_host_v6_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->addr[idx].v6, size); return 0; } static int flow_to_flowset_dst_host_v6_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->addr[idx ^ 1].v6, size); return 0; } static int flow_to_flowset_bgp_next_hop_v6_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->bgp_next_hop[idx].v6, size); return 0; } static int flow_to_flowset_src_port_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->port[idx], size); return 0; } static int flow_to_flowset_dst_port_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->port[idx ^ 1], size); return 0; } static int flow_to_flowset_ip_tos_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->tos[idx], size); return 0; } static int flow_to_flowset_tcp_flags_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->tcp_flags[idx], size); return 0; } static int flow_to_flowset_ip_proto_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->protocol, size); return 0; } static int flow_to_flowset_src_as_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->as[idx], size); return 0; } static int flow_to_flowset_dst_as_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->as[idx ^ 1], size); return 0; } static int flow_to_flowset_src_mac_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->mac[idx], size); return 0; } static int flow_to_flowset_dst_mac_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->mac[idx ^ 1], size); return 0; } static int flow_to_flowset_vlan_handler(char *flowset, const struct FLOW *flow, int idx, int size) { memcpy(flowset, &flow->vlan, size); return 0; } static int flow_to_flowset_mpls_label_top_handler(char *flowset, const struct FLOW *flow, int idx, int size) { encode_mpls_label(flowset, flow->mpls_label[idx]); // memcpy(flowset, &flow->mpls_label[idx], size); return 0; } #if defined (WITH_NDPI) static int flow_to_flowset_ndpi_class_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int8_t ie95_classId = 0x16; /* nDPI */ u_int32_t ie95_selectId = htonl(flow->ndpi_class.app_protocol); if (size == 5) { memcpy(flowset, &ie95_classId, 1); memcpy((flowset + 1), &ie95_selectId, 4); } return 0; } #endif static int flow_to_flowset_tag_handler(char *flowset, const struct FLOW *flow, int idx, int size) { pm_id_t tag; tag = pm_htonll(flow->tag[idx]); memcpy(flowset, &tag, size); return 0; } static int flow_to_flowset_tag2_handler(char *flowset, const struct FLOW *flow, int idx, int size) { pm_id_t tag; tag = pm_htonll(flow->tag2[idx]); memcpy(flowset, &tag, size); return 0; } static int flow_to_flowset_label_handler(char *flowset, const struct FLOW *flow, int idx, int size) { char null_char = '\0', *label_ptr = NULL; int add_len = IPFIX_VLEN_REC_SHORT; u_int8_t len = 0; vlen_prims_get(flow->pvlen[idx], COUNT_INT_LABEL, &label_ptr); if (!label_ptr) { len = NULL_CHAR_LEN; label_ptr = &null_char; } else len = MIN(IPFIX_VLEN_REC_SHORT_MAXLEN, strlen(label_ptr) + 1); // XXX: check available len? add_len += len; memcpy(flowset, &len, IPFIX_VLEN_REC_SHORT); flowset += IPFIX_VLEN_REC_SHORT; memcpy(flowset, label_ptr, len); flowset[len] = '\0'; return add_len; } static int flow_to_flowset_sampler_id_handler(char *flowset, const struct FLOW *flow, int idx, int size) { u_int8_t rec8; rec8 = 1; memcpy(flowset, &rec8, size); return 0; } static int flow_to_flowset_cp_handler(char *flowset, const struct FLOW *flow, int idx, int size) { struct custom_primitive_ptrs *cp_entry; char *label_ptr, null_char = '\0'; int cp_idx, add_len = 0; u_int8_t len = 0; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { cp_entry = &config.cpptrs.primitive[cp_idx]; if (!cp_entry->ptr->pen) { if (cp_entry->ptr->len != PM_VARIABLE_LENGTH) { if (flow->pcust[idx] && cp_entry->ptr->field_type) { if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { serialize_bin((flow->pcust[idx] + cp_entry->off), (u_char *)flowset, strlen((char *)(flow->pcust[idx] + cp_entry->off))); } else { memcpy(flowset, (flow->pcust[idx] + cp_entry->off), cp_entry->ptr->len); } } else { memset(flowset, 0, cp_entry->ptr->len); } flowset += cp_entry->ptr->len; } else { if (config.nfprobe_version == 10) { vlen_prims_get(flow->pvlen[idx], cp_entry->ptr->type, &label_ptr); if (!label_ptr) { len = NULL_CHAR_LEN; label_ptr = &null_char; } else len = MIN(IPFIX_VLEN_REC_SHORT_MAXLEN, strlen(label_ptr) + 1); // XXX: check available len? memcpy(flowset, &len, IPFIX_VLEN_REC_SHORT); flowset += IPFIX_VLEN_REC_SHORT; add_len += IPFIX_VLEN_REC_SHORT; memcpy(flowset, label_ptr, len); flowset[len] = '\0'; flowset += len; add_len += len; } } } } return add_len; } static int flow_to_flowset_cp_pen_handler(char *flowset, const struct FLOW *flow, int idx, int size) { struct custom_primitive_ptrs *cp_entry; char *label_ptr, null_char = '\0'; int cp_idx, add_len = 0; u_int8_t len = 0; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { cp_entry = &config.cpptrs.primitive[cp_idx]; if (config.nfprobe_version == 10 && cp_entry->ptr->pen) { if (cp_entry->ptr->len != PM_VARIABLE_LENGTH) { if (flow->pcust[idx] && cp_entry->ptr->field_type) { if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { serialize_bin((flow->pcust[idx] + cp_entry->off), (u_char *)flowset, strlen((char *)(flow->pcust[idx] + cp_entry->off))); } else { memcpy(flowset, (flow->pcust[idx] + cp_entry->off), cp_entry->ptr->len); } } else { memset(flowset, 0, cp_entry->ptr->len); } flowset += cp_entry->ptr->len; } else { vlen_prims_get(flow->pvlen[idx], cp_entry->ptr->type, &label_ptr); if (!label_ptr) { len = NULL_CHAR_LEN; label_ptr = &null_char; } else len = MIN(IPFIX_VLEN_REC_SHORT_MAXLEN, strlen(label_ptr) + 1); // XXX: check available len? memcpy(flowset, &len, IPFIX_VLEN_REC_SHORT); flowset += IPFIX_VLEN_REC_SHORT; add_len += IPFIX_VLEN_REC_SHORT; memcpy(flowset, label_ptr, len); flowset[len] = '\0'; flowset += len; add_len += len; } } } return add_len; } int nf9_init_cp_template(struct NF9_SOFTFLOWD_TEMPLATE *tpl, struct NF9_SOFTFLOWD_TEMPLATE *tpl_out, struct NF9_INTERNAL_TEMPLATE *tpl_int, struct NF9_INTERNAL_TEMPLATE *tpl_int_out, int rcount) { struct NF9_INTERNAL_TEMPLATE_RECORD *cp_first_record = NULL, *cp_first_record_out = NULL; struct custom_primitive_ptrs *cp_entry; int cp_idx, cp_first = FALSE, cp_len = 0; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { cp_entry = &config.cpptrs.primitive[cp_idx]; if (cp_entry->ptr->field_type) { if (!cp_entry->ptr->pen) { if (cp_entry->ptr->len != PM_VARIABLE_LENGTH || config.nfprobe_version == 10) { tpl->r[rcount].type = htons(cp_entry->ptr->field_type); tpl->r[rcount].length = htons(cp_entry->ptr->len); tpl_int->r[rcount].length = 0; tpl_out->r[rcount].type = htons(cp_entry->ptr->field_type); tpl_out->r[rcount].length = htons(cp_entry->ptr->len); tpl_int_out->r[rcount].length = 0; cp_len += cp_entry->ptr->len; if (!cp_first) { tpl_int->r[rcount].handler = flow_to_flowset_cp_handler; tpl_int_out->r[rcount].handler = flow_to_flowset_cp_handler; cp_first_record = &tpl_int->r[rcount]; cp_first_record_out = &tpl_int_out->r[rcount]; cp_first = TRUE; } else { tpl_int->r[rcount].handler = NULL; tpl_int_out->r[rcount].handler = NULL; } rcount++; } } } } if (cp_first_record) cp_first_record->length = cp_len; if (cp_first_record_out) cp_first_record_out->length = cp_len; return rcount; } int nf9_init_cp_pen_template(struct IPFIX_PEN_TEMPLATE_ADDENDUM *tpl, struct IPFIX_PEN_TEMPLATE_ADDENDUM *tpl_out, struct NF9_INTERNAL_TEMPLATE *tpl_int, struct NF9_INTERNAL_TEMPLATE *tpl_int_out, int rcount_pen) { struct NF9_INTERNAL_TEMPLATE_RECORD *cp_pen_first_record = NULL, *cp_pen_first_record_out = NULL; struct custom_primitive_ptrs *cp_entry; int cp_idx, cp_pen_first = FALSE, cp_pen_len = 0; for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) { cp_entry = &config.cpptrs.primitive[cp_idx]; if (config.nfprobe_version == 10 && cp_entry->ptr->pen) { tpl->r[rcount_pen].type = htons(IPFIX_TPL_EBIT | cp_entry->ptr->field_type); tpl->r[rcount_pen].pen = htonl(cp_entry->ptr->pen); tpl->r[rcount_pen].length = htons(cp_entry->ptr->len); tpl_int->r[rcount_pen].length = 0; tpl_out->r[rcount_pen].type = htons(IPFIX_TPL_EBIT | cp_entry->ptr->field_type); tpl_out->r[rcount_pen].pen = htonl(cp_entry->ptr->pen); tpl_out->r[rcount_pen].length = htons(cp_entry->ptr->len); tpl_int_out->r[rcount_pen].length = 0; cp_pen_len += cp_entry->ptr->len; if (!cp_pen_first) { tpl_int->r[rcount_pen].handler = flow_to_flowset_cp_pen_handler; tpl_int_out->r[rcount_pen].handler = flow_to_flowset_cp_pen_handler; cp_pen_first_record = &tpl_int->r[rcount_pen]; cp_pen_first_record_out = &tpl_int_out->r[rcount_pen]; cp_pen_first = TRUE; } else { tpl_int->r[rcount_pen].handler = NULL; tpl_int_out->r[rcount_pen].handler = NULL; } rcount_pen++; } } if (cp_pen_first_record) cp_pen_first_record->length = cp_pen_len; if (cp_pen_first_record_out) cp_pen_first_record_out->length = cp_pen_len; return rcount_pen; } static void nf9_init_template(void) { int rcount, rcount_pen, idx, flowset_id = 0; /* Let's enforce some defaults; if we are launched without an * aggregation, then let's choose one. If we don't have one or * more flow-distinguishing primitives, then let's add flow * aggregation info to the template */ if (!config.nfprobe_what_to_count && !config.nfprobe_what_to_count_2) { config.nfprobe_what_to_count |= COUNT_SRC_HOST; config.nfprobe_what_to_count |= COUNT_DST_HOST; config.nfprobe_what_to_count |= COUNT_SRC_PORT; config.nfprobe_what_to_count |= COUNT_DST_PORT; config.nfprobe_what_to_count |= COUNT_IP_PROTO; config.nfprobe_what_to_count |= COUNT_IP_TOS; } rcount = 0; rcount_pen = 0; bzero(&v4_template, sizeof(v4_template)); bzero(&v4_int_template, sizeof(v4_int_template)); bzero(&v4_pen_template, sizeof(v4_pen_template)); bzero(&v4_pen_int_template, sizeof(v4_pen_int_template)); bzero(&v4_template_out, sizeof(v4_template_out)); bzero(&v4_int_template_out, sizeof(v4_int_template_out)); bzero(&v4_pen_template_out, sizeof(v4_pen_template_out)); bzero(&v4_pen_int_template_out, sizeof(v4_pen_int_template_out)); if (config.nfprobe_version == 9) flowset_id = NF9_TEMPLATE_FLOWSET_ID; else if (config.nfprobe_version == 10) flowset_id = IPFIX_TEMPLATE_FLOWSET_ID; if (config.nfprobe_version == 9 && config.timestamps_secs) { v4_template.r[rcount].type = htons(NF9_LAST_SWITCHED); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].length = 4; rcount++; v4_template.r[rcount].type = htons(NF9_FIRST_SWITCHED); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].length = 4; rcount++; } else if ((config.nfprobe_version == 9 && !config.timestamps_secs) || config.nfprobe_version == 10) { if (!config.nfprobe_tstamp_usec) { v4_template.r[rcount].type = htons(NF9_LAST_SWITCHED_MSEC); v4_template.r[rcount].length = htons(8); v4_int_template.r[rcount].length = 8; v4_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED_MSEC); v4_template_out.r[rcount].length = htons(8); v4_int_template_out.r[rcount].length = 8; rcount++; v4_template.r[rcount].type = htons(NF9_FIRST_SWITCHED_MSEC); v4_template.r[rcount].length = htons(8); v4_int_template.r[rcount].length = 8; v4_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED_MSEC); v4_template_out.r[rcount].length = htons(8); v4_int_template_out.r[rcount].length = 8; rcount++; } else { v4_template.r[rcount].type = htons(NF9_LAST_SWITCHED_USEC); v4_template.r[rcount].length = htons(16); v4_int_template.r[rcount].length = 16; v4_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED_USEC); v4_template_out.r[rcount].length = htons(16); v4_int_template_out.r[rcount].length = 16; rcount++; v4_template.r[rcount].type = htons(NF9_FIRST_SWITCHED_USEC); v4_template.r[rcount].length = htons(16); v4_int_template.r[rcount].length = 16; v4_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED_USEC); v4_template_out.r[rcount].length = htons(16); v4_int_template_out.r[rcount].length = 16; rcount++; } } v4_template.r[rcount].type = htons(NF9_IN_BYTES); v4_template.r[rcount].length = htons(8); v4_int_template.r[rcount].length = 8; v4_template_out.r[rcount].type = htons(NF9_IN_BYTES); v4_template_out.r[rcount].length = htons(8); v4_int_template_out.r[rcount].length = 8; rcount++; v4_template.r[rcount].type = htons(NF9_IN_PACKETS); v4_template.r[rcount].length = htons(8); v4_int_template.r[rcount].length = 8; v4_template_out.r[rcount].type = htons(NF9_IN_PACKETS); v4_template_out.r[rcount].length = htons(8); v4_int_template_out.r[rcount].length = 8; rcount++; v4_template.r[rcount].type = htons(NF9_IP_PROTOCOL_VERSION); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_IP_PROTOCOL_VERSION); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].length = 1; rcount++; v4_template.r[rcount].type = htons(NF9_INPUT_SNMP); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_input_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_INPUT_SNMP); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_input_handler; v4_int_template_out.r[rcount].length = 4; rcount++; v4_template.r[rcount].type = htons(NF9_OUTPUT_SNMP); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_output_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_OUTPUT_SNMP); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_output_handler; v4_int_template_out.r[rcount].length = 4; rcount++; v4_template.r[rcount].type = htons(NF9_DIRECTION); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_direction_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_DIRECTION); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_direction_handler; v4_int_template_out.r[rcount].length = 1; rcount++; if (config.nfprobe_what_to_count & COUNT_FLOWS) { v4_template.r[rcount].type = htons(NF9_FLOWS); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_flows_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_FLOWS); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_flows_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_HOST) { v4_template.r[rcount].type = htons(NF9_IPV4_SRC_ADDR); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_src_host_v4_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_IPV4_SRC_ADDR); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_src_host_v4_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_HOST) { v4_template.r[rcount].type = htons(NF9_IPV4_DST_ADDR); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_dst_host_v4_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_IPV4_DST_ADDR); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_dst_host_v4_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_PEER_DST_IP) { v4_template.r[rcount].type = htons(NF9_BGP_IPV4_NEXT_HOP); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_bgp_next_hop_v4_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_BGP_IPV4_NEXT_HOP); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_bgp_next_hop_v4_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_NMASK) { v4_template.r[rcount].type = htons(NF9_SRC_MASK); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_src_nmask_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_SRC_MASK); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_src_nmask_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_NMASK) { v4_template.r[rcount].type = htons(NF9_DST_MASK); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_dst_nmask_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_DST_MASK); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_dst_nmask_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_PORT) { v4_template.r[rcount].type = htons(NF9_L4_SRC_PORT); v4_template.r[rcount].length = htons(2); v4_int_template.r[rcount].handler = flow_to_flowset_src_port_handler; v4_int_template.r[rcount].length = 2; v4_template_out.r[rcount].type = htons(NF9_L4_SRC_PORT); v4_template_out.r[rcount].length = htons(2); v4_int_template_out.r[rcount].handler = flow_to_flowset_src_port_handler; v4_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_PORT) { v4_template.r[rcount].type = htons(NF9_L4_DST_PORT); v4_template.r[rcount].length = htons(2); v4_int_template.r[rcount].handler = flow_to_flowset_dst_port_handler; v4_int_template.r[rcount].length = 2; v4_template_out.r[rcount].type = htons(NF9_L4_DST_PORT); v4_template_out.r[rcount].length = htons(2); v4_int_template_out.r[rcount].handler = flow_to_flowset_dst_port_handler; v4_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count & (COUNT_IP_TOS)) { v4_template.r[rcount].type = htons(NF9_SRC_TOS); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_ip_tos_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_SRC_TOS); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_ip_tos_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & (COUNT_SRC_PORT|COUNT_DST_PORT)) { v4_template.r[rcount].type = htons(NF9_TCP_FLAGS); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_tcp_flags_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_TCP_FLAGS); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_tcp_flags_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_IP_PROTO) { v4_template.r[rcount].type = htons(NF9_IN_PROTOCOL); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_ip_proto_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_IN_PROTOCOL); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_ip_proto_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_AS) { v4_template.r[rcount].type = htons(NF9_SRC_AS); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_src_as_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_SRC_AS); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_src_as_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_AS) { v4_template.r[rcount].type = htons(NF9_DST_AS); v4_template.r[rcount].length = htons(4); v4_int_template.r[rcount].handler = flow_to_flowset_dst_as_handler; v4_int_template.r[rcount].length = 4; v4_template_out.r[rcount].type = htons(NF9_DST_AS); v4_template_out.r[rcount].length = htons(4); v4_int_template_out.r[rcount].handler = flow_to_flowset_dst_as_handler; v4_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_MAC) { v4_template.r[rcount].type = htons(NF9_IN_SRC_MAC); v4_template.r[rcount].length = htons(6); v4_int_template.r[rcount].handler = flow_to_flowset_src_mac_handler; v4_int_template.r[rcount].length = 6; v4_template_out.r[rcount].type = htons(NF9_OUT_SRC_MAC); v4_template_out.r[rcount].length = htons(6); v4_int_template_out.r[rcount].handler = flow_to_flowset_src_mac_handler; v4_int_template_out.r[rcount].length = 6; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_MAC) { v4_template.r[rcount].type = htons(NF9_IN_DST_MAC); v4_template.r[rcount].length = htons(6); v4_int_template.r[rcount].handler = flow_to_flowset_dst_mac_handler; v4_int_template.r[rcount].length = 6; v4_template_out.r[rcount].type = htons(NF9_OUT_DST_MAC); v4_template_out.r[rcount].length = htons(6); v4_int_template_out.r[rcount].handler = flow_to_flowset_dst_mac_handler; v4_int_template_out.r[rcount].length = 6; rcount++; } if (config.nfprobe_what_to_count & COUNT_VLAN) { v4_template.r[rcount].type = htons(NF9_SRC_VLAN); v4_template.r[rcount].length = htons(2); v4_int_template.r[rcount].handler = flow_to_flowset_vlan_handler; v4_int_template.r[rcount].length = 2; v4_template_out.r[rcount].type = htons(NF9_DST_VLAN); v4_template_out.r[rcount].length = htons(2); v4_int_template_out.r[rcount].handler = flow_to_flowset_vlan_handler; v4_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count_2 & COUNT_MPLS_LABEL_TOP) { v4_template.r[rcount].type = htons(NF9_MPLS_LABEL_1); v4_template.r[rcount].length = htons(3); v4_int_template.r[rcount].handler = flow_to_flowset_mpls_label_top_handler; v4_int_template.r[rcount].length = 3; v4_template_out.r[rcount].type = htons(NF9_MPLS_LABEL_1); v4_template_out.r[rcount].length = htons(3); v4_int_template_out.r[rcount].handler = flow_to_flowset_mpls_label_top_handler; v4_int_template_out.r[rcount].length = 3; rcount++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count & COUNT_TAG) { int rlen = sizeof(pm_id_t); v4_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG); v4_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template.r[rcount_pen].length = htons(rlen); v4_pen_int_template.r[rcount_pen].handler = flow_to_flowset_tag_handler; v4_pen_int_template.r[rcount_pen].length = rlen; v4_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG); v4_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template_out.r[rcount_pen].length = htons(rlen); v4_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_tag_handler; v4_pen_int_template_out.r[rcount_pen].length = rlen; rcount_pen++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count & COUNT_TAG2) { int rlen = sizeof(pm_id_t); v4_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG2); v4_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template.r[rcount_pen].length = htons(rlen); v4_pen_int_template.r[rcount_pen].handler = flow_to_flowset_tag2_handler; v4_pen_int_template.r[rcount_pen].length = rlen; v4_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG2); v4_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template_out.r[rcount_pen].length = htons(rlen); v4_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_tag2_handler; v4_pen_int_template_out.r[rcount_pen].length = rlen; rcount_pen++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count_2 & COUNT_LABEL) { v4_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_LABEL); v4_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template.r[rcount_pen].length = htons(IPFIX_VARIABLE_LENGTH); v4_pen_int_template.r[rcount_pen].handler = flow_to_flowset_label_handler; v4_pen_int_template.r[rcount_pen].length = IPFIX_VARIABLE_LENGTH; v4_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_LABEL); v4_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v4_pen_template_out.r[rcount_pen].length = htons(IPFIX_VARIABLE_LENGTH); v4_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_label_handler; v4_pen_int_template_out.r[rcount_pen].length = IPFIX_VARIABLE_LENGTH; rcount_pen++; } if (config.sampling_rate || config.ext_sampling_rate) { v4_template.r[rcount].type = htons(NF9_FLOW_SAMPLER_ID); v4_template.r[rcount].length = htons(1); v4_int_template.r[rcount].handler = flow_to_flowset_sampler_id_handler; v4_int_template.r[rcount].length = 1; v4_template_out.r[rcount].type = htons(NF9_FLOW_SAMPLER_ID); v4_template_out.r[rcount].length = htons(1); v4_int_template_out.r[rcount].handler = flow_to_flowset_sampler_id_handler; v4_int_template_out.r[rcount].length = 1; rcount++; } #if defined (WITH_NDPI) if (config.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS) { v4_template.r[rcount].type = htons(NF9_FLOW_APPLICATION_ID); v4_template.r[rcount].length = htons(5); v4_int_template.r[rcount].handler = flow_to_flowset_ndpi_class_handler; v4_int_template.r[rcount].length = 5; v4_template_out.r[rcount].type = htons(NF9_FLOW_APPLICATION_ID); v4_template_out.r[rcount].length = htons(5); v4_int_template_out.r[rcount].handler = flow_to_flowset_ndpi_class_handler; v4_int_template_out.r[rcount].length = 5; rcount++; } #endif /* all custom primitives printed here: must be kept last since only the first field will also have a corresponding handler */ rcount = nf9_init_cp_template(&v4_template, &v4_template_out, &v4_int_template, &v4_int_template_out, rcount); rcount_pen = nf9_init_cp_pen_template(&v4_pen_template, &v4_pen_template_out, &v4_pen_int_template, &v4_pen_int_template_out, rcount_pen); v4_template.h.c.flowset_id = htons(flowset_id); v4_template.h.c.length = htons( sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) + (sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen) ); v4_template.h.template_id = htons(NF9_SOFTFLOWD_V4_TEMPLATE_ID + config.nfprobe_id); v4_template.h.count = htons(rcount + rcount_pen); v4_template.tot_len = sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); v4_pen_template.tot_len = sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen; v4_template_out.h.c.flowset_id = htons(flowset_id); v4_template_out.h.c.length = htons( sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) + (sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen) ); v4_template_out.h.template_id = htons(NF9_SOFTFLOWD_V4_TEMPLATE_ID + config.nfprobe_id + 1); v4_template_out.h.count = htons(rcount + rcount_pen); v4_template_out.tot_len = sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); v4_pen_template_out.tot_len = sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen; assert(rcount + rcount_pen < NF9_SOFTFLOWD_TEMPLATE_NRECORDS); for (idx = 0, v4_int_template.tot_rec_len = 0, v4_int_template_out.tot_rec_len = 0; idx < rcount; idx++) { if (config.nfprobe_version == 10 && v4_int_template.r[idx].length == IPFIX_VARIABLE_LENGTH); else v4_int_template.tot_rec_len += v4_int_template.r[idx].length; if (config.nfprobe_version == 10 && v4_int_template_out.r[idx].length == IPFIX_VARIABLE_LENGTH); else v4_int_template_out.tot_rec_len += v4_int_template_out.r[idx].length; } for (idx = 0, v4_pen_int_template.tot_rec_len = 0, v4_pen_int_template_out.tot_rec_len = 0; idx < rcount_pen; idx++) { if (config.nfprobe_version == 10 && v4_pen_int_template.r[idx].length == IPFIX_VARIABLE_LENGTH); else v4_pen_int_template.tot_rec_len += v4_pen_int_template.r[idx].length; if (config.nfprobe_version == 10 && v4_pen_int_template_out.r[idx].length == IPFIX_VARIABLE_LENGTH); else v4_pen_int_template_out.tot_rec_len += v4_pen_int_template_out.r[idx].length; } rcount = 0; rcount_pen = 0; bzero(&v6_template, sizeof(v6_template)); bzero(&v6_pen_template, sizeof(v6_pen_template)); bzero(&v6_int_template, sizeof(v6_int_template)); bzero(&v6_pen_int_template, sizeof(v6_pen_int_template)); bzero(&v6_template_out, sizeof(v6_template_out)); bzero(&v6_pen_template_out, sizeof(v6_pen_template_out)); bzero(&v6_int_template_out, sizeof(v6_int_template_out)); bzero(&v6_pen_int_template_out, sizeof(v6_pen_int_template_out)); if (config.nfprobe_version == 9 && config.timestamps_secs) { v6_template.r[rcount].type = htons(NF9_LAST_SWITCHED); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].length = 4; rcount++; v6_template.r[rcount].type = htons(NF9_FIRST_SWITCHED); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].length = 4; rcount++; } else if ((config.nfprobe_version == 9 && !config.timestamps_secs) || config.nfprobe_version == 10) { if (!config.nfprobe_tstamp_usec) { v6_template.r[rcount].type = htons(NF9_LAST_SWITCHED_MSEC); v6_template.r[rcount].length = htons(8); v6_int_template.r[rcount].length = 8; v6_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED_MSEC); v6_template_out.r[rcount].length = htons(8); v6_int_template_out.r[rcount].length = 8; rcount++; v6_template.r[rcount].type = htons(NF9_FIRST_SWITCHED_MSEC); v6_template.r[rcount].length = htons(8); v6_int_template.r[rcount].length = 8; v6_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED_MSEC); v6_template_out.r[rcount].length = htons(8); v6_int_template_out.r[rcount].length = 8; rcount++; } else { v6_template.r[rcount].type = htons(NF9_LAST_SWITCHED_USEC); v6_template.r[rcount].length = htons(16); v6_int_template.r[rcount].length = 16; v6_template_out.r[rcount].type = htons(NF9_LAST_SWITCHED_USEC); v6_template_out.r[rcount].length = htons(16); v6_int_template_out.r[rcount].length = 16; rcount++; v6_template.r[rcount].type = htons(NF9_FIRST_SWITCHED_USEC); v6_template.r[rcount].length = htons(16); v6_int_template.r[rcount].length = 16; v6_template_out.r[rcount].type = htons(NF9_FIRST_SWITCHED_USEC); v6_template_out.r[rcount].length = htons(16); v6_int_template_out.r[rcount].length = 16; rcount++; } } v6_template.r[rcount].type = htons(NF9_IN_BYTES); v6_template.r[rcount].length = htons(8); v6_int_template.r[rcount].length = 8; v6_template_out.r[rcount].type = htons(NF9_IN_BYTES); v6_template_out.r[rcount].length = htons(8); v6_int_template_out.r[rcount].length = 8; rcount++; v6_template.r[rcount].type = htons(NF9_IN_PACKETS); v6_template.r[rcount].length = htons(8); v6_int_template.r[rcount].length = 8; v6_template_out.r[rcount].type = htons(NF9_IN_PACKETS); v6_template_out.r[rcount].length = htons(8); v6_int_template_out.r[rcount].length = 8; rcount++; v6_template.r[rcount].type = htons(NF9_IP_PROTOCOL_VERSION); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_IP_PROTOCOL_VERSION); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].length = 1; rcount++; v6_template.r[rcount].type = htons(NF9_INPUT_SNMP); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].handler = flow_to_flowset_input_handler; v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_INPUT_SNMP); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].handler = flow_to_flowset_input_handler; v6_int_template_out.r[rcount].length = 4; rcount++; v6_template.r[rcount].type = htons(NF9_OUTPUT_SNMP); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].handler = flow_to_flowset_output_handler; v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_OUTPUT_SNMP); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].handler = flow_to_flowset_output_handler; v6_int_template_out.r[rcount].length = 4; rcount++; v6_template.r[rcount].type = htons(NF9_DIRECTION); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_direction_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_DIRECTION); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_direction_handler; v6_int_template_out.r[rcount].length = 1; rcount++; if (config.nfprobe_what_to_count & COUNT_FLOWS) { v6_template.r[rcount].type = htons(NF9_FLOWS); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].handler = flow_to_flowset_flows_handler; v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_FLOWS); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].handler = flow_to_flowset_flows_handler; v6_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_HOST) { v6_template.r[rcount].type = htons(NF9_IPV6_SRC_ADDR); v6_template.r[rcount].length = htons(16); v6_int_template.r[rcount].handler = flow_to_flowset_src_host_v6_handler; v6_int_template.r[rcount].length = 16; v6_template_out.r[rcount].type = htons(NF9_IPV6_SRC_ADDR); v6_template_out.r[rcount].length = htons(16); v6_int_template_out.r[rcount].handler = flow_to_flowset_src_host_v6_handler; v6_int_template_out.r[rcount].length = 16; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_HOST) { v6_template.r[rcount].type = htons(NF9_IPV6_DST_ADDR); v6_template.r[rcount].length = htons(16); v6_int_template.r[rcount].handler = flow_to_flowset_dst_host_v6_handler; v6_int_template.r[rcount].length = 16; v6_template_out.r[rcount].type = htons(NF9_IPV6_DST_ADDR); v6_template_out.r[rcount].length = htons(16); v6_int_template_out.r[rcount].handler = flow_to_flowset_dst_host_v6_handler; v6_int_template_out.r[rcount].length = 16; rcount++; } if (config.nfprobe_what_to_count & COUNT_PEER_DST_IP) { v6_template.r[rcount].type = htons(NF9_BGP_IPV6_NEXT_HOP); v6_template.r[rcount].length = htons(16); v6_int_template.r[rcount].handler = flow_to_flowset_bgp_next_hop_v6_handler; v6_int_template.r[rcount].length = 16; v6_template_out.r[rcount].type = htons(NF9_BGP_IPV6_NEXT_HOP); v6_template_out.r[rcount].length = htons(16); v6_int_template_out.r[rcount].handler = flow_to_flowset_bgp_next_hop_v6_handler; v6_int_template_out.r[rcount].length = 16; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_NMASK) { v6_template.r[rcount].type = htons(NF9_IPV6_SRC_MASK); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_src_nmask_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_IPV6_SRC_MASK); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_src_nmask_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_NMASK) { v6_template.r[rcount].type = htons(NF9_IPV6_DST_MASK); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_dst_nmask_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_IPV6_DST_MASK); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_dst_nmask_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & (COUNT_IP_TOS)) { v6_template.r[rcount].type = htons(NF9_SRC_TOS); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_ip_tos_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_SRC_TOS); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_ip_tos_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_PORT) { v6_template.r[rcount].type = htons(NF9_L4_SRC_PORT); v6_template.r[rcount].length = htons(2); v6_int_template.r[rcount].handler = flow_to_flowset_src_port_handler; v6_int_template.r[rcount].length = 2; v6_template_out.r[rcount].type = htons(NF9_L4_SRC_PORT); v6_template_out.r[rcount].length = htons(2); v6_int_template_out.r[rcount].handler = flow_to_flowset_src_port_handler; v6_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_PORT) { v6_template.r[rcount].type = htons(NF9_L4_DST_PORT); v6_template.r[rcount].length = htons(2); v6_int_template.r[rcount].handler = flow_to_flowset_dst_port_handler; v6_int_template.r[rcount].length = 2; v6_template_out.r[rcount].type = htons(NF9_L4_DST_PORT); v6_template_out.r[rcount].length = htons(2); v6_int_template_out.r[rcount].handler = flow_to_flowset_dst_port_handler; v6_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count & (COUNT_SRC_PORT|COUNT_DST_PORT)) { v6_template.r[rcount].type = htons(NF9_TCP_FLAGS); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_tcp_flags_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_TCP_FLAGS); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_tcp_flags_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_IP_PROTO) { v6_template.r[rcount].type = htons(NF9_IN_PROTOCOL); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_ip_proto_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_IN_PROTOCOL); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_ip_proto_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_AS) { v6_template.r[rcount].type = htons(NF9_SRC_AS); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].handler = flow_to_flowset_src_as_handler; v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_SRC_AS); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].handler = flow_to_flowset_src_as_handler; v6_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_AS) { v6_template.r[rcount].type = htons(NF9_DST_AS); v6_template.r[rcount].length = htons(4); v6_int_template.r[rcount].handler = flow_to_flowset_dst_as_handler; v6_int_template.r[rcount].length = 4; v6_template_out.r[rcount].type = htons(NF9_DST_AS); v6_template_out.r[rcount].length = htons(4); v6_int_template_out.r[rcount].handler = flow_to_flowset_dst_as_handler; v6_int_template_out.r[rcount].length = 4; rcount++; } if (config.nfprobe_what_to_count & COUNT_SRC_MAC) { v6_template.r[rcount].type = htons(NF9_IN_SRC_MAC); v6_template.r[rcount].length = htons(6); v6_int_template.r[rcount].handler = flow_to_flowset_src_mac_handler; v6_int_template.r[rcount].length = 6; v6_template_out.r[rcount].type = htons(NF9_OUT_SRC_MAC); v6_template_out.r[rcount].length = htons(6); v6_int_template_out.r[rcount].handler = flow_to_flowset_src_mac_handler; v6_int_template_out.r[rcount].length = 6; rcount++; } if (config.nfprobe_what_to_count & COUNT_DST_MAC) { v6_template.r[rcount].type = htons(NF9_IN_DST_MAC); v6_template.r[rcount].length = htons(6); v6_int_template.r[rcount].handler = flow_to_flowset_dst_mac_handler; v6_int_template.r[rcount].length = 6; v6_template_out.r[rcount].type = htons(NF9_OUT_DST_MAC); v6_template_out.r[rcount].length = htons(6); v6_int_template_out.r[rcount].handler = flow_to_flowset_dst_mac_handler; v6_int_template_out.r[rcount].length = 6; rcount++; } if (config.nfprobe_what_to_count & COUNT_VLAN) { v6_template.r[rcount].type = htons(NF9_SRC_VLAN); v6_template.r[rcount].length = htons(2); v6_int_template.r[rcount].handler = flow_to_flowset_vlan_handler; v6_int_template.r[rcount].length = 2; v6_template_out.r[rcount].type = htons(NF9_DST_VLAN); v6_template_out.r[rcount].length = htons(2); v6_int_template_out.r[rcount].handler = flow_to_flowset_vlan_handler; v6_int_template_out.r[rcount].length = 2; rcount++; } if (config.nfprobe_what_to_count_2 & COUNT_MPLS_LABEL_TOP) { v6_template.r[rcount].type = htons(NF9_MPLS_LABEL_1); v6_template.r[rcount].length = htons(3); v6_int_template.r[rcount].handler = flow_to_flowset_mpls_label_top_handler; v6_int_template.r[rcount].length = 3; v6_template_out.r[rcount].type = htons(NF9_MPLS_LABEL_1); v6_template_out.r[rcount].length = htons(3); v6_int_template_out.r[rcount].handler = flow_to_flowset_mpls_label_top_handler; v6_int_template_out.r[rcount].length = 3; rcount++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count & COUNT_TAG) { int rlen = sizeof(pm_id_t); v6_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG); v6_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template.r[rcount_pen].length = htons(rlen); v6_pen_int_template.r[rcount_pen].handler = flow_to_flowset_tag_handler; v6_pen_int_template.r[rcount_pen].length = rlen; v6_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG); v6_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template_out.r[rcount_pen].length = htons(rlen); v6_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_tag_handler; v6_pen_int_template_out.r[rcount_pen].length = rlen; rcount_pen++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count & COUNT_TAG2) { int rlen = sizeof(pm_id_t); v6_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG2); v6_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template.r[rcount_pen].length = htons(rlen); v6_pen_int_template.r[rcount_pen].handler = flow_to_flowset_tag2_handler; v6_pen_int_template.r[rcount_pen].length = rlen; v6_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_TAG2); v6_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template_out.r[rcount_pen].length = htons(rlen); v6_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_tag2_handler; v6_pen_int_template_out.r[rcount_pen].length = rlen; rcount_pen++; } if (config.nfprobe_version == 10 && config.nfprobe_what_to_count_2 & COUNT_LABEL) { v6_pen_template.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_LABEL); v6_pen_template.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template.r[rcount_pen].length = htons(IPFIX_VARIABLE_LENGTH); v6_pen_int_template.r[rcount_pen].handler = flow_to_flowset_label_handler; v6_pen_int_template.r[rcount_pen].length = IPFIX_VARIABLE_LENGTH; v6_pen_template_out.r[rcount_pen].type = htons(IPFIX_TPL_EBIT | NF9_CUST_LABEL); v6_pen_template_out.r[rcount_pen].pen = htonl(PMACCT_PEN); v6_pen_template_out.r[rcount_pen].length = htons(IPFIX_VARIABLE_LENGTH); v6_pen_int_template_out.r[rcount_pen].handler = flow_to_flowset_label_handler; v6_pen_int_template_out.r[rcount_pen].length = IPFIX_VARIABLE_LENGTH; rcount_pen++; } if (config.sampling_rate || config.ext_sampling_rate) { v6_template.r[rcount].type = htons(NF9_FLOW_SAMPLER_ID); v6_template.r[rcount].length = htons(1); v6_int_template.r[rcount].handler = flow_to_flowset_sampler_id_handler; v6_int_template.r[rcount].length = 1; v6_template_out.r[rcount].type = htons(NF9_FLOW_SAMPLER_ID); v6_template_out.r[rcount].length = htons(1); v6_int_template_out.r[rcount].handler = flow_to_flowset_sampler_id_handler; v6_int_template_out.r[rcount].length = 1; rcount++; } #if defined (WITH_NDPI) if (config.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS) { v6_template.r[rcount].type = htons(NF9_FLOW_APPLICATION_ID); v6_template.r[rcount].length = htons(5); v6_int_template.r[rcount].handler = flow_to_flowset_ndpi_class_handler; v6_int_template.r[rcount].length = 5; v6_template_out.r[rcount].type = htons(NF9_FLOW_APPLICATION_ID); v6_template_out.r[rcount].length = htons(5); v6_int_template_out.r[rcount].handler = flow_to_flowset_ndpi_class_handler; v6_int_template_out.r[rcount].length = 5; rcount++; } #endif /* all custom primitives printed here: must be kept last since only the first field will also have a corresponding handler */ rcount = nf9_init_cp_template(&v6_template, &v6_template_out, &v6_int_template, &v6_int_template_out, rcount); rcount_pen = nf9_init_cp_pen_template(&v6_pen_template, &v6_pen_template_out, &v6_pen_int_template, &v6_pen_int_template_out, rcount_pen); v6_template.h.c.flowset_id = htons(flowset_id); v6_template.h.c.length = htons( sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) + (sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen) ); v6_template.h.template_id = htons(NF9_SOFTFLOWD_V6_TEMPLATE_ID + config.nfprobe_id); v6_template.h.count = htons(rcount + rcount_pen); v6_template.tot_len = sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); v6_pen_template.tot_len = sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen; v6_template_out.h.c.flowset_id = htons(flowset_id); v6_template_out.h.c.length = htons( sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) + (sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen) ); v6_template_out.h.template_id = htons(NF9_SOFTFLOWD_V6_TEMPLATE_ID + config.nfprobe_id + 1); v6_template_out.h.count = htons(rcount + rcount_pen); v6_template_out.tot_len = sizeof(struct NF9_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); v6_pen_template_out.tot_len = sizeof(struct IPFIX_PEN_TEMPLATE_FLOWSET_RECORD) * rcount_pen; assert(rcount + rcount_pen < NF9_SOFTFLOWD_TEMPLATE_NRECORDS); for (idx = 0, v6_int_template.tot_rec_len = 0, v6_int_template_out.tot_rec_len = 0; idx < rcount; idx++) { if (config.nfprobe_version == 10 && v6_int_template.r[idx].length == IPFIX_VARIABLE_LENGTH); else v6_int_template.tot_rec_len += v6_int_template.r[idx].length; if (config.nfprobe_version == 10 && v6_int_template_out.r[idx].length == IPFIX_VARIABLE_LENGTH); else v6_int_template_out.tot_rec_len += v6_int_template_out.r[idx].length; } for (idx = 0, v6_pen_int_template.tot_rec_len = 0, v6_pen_int_template_out.tot_rec_len = 0; idx < rcount_pen; idx++) { if (config.nfprobe_version == 10 && v6_pen_int_template.r[idx].length == IPFIX_VARIABLE_LENGTH); else v6_pen_int_template.tot_rec_len += v6_pen_int_template.r[idx].length; if (config.nfprobe_version == 10 && v6_pen_int_template_out.r[idx].length == IPFIX_VARIABLE_LENGTH); else v6_pen_int_template_out.tot_rec_len += v6_pen_int_template_out.r[idx].length; } } static void nf9_init_options_template(void) { int rcount, idx, slen = 0, flowset_id = 0, scope = 0; switch (config.nfprobe_source_ha.family) { case AF_INET: slen = 4; break; case AF_INET6: slen = 16; break; default: slen = 4; break; } rcount = 0; bzero(&sampling_option_template, sizeof(sampling_option_template)); bzero(&sampling_option_int_template, sizeof(sampling_option_int_template)); if (config.nfprobe_version == 9) { flowset_id = NF9_OPTIONS_FLOWSET_ID; scope = NF9_OPT_SCOPE_SYSTEM; } else if (config.nfprobe_version == 10) { flowset_id = IPFIX_OPTIONS_FLOWSET_ID; scope = NF9_FLOW_EXPORTER; } sampling_option_template.r[rcount].type = htons(scope); sampling_option_template.r[rcount].length = htons(slen); sampling_option_int_template.r[rcount].length = slen; rcount++; sampling_option_template.r[rcount].type = htons(NF9_FLOW_SAMPLER_ID); sampling_option_template.r[rcount].length = htons(1); sampling_option_int_template.r[rcount].length = 1; rcount++; sampling_option_template.r[rcount].type = htons(NF9_FLOW_SAMPLER_MODE); sampling_option_template.r[rcount].length = htons(1); sampling_option_int_template.r[rcount].length = 1; rcount++; sampling_option_template.r[rcount].type = htons(NF9_FLOW_SAMPLER_INTERVAL); sampling_option_template.r[rcount].length = htons(4); sampling_option_int_template.r[rcount].length = 4; rcount++; sampling_option_template.h.c.flowset_id = htons(flowset_id); sampling_option_template.h.c.length = htons( sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) ); sampling_option_template.h.template_id = htons(NF9_OPTIONS_TEMPLATE_ID + config.nfprobe_id ); if (config.nfprobe_version == 9) { sampling_option_template.h.scope_len = htons(4); /* NF9_OPT_SCOPE_SYSTEM */ sampling_option_template.h.option_len = htons(12); /* NF9_FLOW_SAMPLER_ID + NF9_FLOW_SAMPLER_MODE + NF9_FLOW_SAMPLER_INTERVAL */ } else if (config.nfprobe_version == 10) { sampling_option_template.h.scope_len = htons(3+1); /* IPFIX twist: NF9_FLOW_SAMPLER_ID + NF9_FLOW_SAMPLER_MODE + NF9_FLOW_SAMPLER_INTERVAL + NF9_OPT_SCOPE_SYSTEM */ sampling_option_template.h.option_len = htons(1); /* IPFIX twist: NF9_OPT_SCOPE_SYSTEM */ } sampling_option_template.tot_len = sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); for (idx = 0, sampling_option_int_template.tot_rec_len = 0; idx < rcount; idx++) sampling_option_int_template.tot_rec_len += sampling_option_int_template.r[idx].length; rcount = 0; bzero(&class_option_template, sizeof(class_option_template)); bzero(&class_option_int_template, sizeof(class_option_int_template)); class_option_template.r[rcount].type = htons(scope); class_option_template.r[rcount].length = htons(4); class_option_int_template.r[rcount].length = 4; rcount++; class_option_template.r[rcount].type = htons(NF9_FLOW_APPLICATION_ID); class_option_template.r[rcount].length = htons(5); class_option_int_template.r[rcount].length = 5; rcount++; class_option_template.r[rcount].type = htons(NF9_FLOW_APPLICATION_NAME); class_option_template.r[rcount].length = htons(MAX_PROTOCOL_LEN); class_option_int_template.r[rcount].length = MAX_PROTOCOL_LEN; rcount++; class_option_template.h.c.flowset_id = htons(flowset_id); class_option_template.h.c.length = htons( sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) ); class_option_template.h.template_id = htons(NF9_OPTIONS_TEMPLATE_ID + 1 + config.nfprobe_id ); if (config.nfprobe_version == 9) { class_option_template.h.scope_len = htons(4); /* NF9_OPT_SCOPE_SYSTEM */ class_option_template.h.option_len = htons(8); /* NF9_FLOW_APPLICATION_ID + NF9_FLOW_APPLICATION_NAME */ } else if (config.nfprobe_version == 10) { class_option_template.h.scope_len = htons(2+1); /* IPFIX twist: NF9_FLOW_APPLICATION_ID + NF9_FLOW_APPLICATION_NAME + NF9_OPT_SCOPE_SYSTEM */ class_option_template.h.option_len = htons(1); /* IPFIX twist: NF9_OPT_SCOPE_SYSTEM */ } class_option_template.tot_len = sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); for (idx = 0, class_option_int_template.tot_rec_len = 0; idx < rcount; idx++) class_option_int_template.tot_rec_len += class_option_int_template.r[idx].length; rcount = 0; bzero(&exporter_option_template, sizeof(exporter_option_template)); bzero(&exporter_option_int_template, sizeof(exporter_option_int_template)); if (config.nfprobe_version == 9) { flowset_id = NF9_OPTIONS_FLOWSET_ID; scope = NF9_OPT_SCOPE_SYSTEM; } else if (config.nfprobe_version == 10) { flowset_id = IPFIX_OPTIONS_FLOWSET_ID; scope = NF9_FLOW_EXPORTER; } exporter_option_template.r[rcount].type = htons(scope); exporter_option_template.r[rcount].length = htons(slen); exporter_option_int_template.r[rcount].length = slen; rcount++; exporter_option_template.r[rcount].type = htons(NF9_EXPORTER_IPV4_ADDRESS); exporter_option_template.r[rcount].length = htons(4); exporter_option_int_template.r[rcount].length = 4; rcount++; exporter_option_template.r[rcount].type = htons(NF9_EXPORTER_IPV6_ADDRESS); exporter_option_template.r[rcount].length = htons(16); exporter_option_int_template.r[rcount].length = 16; rcount++; exporter_option_template.h.c.flowset_id = htons(flowset_id); exporter_option_template.h.c.length = htons( sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount) ); exporter_option_template.h.template_id = htons(NF9_OPTIONS_TEMPLATE_ID + 2 + config.nfprobe_id ); if (config.nfprobe_version == 9) { exporter_option_template.h.scope_len = htons(4); /* NF9_OPT_SCOPE_SYSTEM */ exporter_option_template.h.option_len = htons(8); /* NF9_EXPORTER_IPV4_ADDRESS + NF9_EXPORTER_IPV6_ADDRESS */ } else if (config.nfprobe_version == 10) { exporter_option_template.h.scope_len = htons(2+1); /* IPFIX twist: NF9_EXPORTER_IPV4_ADDRESS + NF9_EXPORTER_IPV6_ADDRESS + NF9_OPT_SCOPE_SYSTEM */ exporter_option_template.h.option_len = htons(1); /* IPFIX twist: NF9_OPT_SCOPE_SYSTEM */ } exporter_option_template.tot_len = sizeof(struct NF9_OPTIONS_TEMPLATE_FLOWSET_HEADER) + (sizeof(struct NF9_TEMPLATE_FLOWSET_RECORD) * rcount); for (idx = 0, exporter_option_int_template.tot_rec_len = 0; idx < rcount; idx++) exporter_option_int_template.tot_rec_len += exporter_option_int_template.r[idx].length; } static void nf_flow_to_flowset_inc_len(char **ftoft_ptr, int *add_len, int orig_len, int elem_len) { if (!elem_len) *ftoft_ptr += orig_len; else { /* hmm, what if sum of all orig_len elements != PM_VARIABLE_LENGTH gets >= PM_VARIABLE_LENGTH ? Unlikely but we may hit a problem .. */ *ftoft_ptr += ((orig_len % PM_VARIABLE_LENGTH) + elem_len); *add_len += elem_len; } } static int nf_flow_to_flowset(const struct FLOW *flow, u_char *packet, u_int len, const struct timeval *system_boot_time, u_int *len_used, int direction) { u_int freclen_0 = 0, freclen_1 = 0, ret_len, nflows, idx; u_int64_t rec64; u_int32_t rec32 = 0; u_int8_t rec8; char *ftoft_ptr_0 = ftoft_buf_0; char *ftoft_ptr_1 = ftoft_buf_1; int flow_direction[2], elem_len, add_len; bzero(ftoft_buf_0, sizeof(ftoft_buf_0)); bzero(ftoft_buf_1, sizeof(ftoft_buf_1)); *len_used = nflows = ret_len = 0; flow_direction[0] = (flow->direction[0] == DIRECTION_UNKNOWN) ? DIRECTION_IN : flow->direction[0]; flow_direction[1] = (flow->direction[1] == DIRECTION_UNKNOWN) ? DIRECTION_IN : flow->direction[1]; if (direction == flow_direction[0]) { if (config.nfprobe_version == 9 && config.timestamps_secs) { rec32 = htonl(timeval_sub_ms(&flow->flow_last, system_boot_time)); memcpy(ftoft_ptr_0, &rec32, 4); ftoft_ptr_0 += 4; rec32 = htonl(timeval_sub_ms(&flow->flow_start, system_boot_time)); memcpy(ftoft_ptr_0, &rec32, 4); ftoft_ptr_0 += 4; } else if ((config.nfprobe_version == 9 && !config.timestamps_secs) || config.nfprobe_version == 10) { if (!config.nfprobe_tstamp_usec) { u_int64_t tstamp_msec; tstamp_msec = flow->flow_last.tv_sec; tstamp_msec = tstamp_msec * 1000; tstamp_msec += (flow->flow_last.tv_usec / 1000); rec64 = pm_htonll(tstamp_msec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; tstamp_msec = flow->flow_start.tv_sec; tstamp_msec = tstamp_msec * 1000; tstamp_msec += (flow->flow_start.tv_usec / 1000); rec64 = pm_htonll(tstamp_msec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; } else { rec64 = pm_htonll(flow->flow_last.tv_sec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; rec64 = pm_htonll(flow->flow_last.tv_usec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; rec64 = pm_htonll(flow->flow_start.tv_sec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; rec64 = pm_htonll(flow->flow_start.tv_usec); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; } } rec64 = pm_htonll(flow->octets[0]); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; rec64 = pm_htonll(flow->packets[0]); memcpy(ftoft_ptr_0, &rec64, 8); ftoft_ptr_0 += 8; switch (flow->af) { case AF_INET: rec8 = 4; memcpy(ftoft_ptr_0, &rec8, 1); ftoft_ptr_0 += 1; if (flow_direction[0] == DIRECTION_IN) { for (idx = 5, add_len = 0; v4_int_template.r[idx].handler; idx++) { elem_len = v4_int_template.r[idx].handler(ftoft_ptr_0, flow, 0, v4_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v4_int_template.r[idx].length, elem_len); } freclen_0 = v4_int_template.tot_rec_len; for (idx = 0; v4_pen_int_template.r[idx].handler; idx++) { elem_len = v4_pen_int_template.r[idx].handler(ftoft_ptr_0, flow, 0, v4_pen_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v4_pen_int_template.r[idx].length, elem_len); } freclen_0 += (v4_pen_int_template.tot_rec_len + add_len); } else if (flow_direction[0] == DIRECTION_OUT) { for (idx = 5, add_len = 0; v4_int_template_out.r[idx].handler; idx++) { elem_len = v4_int_template_out.r[idx].handler(ftoft_ptr_0, flow, 0, v4_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v4_int_template_out.r[idx].length, elem_len); } freclen_0 = v4_int_template_out.tot_rec_len; for (idx = 0; v4_pen_int_template_out.r[idx].handler; idx++) { elem_len = v4_pen_int_template_out.r[idx].handler(ftoft_ptr_0, flow, 0, v4_pen_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v4_pen_int_template_out.r[idx].length, elem_len); } freclen_0 += (v4_pen_int_template_out.tot_rec_len + add_len); } break; case AF_INET6: rec8 = 6; memcpy(ftoft_ptr_0, &rec8, 1); ftoft_ptr_0 += 1; if (flow_direction[0] == DIRECTION_IN) { for (idx = 5, add_len = 0; v6_int_template.r[idx].handler; idx++) { elem_len = v6_int_template.r[idx].handler(ftoft_ptr_0, flow, 0, v6_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v6_int_template.r[idx].length, elem_len); } freclen_0 = v6_int_template.tot_rec_len; for (idx = 0; v6_pen_int_template.r[idx].handler; idx++) { elem_len = v6_pen_int_template.r[idx].handler(ftoft_ptr_0, flow, 0, v6_pen_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v6_pen_int_template.r[idx].length, elem_len); } freclen_0 += (v6_pen_int_template.tot_rec_len + add_len); } else if (flow_direction[0] == DIRECTION_OUT) { for (idx = 5, add_len = 0; v6_int_template_out.r[idx].handler; idx++) { elem_len = v6_int_template_out.r[idx].handler(ftoft_ptr_0, flow, 0, v6_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v6_int_template_out.r[idx].length, elem_len); } freclen_0 = v6_int_template_out.tot_rec_len; for (idx = 0; v6_pen_int_template_out.r[idx].handler; idx++) { elem_len = v6_pen_int_template_out.r[idx].handler(ftoft_ptr_0, flow, 0, v6_pen_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_0, &add_len, v6_pen_int_template_out.r[idx].length, elem_len); } freclen_0 += (v6_pen_int_template_out.tot_rec_len + add_len); } break; default: return (-1); } } if (direction == flow_direction[1]) { if (config.nfprobe_version == 9 && config.timestamps_secs) { rec32 = htonl(timeval_sub_ms(&flow->flow_last, system_boot_time)); memcpy(ftoft_ptr_1, &rec32, 4); ftoft_ptr_1 += 4; rec32 = htonl(timeval_sub_ms(&flow->flow_start, system_boot_time)); memcpy(ftoft_ptr_1, &rec32, 4); ftoft_ptr_1 += 4; } else if ((config.nfprobe_version == 9 && !config.timestamps_secs) || config.nfprobe_version == 10) { if (!config.nfprobe_tstamp_usec) { u_int64_t tstamp_msec; tstamp_msec = flow->flow_last.tv_sec; tstamp_msec = tstamp_msec * 1000; tstamp_msec += (flow->flow_last.tv_usec / 1000); rec64 = pm_htonll(tstamp_msec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; tstamp_msec = flow->flow_start.tv_sec; tstamp_msec = tstamp_msec * 1000; tstamp_msec += (flow->flow_start.tv_usec / 1000); rec64 = pm_htonll(tstamp_msec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; } else { rec64 = pm_htonll(flow->flow_last.tv_sec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; rec64 = pm_htonll(flow->flow_last.tv_usec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; rec64 = pm_htonll(flow->flow_start.tv_sec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; rec64 = pm_htonll(flow->flow_start.tv_usec); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; } } rec64 = pm_htonll(flow->octets[1]); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; rec64 = pm_htonll(flow->packets[1]); memcpy(ftoft_ptr_1, &rec64, 8); ftoft_ptr_1 += 8; switch (flow->af) { case AF_INET: rec8 = 4; memcpy(ftoft_ptr_1, &rec8, 1); ftoft_ptr_1 += 1; if (flow_direction[1] == DIRECTION_IN) { for (idx = 5, add_len = 0; v4_int_template.r[idx].handler; idx++) { elem_len = v4_int_template.r[idx].handler(ftoft_ptr_1, flow, 1, v4_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v4_int_template.r[idx].length, elem_len); } freclen_1 = v4_int_template.tot_rec_len; for (idx = 0; v4_pen_int_template.r[idx].handler; idx++) { elem_len = v4_pen_int_template.r[idx].handler(ftoft_ptr_1, flow, 1, v4_pen_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v4_pen_int_template.r[idx].length, elem_len); } freclen_1 += (v4_pen_int_template.tot_rec_len + add_len); } else if (flow_direction[1] == DIRECTION_OUT) { for (idx = 5, add_len = 0; v4_int_template_out.r[idx].handler; idx++) { elem_len = v4_int_template_out.r[idx].handler(ftoft_ptr_1, flow, 1, v4_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v4_int_template_out.r[idx].length, elem_len); } freclen_1 = v4_int_template_out.tot_rec_len; for (idx = 0; v4_pen_int_template_out.r[idx].handler; idx++) { elem_len = v4_pen_int_template_out.r[idx].handler(ftoft_ptr_1, flow, 1, v4_pen_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v4_pen_int_template_out.r[idx].length, elem_len); } freclen_1 += (v4_pen_int_template_out.tot_rec_len + add_len); } break; case AF_INET6: rec8 = 6; memcpy(ftoft_ptr_1, &rec8, 1); ftoft_ptr_1 += 1; if (flow_direction[1] == DIRECTION_IN) { for (idx = 5, add_len = 0; v6_int_template.r[idx].handler; idx++) { elem_len = v6_int_template.r[idx].handler(ftoft_ptr_1, flow, 1, v6_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v6_int_template.r[idx].length, elem_len); } freclen_1 = v6_int_template.tot_rec_len; for (idx = 0; v6_pen_int_template.r[idx].handler; idx++) { elem_len = v6_pen_int_template.r[idx].handler(ftoft_ptr_1, flow, 1, v6_pen_int_template.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v6_pen_int_template.r[idx].length, elem_len); } freclen_1 += (v6_pen_int_template.tot_rec_len + add_len); } else if (flow_direction[1] == DIRECTION_OUT) { for (idx = 5, add_len = 0; v6_int_template_out.r[idx].handler; idx++) { elem_len = v6_int_template_out.r[idx].handler(ftoft_ptr_1, flow, 1, v6_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v6_int_template_out.r[idx].length, elem_len); } freclen_1 = v6_int_template_out.tot_rec_len; for (idx = 0; v6_pen_int_template_out.r[idx].handler; idx++) { elem_len = v6_pen_int_template_out.r[idx].handler(ftoft_ptr_1, flow, 1, v6_pen_int_template_out.r[idx].length); nf_flow_to_flowset_inc_len(&ftoft_ptr_1, &add_len, v6_pen_int_template_out.r[idx].length, elem_len); } freclen_1 += (v6_pen_int_template_out.tot_rec_len + add_len); } break; default: return (-1); } } if (flow->octets[0] > 0 && direction == flow_direction[0]) { if (ret_len + freclen_0 > len) return (-1); memcpy(packet + ret_len, ftoft_buf_0, freclen_0); ret_len += freclen_0; nflows++; } if (flow->octets[1] > 0 && direction == flow_direction[1]) { if (ret_len + freclen_1 > len) return (-1); memcpy(packet + ret_len, ftoft_buf_1, freclen_1); ret_len += freclen_1; nflows++; } *len_used = ret_len; return (nflows); } static int nf_sampling_option_to_flowset(u_char *packet, u_int len, const struct timeval *system_boot_time, u_int *len_used) { u_int freclen, ret_len, nflows; u_int32_t rec32 = 0; u_int8_t rec8; char *ftoft_ptr_0 = ftoft_buf_0; bzero(ftoft_buf_0, sizeof(ftoft_buf_0)); *len_used = nflows = ret_len = 0; /* NF9_OPT_SCOPE_SYSTEM */ switch (config.nfprobe_source_ha.family) { case AF_INET: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv4, 4); ftoft_ptr_0 += 4; break; case AF_INET6: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv6, 16); ftoft_ptr_0 += 16; break; default: memset(ftoft_ptr_0, 0, 4); ftoft_ptr_0 += 4; break; } rec8 = 1; /* NF9_FLOW_SAMPLER_ID */ memcpy(ftoft_ptr_0, &rec8, 1); ftoft_ptr_0 += 1; rec8 = 0x02; /* NF9_FLOW_SAMPLER_MODE */ memcpy(ftoft_ptr_0, &rec8, 1); ftoft_ptr_0 += 1; if (config.sampling_rate) rec32 = htonl(config.sampling_rate); /* NF9_FLOW_SAMPLER_INTERVAL */ else if (config.ext_sampling_rate) rec32 = htonl(config.ext_sampling_rate); /* NF9_FLOW_SAMPLER_INTERVAL */ memcpy(ftoft_ptr_0, &rec32, 4); ftoft_ptr_0 += 4; freclen = sampling_option_int_template.tot_rec_len; if (ret_len + freclen > len) return (-1); memcpy(packet + ret_len, ftoft_buf_0, freclen); ret_len += freclen; nflows++; *len_used = ret_len; return (nflows); } static int nf_class_option_to_flowset(u_int idx, u_char *packet, u_int len, const struct timeval *system_boot_time, u_int *len_used) { u_int freclen, ret_len, nflows; char *ftoft_ptr_0 = ftoft_buf_0; bzero(ftoft_buf_0, sizeof(ftoft_buf_0)); *len_used = nflows = ret_len = 0; /* NF9_OPT_SCOPE_SYSTEM */ switch (config.nfprobe_source_ha.family) { case AF_INET: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv4, 4); ftoft_ptr_0 += 4; break; case AF_INET6: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv6, 16); ftoft_ptr_0 += 16; break; default: memset(ftoft_ptr_0, 0, 4); ftoft_ptr_0 += 4; break; } /* NF9_FLOW_APPLICATION_ID (ClassID) */ { u_int8_t ie95_classId = 0x16; /* nDPI */ memcpy(ftoft_ptr_0, &ie95_classId, 1); ftoft_ptr_0 += 1; } /* NF9_FLOW_APPLICATION_ID (SelectID) */ { u_int32_t ie95_selectId = htonl(class[idx].id); memcpy(ftoft_ptr_0, &ie95_selectId, 4); ftoft_ptr_0 += 4; } /* NF9_FLOW_APPLICATION_NAME */ strlcpy(ftoft_ptr_0, class[idx].protocol, MAX_PROTOCOL_LEN); ftoft_ptr_0 += MAX_PROTOCOL_LEN; freclen = class_option_int_template.tot_rec_len; if (ret_len + freclen > len) return (-1); memcpy(packet + ret_len, ftoft_buf_0, freclen); ret_len += freclen; nflows++; *len_used = ret_len; return (nflows); } static int nf_exporter_option_to_flowset(u_char *packet, u_int len, const struct timeval *system_boot_time, u_int *len_used) { u_int freclen, ret_len, nflows; char *ftoft_ptr_0 = ftoft_buf_0; memset(ftoft_buf_0, 0, sizeof(ftoft_buf_0)); *len_used = nflows = ret_len = 0; /* NF9_OPT_SCOPE_SYSTEM */ switch (config.nfprobe_source_ha.family) { case AF_INET: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv4, 4); ftoft_ptr_0 += 4; break; case AF_INET6: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv6, 16); ftoft_ptr_0 += 16; break; default: memset(ftoft_ptr_0, 0, 4); ftoft_ptr_0 += 4; break; } switch (config.nfprobe_source_ha.family) { /* NF9_EXPORTER_IPV4_ADDRESS */ case AF_INET: memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv4, 4); ftoft_ptr_0 += 4; memset(ftoft_ptr_0, 0, 16); ftoft_ptr_0 += 16; break; /* NF9_EXPORTER_IPV6_ADDRESS */ case AF_INET6: memset(ftoft_ptr_0, 0, 4); ftoft_ptr_0 += 4; memcpy(ftoft_ptr_0, &config.nfprobe_source_ha.address.ipv6, 16); ftoft_ptr_0 += 16; break; default: memset(ftoft_ptr_0, 0, 4); ftoft_ptr_0 += 4; memset(ftoft_ptr_0, 0, 16); ftoft_ptr_0 += 16; break; } freclen = exporter_option_int_template.tot_rec_len; if (ret_len + freclen > len) return (ERR); memcpy(packet + ret_len, ftoft_buf_0, freclen); ret_len += freclen; nflows++; *len_used = ret_len; return (nflows); } /* * Given an array of expired flows, send netflow v9 report packets * Returns number of packets sent or -1 on error */ int send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock, void *dtls, u_int64_t *flows_exported, struct timeval *system_boot_time, int verbose_flag, u_int8_t unused, u_int32_t source_id) { struct NF9_HEADER *nf9; struct IPFIX_HEADER *nf10; struct NF9_DATA_FLOWSET_HEADER *dh; struct timeval now; u_int offset, last_af, flow_j, num_packets, inc, last_valid; u_int num_class, class_j; int direction, new_direction; socklen_t errsz; int err, r, flow_i, class_i, ret; #ifdef WITH_GNUTLS pm_dtls_peer_t *dtls_peer = dtls; #endif memset(packet, 0, sizeof(packet)); gettimeofday(&now, NULL); if (nf9_pkts_until_template == -1) { nf9_init_template(); nf9_init_options_template(); nf9_pkts_until_template = 0; } offset = 0; r = 0; num_packets = 0; num_class = pmct_find_first_free(); for (direction = DIRECTION_IN; direction <= DIRECTION_OUT; direction++) { last_valid = 0; new_direction = TRUE; for (flow_j = 0, class_j = 0; flow_j < num_flows;) { bzero(packet, sizeof(packet)); if (config.nfprobe_version == 9) { nf9 = (struct NF9_HEADER *)packet; nf9->version = htons(9); nf9->flows = 0; /* Filled as we go, htons at end */ nf9->uptime_ms = htonl(timeval_sub_ms(&now, system_boot_time)); nf9->time_sec = htonl(time(NULL)); nf9->package_sequence = htonl(++(*flows_exported)); nf9->source_id = htonl(source_id); offset = sizeof(*nf9); } else if (config.nfprobe_version == 10) { nf10 = (struct IPFIX_HEADER *)packet; nf10->version = htons(10); nf10->len = 0; nf10->time_sec = htonl(time(NULL)); nf10->package_sequence = htonl(*flows_exported); nf10->source_id = htonl(source_id); offset = sizeof(*nf10); } /* Refresh template headers if we need to */ if (nf9_pkts_until_template <= 0) { u_int16_t flows = 0, tot_len = 0; memcpy(packet + offset, &v4_template, v4_template.tot_len); offset += v4_template.tot_len; memcpy(packet + offset, &v4_pen_template, v4_pen_template.tot_len); offset += v4_pen_template.tot_len; flows++; tot_len += v4_template.tot_len + v4_pen_template.tot_len; memcpy(packet + offset, &v4_template_out, v4_template_out.tot_len); offset += v4_template_out.tot_len; memcpy(packet + offset, &v4_pen_template_out, v4_pen_template_out.tot_len); offset += v4_pen_template_out.tot_len; flows++; tot_len += v4_template_out.tot_len + v4_pen_template_out.tot_len; memcpy(packet + offset, &v6_template, v6_template.tot_len); offset += v6_template.tot_len; memcpy(packet + offset, &v6_pen_template, v6_pen_template.tot_len); offset += v6_pen_template.tot_len; flows++; tot_len += v6_template.tot_len + v6_pen_template.tot_len; memcpy(packet + offset, &v6_template_out, v6_template_out.tot_len); offset += v6_template_out.tot_len; memcpy(packet + offset, &v6_pen_template_out, v6_pen_template_out.tot_len); offset += v6_pen_template_out.tot_len; flows++; tot_len += v6_template_out.tot_len + v6_pen_template_out.tot_len; if (config.sampling_rate || config.ext_sampling_rate) { memcpy(packet + offset, &sampling_option_template, sampling_option_template.tot_len); offset += sampling_option_template.tot_len; flows++; tot_len += sampling_option_template.tot_len; send_options = TRUE; send_sampling_option = TRUE; } #if defined (WITH_NDPI) if ((config.nfprobe_what_to_count_2 & COUNT_NDPI_CLASS) && num_class > 0) { memcpy(packet + offset, &class_option_template, class_option_template.tot_len); offset += class_option_template.tot_len; flows++; tot_len += class_option_template.tot_len; send_options = TRUE; send_options = TRUE; send_class_option = TRUE; } #endif if (config.nfprobe_source_ip) { memcpy(packet + offset, &exporter_option_template, exporter_option_template.tot_len); offset += exporter_option_template.tot_len; flows++; tot_len += exporter_option_template.tot_len; send_options = TRUE; send_exporter_option = TRUE; } nf9_pkts_until_template = NF9_DEFAULT_TEMPLATE_INTERVAL; if (config.nfprobe_version == 9) nf9->flows = flows; } dh = NULL; last_af = 0; for (flow_i = 0, class_i = 0; flow_i + flow_j < num_flows; flow_i++) { /* Shall we send a new flowset header? */ if (dh == NULL || (!send_options && (flows[flow_i + flow_j]->af != last_af || new_direction)) || send_sampling_option || send_exporter_option || (send_class_option && !class_i) ) { if (dh != NULL) { if (offset % 4 != 0) { /* Pad to multiple of 4 */ dh->c.length += 4 - (offset % 4); offset += 4 - (offset % 4); } /* Finalise last header */ dh->c.length = htons(dh->c.length); } if (offset + sizeof(*dh) > sizeof(packet)) { /* Mark header is finished */ dh = NULL; break; } dh = (struct NF9_DATA_FLOWSET_HEADER *) (packet + offset); if (send_options) { if (send_sampling_option) { dh->c.flowset_id = sampling_option_template.h.template_id; // last_af = 0; new_direction = TRUE; } else if (send_class_option) { dh->c.flowset_id = class_option_template.h.template_id; // last_af = 0; new_direction = TRUE; } else if (send_exporter_option) { dh->c.flowset_id = exporter_option_template.h.template_id; // last_af = 0; new_direction = TRUE; } } else { if (flows[flow_i + flow_j]->af == AF_INET) { if (direction == DIRECTION_IN) dh->c.flowset_id = v4_template.h.template_id; else if (direction == DIRECTION_OUT) dh->c.flowset_id = v4_template_out.h.template_id; } else if (flows[flow_i + flow_j]->af == AF_INET6) { if (direction == DIRECTION_IN) dh->c.flowset_id = v6_template.h.template_id; else if (direction == DIRECTION_OUT) dh->c.flowset_id = v6_template_out.h.template_id; } // last_af = flows[flow_i + flow_j]->af; /* XXX */ } last_valid = offset; new_direction = FALSE; dh->c.length = sizeof(*dh); /* Filled as we go */ offset += sizeof(*dh); } /* Send flowset data over */ if (send_options) { if (send_sampling_option) { r = nf_sampling_option_to_flowset((u_char *)(packet + offset), sizeof(packet) - offset, system_boot_time, &inc); send_sampling_option = FALSE; } else if (send_class_option) { r = nf_class_option_to_flowset(class_i + class_j, (u_char *)(packet + offset), sizeof(packet) - offset, system_boot_time, &inc); if (r > 0) class_i += r; if (class_i + class_j >= num_class) send_class_option = FALSE; } else if (send_exporter_option) { r = nf_exporter_option_to_flowset((u_char *)(packet + offset), sizeof(packet) - offset, system_boot_time, &inc); send_exporter_option = FALSE; } } else r = nf_flow_to_flowset(flows[flow_i + flow_j], (u_char *)(packet + offset), sizeof(packet) - offset, system_boot_time, &inc, direction); /* Wrap up */ if (r <= 0) { /* yank off data header, if we had to go back */ if (last_valid) offset = last_valid; if (r < 0) break; } else { offset += inc; dh->c.length += inc; if (config.nfprobe_version == 9) nf9->flows += r; else if (config.nfprobe_version == 10) *flows_exported += r; last_valid = 0; /* Don't clobber this header now */ if (verbose_flag) { if (config.nfprobe_version == 9) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Building NetFlow v9 packet: offset = %d, template ID = %d, total len = %d, # elements = %d\n", config.name, config.type, offset, ntohs(dh->c.flowset_id), dh->c.length, nf9->flows); } else if (config.nfprobe_version == 10) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): Building IPFIX packet: offset = %d, template ID = %d, total len = %d\n", config.name, config.type, offset, ntohs(dh->c.flowset_id), dh->c.length); } } if (send_options) { if (!send_sampling_option && !send_class_option && !send_exporter_option) { send_options = FALSE; } flow_i--; } else last_af = flows[flow_i + flow_j]->af; /* XXX */ } } /* Don't finish header if it has already been done */ if (dh != NULL) { if (offset % 4 != 0) { /* Pad to multiple of 4 */ dh->c.length += 4 - (offset % 4); offset += 4 - (offset % 4); } /* Finalise last header */ dh->c.length = htons(dh->c.length); } if ((config.nfprobe_version == 9 && nf9->flows > 0) || (config.nfprobe_version == 10 && offset > 20)) { /* 20: IPFIX header + IPFIX Flowset header */ if (config.nfprobe_version == 9) nf9->flows = htons(nf9->flows); else if (config.nfprobe_version == 10) nf10->len = htons(offset); if (verbose_flag) Log(LOG_DEBUG, "DEBUG ( %s/%s ): Sending NetFlow v9/IPFIX packet: len = %d\n", config.name, config.type, offset); errsz = sizeof(err); /* Clear ICMP errors */ getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); if (!config.nfprobe_dtls) { ret = send(nfsock, packet, (size_t)offset, 0); if (ret == ERR) { Log(LOG_WARNING, "WARN ( %s/%s ): send() failed: %s\n", config.name, config.type, strerror(errno)); return ret; } } #ifdef WITH_GNUTLS else { ret = pm_dtls_client_send(dtls_peer, packet, (size_t)offset); if (ret < 0) return ret; } #endif num_packets++; nf9_pkts_until_template--; } else { if (config.nfprobe_version == 9) --(*flows_exported); } class_j += class_i; flow_j += flow_i; } } return (num_packets); } pmacct-1.7.8/src/nfprobe_plugin/convtime.h0000644000175000017500000000345314354105275017614 0ustar paolopaolo/* * Copyright (c) 2001 Kevin Steves. 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 THE AUTHOR ``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 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 NFPROBE_CONVTIME_H /* * Convert a time string into seconds; format is * a sequence of: * time[qualifier] * * Valid time qualifiers are: * seconds * s|S seconds * m|M minutes * h|H hours * d|D days * w|W weeks * * Examples: * 90m 90 minutes * 1h30m 90 minutes * 2d 2 days * 1w 1 week * * Return -1 if time string is invalid. */ long int convtime(const char *s); #endif /* _SFD_CONVTIME_H */ pmacct-1.7.8/src/nfprobe_plugin/Makefile.in0000644000175000017500000006177714354105416017676 0ustar paolopaolo# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/nfprobe_plugin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_linearize_path.m4 \ $(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnfprobe_plugin_la_LIBADD = am_libnfprobe_plugin_la_OBJECTS = \ libnfprobe_plugin_la-nfprobe_plugin.lo \ libnfprobe_plugin_la-netflow5.lo \ libnfprobe_plugin_la-netflow9.lo \ libnfprobe_plugin_la-convtime.lo libnfprobe_plugin_la_OBJECTS = $(am_libnfprobe_plugin_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libnfprobe_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libnfprobe_plugin_la-convtime.Plo \ ./$(DEPDIR)/libnfprobe_plugin_la-netflow5.Plo \ ./$(DEPDIR)/libnfprobe_plugin_la-netflow9.Plo \ ./$(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libnfprobe_plugin_la_SOURCES) DIST_SOURCES = $(libnfprobe_plugin_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVRO_CFLAGS = @AVRO_CFLAGS@ AVRO_LIBS = @AVRO_LIBS@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ EBPF_CFLAGS = @EBPF_CFLAGS@ EBPF_LIBS = @EBPF_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GEOIPV2_CFLAGS = @GEOIPV2_CFLAGS@ GEOIPV2_LIBS = @GEOIPV2_LIBS@ GEOIP_CFLAGS = @GEOIP_CFLAGS@ GEOIP_LIBS = @GEOIP_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JANSSON_CFLAGS = @JANSSON_CFLAGS@ JANSSON_LIBS = @JANSSON_LIBS@ KAFKA_CFLAGS = @KAFKA_CFLAGS@ KAFKA_LIBS = @KAFKA_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKE = @MAKE@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONGODB_CFLAGS = @MONGODB_CFLAGS@ MONGODB_LIBS = @MONGODB_LIBS@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_VERSION = @MYSQL_VERSION@ NDPI_CFLAGS = @NDPI_CFLAGS@ NDPI_LIBS = @NDPI_LIBS@ NFLOG_CFLAGS = @NFLOG_CFLAGS@ NFLOG_LIBS = @NFLOG_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCAP_CONFIG = @PCAP_CONFIG@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PMACCT_CFLAGS = @PMACCT_CFLAGS@ PMACCT_VERSION = @PMACCT_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ REDIS_CFLAGS = @REDIS_CFLAGS@ REDIS_LIBS = @REDIS_LIBS@ SED = @SED@ SERDES_CFLAGS = @SERDES_CFLAGS@ SERDES_LIBS = @SERDES_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ UNYTE_UDP_NOTIF_CFLAGS = @UNYTE_UDP_NOTIF_CFLAGS@ UNYTE_UDP_NOTIF_LIBS = @UNYTE_UDP_NOTIF_LIBS@ VERSION = @VERSION@ ZMQ_CFLAGS = @ZMQ_CFLAGS@ ZMQ_LIBS = @ZMQ_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configure_silent_rules_val = @configure_silent_rules_val@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libnfprobe_plugin.la libnfprobe_plugin_la_SOURCES = nfprobe_plugin.c netflow5.c \ netflow9.c convtime.c common.h convtime.h sys-tree.h \ nfprobe_plugin.h treetype.h libnfprobe_plugin_la_CFLAGS = -DFLOW_SPLAY -DEXPIRY_RB -I$(srcdir)/.. $(AM_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/nfprobe_plugin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/nfprobe_plugin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libnfprobe_plugin.la: $(libnfprobe_plugin_la_OBJECTS) $(libnfprobe_plugin_la_DEPENDENCIES) $(EXTRA_libnfprobe_plugin_la_DEPENDENCIES) $(AM_V_CCLD)$(libnfprobe_plugin_la_LINK) $(libnfprobe_plugin_la_OBJECTS) $(libnfprobe_plugin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnfprobe_plugin_la-convtime.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnfprobe_plugin_la-netflow5.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnfprobe_plugin_la-netflow9.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libnfprobe_plugin_la-nfprobe_plugin.lo: nfprobe_plugin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libnfprobe_plugin_la-nfprobe_plugin.lo -MD -MP -MF $(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Tpo -c -o libnfprobe_plugin_la-nfprobe_plugin.lo `test -f 'nfprobe_plugin.c' || echo '$(srcdir)/'`nfprobe_plugin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Tpo $(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nfprobe_plugin.c' object='libnfprobe_plugin_la-nfprobe_plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libnfprobe_plugin_la-nfprobe_plugin.lo `test -f 'nfprobe_plugin.c' || echo '$(srcdir)/'`nfprobe_plugin.c libnfprobe_plugin_la-netflow5.lo: netflow5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libnfprobe_plugin_la-netflow5.lo -MD -MP -MF $(DEPDIR)/libnfprobe_plugin_la-netflow5.Tpo -c -o libnfprobe_plugin_la-netflow5.lo `test -f 'netflow5.c' || echo '$(srcdir)/'`netflow5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnfprobe_plugin_la-netflow5.Tpo $(DEPDIR)/libnfprobe_plugin_la-netflow5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netflow5.c' object='libnfprobe_plugin_la-netflow5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libnfprobe_plugin_la-netflow5.lo `test -f 'netflow5.c' || echo '$(srcdir)/'`netflow5.c libnfprobe_plugin_la-netflow9.lo: netflow9.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libnfprobe_plugin_la-netflow9.lo -MD -MP -MF $(DEPDIR)/libnfprobe_plugin_la-netflow9.Tpo -c -o libnfprobe_plugin_la-netflow9.lo `test -f 'netflow9.c' || echo '$(srcdir)/'`netflow9.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnfprobe_plugin_la-netflow9.Tpo $(DEPDIR)/libnfprobe_plugin_la-netflow9.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netflow9.c' object='libnfprobe_plugin_la-netflow9.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libnfprobe_plugin_la-netflow9.lo `test -f 'netflow9.c' || echo '$(srcdir)/'`netflow9.c libnfprobe_plugin_la-convtime.lo: convtime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -MT libnfprobe_plugin_la-convtime.lo -MD -MP -MF $(DEPDIR)/libnfprobe_plugin_la-convtime.Tpo -c -o libnfprobe_plugin_la-convtime.lo `test -f 'convtime.c' || echo '$(srcdir)/'`convtime.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnfprobe_plugin_la-convtime.Tpo $(DEPDIR)/libnfprobe_plugin_la-convtime.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='convtime.c' object='libnfprobe_plugin_la-convtime.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnfprobe_plugin_la_CFLAGS) $(CFLAGS) -c -o libnfprobe_plugin_la-convtime.lo `test -f 'convtime.c' || echo '$(srcdir)/'`convtime.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-convtime.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-netflow5.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-netflow9.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-convtime.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-netflow5.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-netflow9.Plo -rm -f ./$(DEPDIR)/libnfprobe_plugin_la-nfprobe_plugin.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: pmacct-1.7.8/src/nfprobe_plugin/Makefile.am0000644000175000017500000000045514354105275017652 0ustar paolopaoloAM_CFLAGS = $(PMACCT_CFLAGS) noinst_LTLIBRARIES = libnfprobe_plugin.la libnfprobe_plugin_la_SOURCES = nfprobe_plugin.c netflow5.c \ netflow9.c convtime.c common.h convtime.h sys-tree.h \ nfprobe_plugin.h treetype.h libnfprobe_plugin_la_CFLAGS = -DFLOW_SPLAY -DEXPIRY_RB -I$(srcdir)/.. $(AM_CFLAGS) pmacct-1.7.8/src/plugin_hooks.c0000644000175000017500000010101614354105275015445 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "thread_pool.h" #include "plugin_hooks.h" #include "plugin_common.h" #include "pkt_handlers.h" /* functions */ /* load_plugins() starts plugin processes; creates pipes and handles them inserting in channels_list structure */ /* no AMQP: when not using map_shared, 'pipe_size' is the size of the pipe created with socketpair(); when map_shared is enabled, it refers to the size of the shared memory area */ void load_plugins(struct plugin_requests *req) { u_int64_t buf_pipe_ratio_sz = 0, pipe_idx = 0; int snd_buflen = 0, rcv_buflen = 0, socklen = 0, target_buflen = 0; int nfprobe_id = 0, min_sz = 0, extra_sz = 0, offset = 0; struct plugins_list_entry *list = plugins_list; socklen_t l = sizeof(list->cfg.pipe_size); struct channels_list_entry *chptr = NULL; init_random_seed(); init_pipe_channels(); #ifdef WITH_ZMQ char username[SHORTBUFLEN], password[SHORTBUFLEN]; memset(username, 0, sizeof(username)); memset(password, 0, sizeof(password)); generate_random_string(username, (sizeof(username) - 1)); generate_random_string(password, (sizeof(password) - 1)); #endif while (list) { if ((*list->type.func)) { if (list->cfg.data_type & (PIPE_TYPE_METADATA|PIPE_TYPE_PAYLOAD|PIPE_TYPE_MSG)); else { Log(LOG_ERR, "ERROR ( %s/%s ): Data type not supported: %d\n", list->name, list->type.string, list->cfg.data_type); exit_gracefully(1); } min_sz = ChBufHdrSz; list->cfg.buffer_immediate = FALSE; if (list->cfg.data_type & PIPE_TYPE_METADATA) min_sz += PdataSz; if (list->cfg.data_type & PIPE_TYPE_PAYLOAD) { if (list->cfg.acct_type == ACCT_PM && list->cfg.snaplen && list->cfg.snaplen < DEFAULT_SFPROBE_PLOAD_SIZE) { min_sz += (PpayloadSz + list->cfg.snaplen); } else { min_sz += (PpayloadSz + DEFAULT_SFPROBE_PLOAD_SIZE); } } if (list->cfg.data_type & PIPE_TYPE_EXTRAS) min_sz += PextrasSz; if (list->cfg.data_type & PIPE_TYPE_MSG) { min_sz += PmsgSz; if (!list->cfg.buffer_size) { extra_sz = PKT_MSG_SIZE; list->cfg.buffer_immediate = TRUE; } } if (list->cfg.data_type & PIPE_TYPE_BGP) min_sz += sizeof(struct pkt_bgp_primitives); if (list->cfg.data_type & PIPE_TYPE_LBGP) min_sz += sizeof(struct pkt_legacy_bgp_primitives); if (list->cfg.data_type & PIPE_TYPE_NAT) min_sz += sizeof(struct pkt_nat_primitives); if (list->cfg.data_type & PIPE_TYPE_TUN) min_sz += sizeof(struct pkt_tunnel_primitives); if (list->cfg.data_type & PIPE_TYPE_MPLS) min_sz += sizeof(struct pkt_mpls_primitives); if (list->cfg.cpptrs.len) min_sz += list->cfg.cpptrs.len; if (list->cfg.data_type & PIPE_TYPE_VLEN) { min_sz += sizeof(struct pkt_vlen_hdr_primitives); if (!list->cfg.buffer_size) { extra_sz = 1024; /* wild shot: 1Kb added for the actual variable-length data */ list->cfg.buffer_immediate = TRUE; } } /* If nothing is supplied, let's hint some working default values */ if (!list->cfg.pipe_size || !list->cfg.buffer_size) { if (!list->cfg.pipe_size) list->cfg.pipe_size = 4096000; /* 4Mb */ if (!list->cfg.buffer_size) { if (list->cfg.pcap_savefile) list->cfg.buffer_size = 10240; /* 10Kb */ else list->cfg.buffer_size = MIN((min_sz + extra_sz), 10240); } } /* some validations */ if (list->cfg.pipe_size < min_sz) list->cfg.pipe_size = min_sz; if (list->cfg.buffer_size < min_sz) list->cfg.buffer_size = min_sz; if (list->cfg.buffer_size > list->cfg.pipe_size) list->cfg.buffer_size = list->cfg.pipe_size; /* if required let's align plugin_buffer_size to 4 bytes boundary */ #if NEED_ALIGN while (list->cfg.buffer_size % 4 != 0) list->cfg.buffer_size--; #endif if (!list->cfg.pipe_zmq) { /* creating communication channel */ socketpair(AF_UNIX, SOCK_DGRAM, 0, list->pipe); /* checking SO_RCVBUF and SO_SNDBUF values; if different we take the smaller one */ getsockopt(list->pipe[0], SOL_SOCKET, SO_RCVBUF, &rcv_buflen, &l); getsockopt(list->pipe[1], SOL_SOCKET, SO_SNDBUF, &snd_buflen, &l); socklen = (rcv_buflen < snd_buflen) ? rcv_buflen : snd_buflen; buf_pipe_ratio_sz = (list->cfg.pipe_size/list->cfg.buffer_size)*sizeof(char *); if (buf_pipe_ratio_sz > INT_MAX) { Log(LOG_ERR, "ERROR ( %s/%s ): Current plugin_buffer_size elems per plugin_pipe_size: %llu. Max: %d.\nExiting.\n", list->name, list->type.string, (unsigned long long)(list->cfg.pipe_size/list->cfg.buffer_size), (INT_MAX/(int)sizeof(char *))); exit_gracefully(1); } else target_buflen = buf_pipe_ratio_sz; if (target_buflen > socklen) { Setsocksize(list->pipe[0], SOL_SOCKET, SO_RCVBUF, &target_buflen, l); Setsocksize(list->pipe[1], SOL_SOCKET, SO_SNDBUF, &target_buflen, l); } getsockopt(list->pipe[0], SOL_SOCKET, SO_RCVBUF, &rcv_buflen, &l); getsockopt(list->pipe[1], SOL_SOCKET, SO_SNDBUF, &snd_buflen, &l); if (rcv_buflen < snd_buflen) snd_buflen = rcv_buflen; if (snd_buflen < socklen) { Setsocksize(list->pipe[0], SOL_SOCKET, SO_RCVBUF, &socklen, l); Setsocksize(list->pipe[1], SOL_SOCKET, SO_SNDBUF, &socklen, l); getsockopt(list->pipe[0], SOL_SOCKET, SO_RCVBUF, &rcv_buflen, &l); getsockopt(list->pipe[1], SOL_SOCKET, SO_SNDBUF, &snd_buflen, &l); if (rcv_buflen < snd_buflen) snd_buflen = rcv_buflen; } if (list->cfg.debug || (list->cfg.pipe_size > WARNING_PIPE_SIZE)) { Log(LOG_INFO, "INFO ( %s/%s ): plugin_pipe_size=%" PRIu64 " bytes plugin_buffer_size=%" PRIu64 " bytes\n", list->name, list->type.string, list->cfg.pipe_size, list->cfg.buffer_size); if (target_buflen <= snd_buflen) Log(LOG_INFO, "INFO ( %s/%s ): ctrl channel: obtained=%d bytes target=%d bytes\n", list->name, list->type.string, snd_buflen, target_buflen); else /* This should return an error and exit but we fallback to a warning in order to be backward compatible */ Log(LOG_WARNING, "WARN ( %s/%s ): ctrl channel: obtained=%d bytes target=%d bytes\n", list->name, list->type.string, snd_buflen, target_buflen); } } else { pipe_idx++; list->pipe[0] = list->pipe[1] = pipe_idx; } list->cfg.name = list->name; list->cfg.type = list->type.string; list->cfg.type_id = list->type.id; chptr = insert_pipe_channel(list->type.id, &list->cfg, list->pipe[1]); if (!chptr) { Log(LOG_ERR, "ERROR ( %s/%s ): Unable to setup a new Core Process <-> Plugin channel.\nExiting.\n", list->name, list->type.string); exit_gracefully(1); } else chptr->plugin = list; /* sets new value to be assigned to 'wakeup'; 'TRUE' disables on-request wakeup */ if (list->type.id == PLUGIN_ID_MEMORY) chptr->request = TRUE; /* sets fixed/vlen offsets and cleaner routine; XXX: we should refine the cleaner part: 1) ie. extras assumes it's automagically piled with metadata; 2) what if multiple vlen components are stacked up? */ if (list->cfg.data_type & PIPE_TYPE_METADATA) { chptr->clean_func = pkt_data_clean; offset = sizeof(struct pkt_data); } if (list->cfg.data_type & PIPE_TYPE_PAYLOAD) chptr->clean_func = pkt_payload_clean; if (list->cfg.data_type & PIPE_TYPE_EXTRAS) { chptr->extras.off_pkt_extras = offset; offset += sizeof(struct pkt_extras); } if (list->cfg.data_type & PIPE_TYPE_MSG) chptr->clean_func = pkt_msg_clean; if (list->cfg.data_type & PIPE_TYPE_BGP) { chptr->extras.off_pkt_bgp_primitives = offset; offset += sizeof(struct pkt_bgp_primitives); } else chptr->extras.off_pkt_bgp_primitives = 0; if (list->cfg.data_type & PIPE_TYPE_LBGP) { chptr->extras.off_pkt_lbgp_primitives = offset; offset += sizeof(struct pkt_legacy_bgp_primitives); } else chptr->extras.off_pkt_lbgp_primitives = 0; if (list->cfg.data_type & PIPE_TYPE_NAT) { chptr->extras.off_pkt_nat_primitives = offset; offset += sizeof(struct pkt_nat_primitives); } else chptr->extras.off_pkt_nat_primitives = 0; if (list->cfg.data_type & PIPE_TYPE_TUN) { chptr->extras.off_pkt_tun_primitives = offset; offset += sizeof(struct pkt_tunnel_primitives); } else chptr->extras.off_pkt_tun_primitives = 0; if (list->cfg.data_type & PIPE_TYPE_MPLS) { chptr->extras.off_pkt_mpls_primitives = offset; offset += sizeof(struct pkt_mpls_primitives); } else chptr->extras.off_pkt_mpls_primitives = 0; if (list->cfg.cpptrs.len) { chptr->extras.off_custom_primitives = offset; offset += list->cfg.cpptrs.len; } /* PIPE_TYPE_VLEN at the end of the stack so to not make vlen other structures (although possible it would not make much sense) */ if (list->cfg.data_type & PIPE_TYPE_VLEN) { chptr->extras.off_pkt_vlen_hdr_primitives = offset; offset += sizeof(struct pkt_vlen_hdr_primitives); } else chptr->extras.off_pkt_vlen_hdr_primitives = 0; /* any further offset beyond this point must be set to PM_VARIABLE_LENGTH so to indicate plugins to resolve value at runtime. */ chptr->datasize = min_sz-ChBufHdrSz; /* sets nfprobe ID */ if (list->type.id == PLUGIN_ID_NFPROBE) { list->cfg.nfprobe_id = nfprobe_id; nfprobe_id++; } /* ZMQ inits, if required */ #ifdef WITH_ZMQ if (list->cfg.pipe_zmq) { char log_id[LARGEBUFLEN]; p_zmq_plugin_pipe_init_core(&chptr->zmq_host, list->id, username, password); snprintf(log_id, sizeof(log_id), "%s/%s", list->name, list->type.string); p_zmq_set_log_id(&chptr->zmq_host, log_id); p_zmq_pub_setup(&chptr->zmq_host); } #endif switch (list->pid = fork()) { case -1: /* Something went wrong */ Log(LOG_WARNING, "WARN ( %s/%s ): Unable to initialize plugin: %s\n", list->name, list->type.string, strerror(errno)); delete_pipe_channel(list->pipe[1]); break; case 0: /* Child */ /* SIGCHLD handling issue: SysV avoids zombies by ignoring SIGCHLD; to emulate such semantics on BSD systems, we need an handler like handle_falling_child() */ #if defined (SOLARIS) signal(SIGCHLD, SIG_IGN); #else signal(SIGCHLD, ignore_falling_child); #endif #if defined HAVE_MALLOPT mallopt(M_CHECK_ACTION, 0); #endif if (device.dev_desc) pcap_close(device.dev_desc); close(config.sock); close(config.bgp_sock); if (!list->cfg.pipe_zmq) close(list->pipe[1]); (*list->type.func)(list->pipe[0], &list->cfg, chptr); exit_gracefully(0); default: /* Parent */ if (!list->cfg.pipe_zmq) { close(list->pipe[0]); setnonblocking(list->pipe[1]); } break; } /* some residual check */ if (chptr && list->cfg.a_filter) req->bpf_filter = TRUE; } list = list->next; } sort_pipe_channels(); /* define pre_tag_map(s) now so that they don't finish unnecessarily in plugin memory space */ { int ptm_index = 0, ptm_global = FALSE; char *ptm_ptr = NULL; list = plugins_list; while (list) { if (list->cfg.pre_tag_map) { if (!ptm_index) { ptm_ptr = list->cfg.pre_tag_map; ptm_global = TRUE; } else { if (!ptm_ptr || strcmp(ptm_ptr, list->cfg.pre_tag_map)) ptm_global = FALSE; } if (list->cfg.type_id == PLUGIN_ID_TEE) { req->ptm_c.load_ptm_plugin = list->cfg.type_id; req->ptm_c.load_ptm_res = FALSE; } load_pre_tag_map(config.acct_type, list->cfg.pre_tag_map, &list->cfg.ptm, req, &list->cfg.ptm_alloc, list->cfg.maps_entries, list->cfg.maps_row_len); if (list->cfg.type_id == PLUGIN_ID_TEE) { list->cfg.ptm_complex = req->ptm_c.load_ptm_res; if (req->ptm_c.load_ptm_res) req->ptm_c.exec_ptm_dissect = TRUE; } } if (list->cfg.type_id != PLUGIN_ID_TEE) { if (list->cfg.acct_type == ACCT_NF && list->cfg.nfacctd_account_options) { int have_sample_type = FALSE; if (list->cfg.ptm.index_num) { int idx; for (idx = 0; idx < list->cfg.ptm.index_num; idx++) { if (list->cfg.ptm.index[idx].bitmap & PRETAG_SAMPLE_TYPE) { have_sample_type = TRUE; } } } if ((!have_sample_type && !list->cfg.ptm.num) || (!have_sample_type && list->cfg.ptm.index_num)) { Log(LOG_WARNING, "WARN ( %s/%s ): nfacctd_account_options is enabled but pre_tag_map does not contain a sample_type rule.\n", list->name, list->type.string); } } } list = list->next; ptm_index++; } /* enforcing global flag */ list = plugins_list; while (list) { list->cfg.ptm_global = ptm_global; list = list->next; } } } void exec_plugins(struct packet_ptrs *pptrs, struct plugin_requests *req) { int saved_have_tag = FALSE, saved_have_tag2 = FALSE, saved_have_label = FALSE; pm_id_t saved_tag = 0, saved_tag2 = 0; pt_label_t *saved_label = malloc(sizeof(pt_label_t)); int num, fixed_size; u_int32_t savedptr; char *bptr; int index, got_tags = FALSE; pretag_init_label(saved_label); #if defined WITH_GEOIPV2 if (reload_geoipv2_file && config.geoipv2_file) { pm_geoipv2_close(); pm_geoipv2_init(); reload_geoipv2_file = FALSE; } #endif for (index = 0; channels_list[index].aggregation || channels_list[index].aggregation_2; index++) { struct plugins_list_entry *p = channels_list[index].plugin; channels_list[index].already_reprocessed = FALSE; if (p->cfg.pre_tag_map && find_id_func) { if (p->cfg.type_id == PLUGIN_ID_TEE) { /* replicate and compute tagging if: - a dissected flow hits a complex pre_tag_map or - a non-dissected (full) packet hits a simple pre_tag_map */ if ((req->ptm_c.exec_ptm_res && !p->cfg.ptm_complex) || (!req->ptm_c.exec_ptm_res && p->cfg.ptm_complex)) continue; } if (p->cfg.ptm_global && got_tags) { pptrs->tag = saved_tag; pptrs->tag2 = saved_tag2; pretag_copy_label(&pptrs->label, saved_label); pptrs->have_tag = saved_have_tag; pptrs->have_tag2 = saved_have_tag2; pptrs->have_label = saved_have_label; } else { if (p->cfg.type_id == PLUGIN_ID_TEE && req->ptm_c.exec_ptm_res && pptrs->tee_dissect_bcast) /* noop */; else { find_id_func(&p->cfg.ptm, pptrs, &pptrs->tag, &pptrs->tag2); if (p->cfg.ptm_global) { saved_tag = pptrs->tag; saved_tag2 = pptrs->tag2; pretag_copy_label(saved_label, &pptrs->label); saved_have_tag = pptrs->have_tag; saved_have_tag2 = pptrs->have_tag2; saved_have_label = pptrs->have_label; got_tags = TRUE; } } } } else { if (p->cfg.type_id == PLUGIN_ID_TEE) { /* stop dissected flows from being replicated in case of no pre_tag_map */ if (req->ptm_c.exec_ptm_res) continue; } } if (evaluate_filters(&channels_list[index].agg_filter, pptrs->packet_ptr, pptrs->pkthdr) && !evaluate_tags(&channels_list[index].tag_filter, pptrs->tag) && !evaluate_tags(&channels_list[index].tag2_filter, pptrs->tag2) && !evaluate_labels(&channels_list[index].label_filter, &pptrs->label) && !check_shadow_status(pptrs, &channels_list[index])) { /* arranging buffer: supported primitives + packet total length */ reprocess: channels_list[index].reprocess = FALSE; num = 0; /* rg.ptr points to slot's base address into the ring (shared memory); bufptr works as a displacement into the slot to place sequentially packets */ bptr = channels_list[index].rg.ptr+ChBufHdrSz+channels_list[index].bufptr; fixed_size = (*channels_list[index].clean_func)(bptr, channels_list[index].datasize); channels_list[index].var_size = 0; savedptr = channels_list[index].bufptr; reset_fallback_status(pptrs); while (channels_list[index].phandler[num]) { (*channels_list[index].phandler[num])(&channels_list[index], pptrs, &bptr); num++; } if (channels_list[index].s.rate && !channels_list[index].s.sampled_pkts) { channels_list[index].reprocess = FALSE; channels_list[index].bufptr = savedptr; channels_list[index].hdr.num--; /* let's cheat this value as it will get increased later */ fixed_size = 0; channels_list[index].var_size = 0; } if (channels_list[index].reprocess) { /* Let's check if we have an issue with the buffer size */ if (channels_list[index].already_reprocessed) { struct plugins_list_entry *list = channels_list[index].plugin; Log(LOG_ERR, "ERROR ( %s/%s ): plugin_buffer_size is too short.\n", list->name, list->type.string); exit_gracefully(1); } channels_list[index].already_reprocessed = TRUE; /* Let's cheat the size in order to send out the current buffer */ fixed_size = channels_list[index].plugin->cfg.pipe_size; } else { channels_list[index].hdr.num++; channels_list[index].bufptr += (fixed_size + channels_list[index].var_size); } if (((channels_list[index].bufptr + fixed_size) > channels_list[index].bufend) || (channels_list[index].hdr.num == INT_MAX) || channels_list[index].buffer_immediate) { channels_list[index].hdr.seq++; channels_list[index].hdr.seq %= MAX_SEQNUM; /* let's commit the buffer we just finished writing */ ((struct ch_buf_hdr *)channels_list[index].rg.ptr)->len = channels_list[index].bufptr; ((struct ch_buf_hdr *)channels_list[index].rg.ptr)->seq = channels_list[index].hdr.seq; ((struct ch_buf_hdr *)channels_list[index].rg.ptr)->num = channels_list[index].hdr.num; channels_list[index].status->last_buf_off = (u_int64_t)(channels_list[index].rg.ptr - channels_list[index].rg.base); if (config.debug_internal_msg) { struct plugins_list_entry *list = channels_list[index].plugin; Log(LOG_DEBUG, "DEBUG ( %s/%s ): buffer released len=%" PRIu64 " seq=%u num_entries=%u off=%" PRIu64 "\n", list->name, list->type.string, channels_list[index].bufptr, channels_list[index].hdr.seq, channels_list[index].hdr.num, channels_list[index].status->last_buf_off); } /* sending buffer to connected ZMQ subscriber(s) */ if (channels_list[index].plugin->cfg.pipe_zmq) { #ifdef WITH_ZMQ struct channels_list_entry *chptr = &channels_list[index]; int ret = p_zmq_topic_send(&chptr->zmq_host, chptr->rg.ptr, chptr->bufsize); (void)ret; //Check error? #endif } else { if (channels_list[index].status->wakeup) { channels_list[index].status->wakeup = channels_list[index].request; if (write(channels_list[index].pipe, &channels_list[index].rg.ptr, CharPtrSz) != CharPtrSz) { struct plugins_list_entry *list = channels_list[index].plugin; Log(LOG_WARNING, "WARN ( %s/%s ): Failed during write: %s\n", list->name, list->type.string, strerror(errno)); } } } channels_list[index].rg.ptr += channels_list[index].bufsize; if ((channels_list[index].rg.ptr+channels_list[index].bufsize) > channels_list[index].rg.end) channels_list[index].rg.ptr = channels_list[index].rg.base; /* let's protect the buffer we are going to write */ ((struct ch_buf_hdr *)channels_list[index].rg.ptr)->seq = -1; ((struct ch_buf_hdr *)channels_list[index].rg.ptr)->num = 0; /* rewind pointer */ channels_list[index].bufptr = channels_list[index].buf; channels_list[index].hdr.num = 0; if (channels_list[index].reprocess) goto reprocess; /* if reading from a savefile, let's sleep a bit after having sent over a buffer worth of data */ if (channels_list[index].plugin->cfg.pcap_savefile) usleep(1000); /* 1 msec */ } } pptrs->tag = 0; pptrs->tag2 = 0; pretag_free_label(&pptrs->label); } /* check if we have to reload the map: new loop is to ensure we reload it for all plugins and prevent any timing issues with pointers to labels */ if (reload_map_exec_plugins) { memset(&req->ptm_c, 0, sizeof(struct ptm_complex)); for (index = 0; channels_list[index].aggregation || channels_list[index].aggregation_2; index++) { struct plugins_list_entry *p = channels_list[index].plugin; if (p->cfg.pre_tag_map && find_id_func) { if (p->cfg.type_id == PLUGIN_ID_TEE) { req->ptm_c.load_ptm_plugin = p->cfg.type_id; req->ptm_c.load_ptm_res = FALSE; } load_pre_tag_map(config.acct_type, p->cfg.pre_tag_map, &p->cfg.ptm, req, &p->cfg.ptm_alloc, p->cfg.maps_entries, p->cfg.maps_row_len); if (p->cfg.type_id == PLUGIN_ID_TEE) { p->cfg.ptm_complex = req->ptm_c.load_ptm_res; if (req->ptm_c.load_ptm_res) req->ptm_c.exec_ptm_dissect = TRUE; } } } } /* cleanups */ reload_map_exec_plugins = FALSE; pretag_free_label(saved_label); if (saved_label) free(saved_label); } struct channels_list_entry *insert_pipe_channel(int plugin_type, struct configuration *cfg, int pipe) { struct channels_list_entry *chptr; int index = 0; while (index < MAX_N_PLUGINS) { chptr = &channels_list[index]; if (!chptr->aggregation && !chptr->aggregation_2) { /* found room */ chptr->aggregation = cfg->what_to_count; chptr->aggregation_2 = cfg->what_to_count_2; chptr->pipe = pipe; chptr->agg_filter.table = cfg->bpfp_a_table; chptr->agg_filter.num = (int *) &cfg->bpfp_a_num; chptr->bufsize = cfg->buffer_size; chptr->buffer_immediate = cfg->buffer_immediate; chptr->core_pid = getpid(); chptr->tag = cfg->post_tag; chptr->tag2 = cfg->post_tag2; if (cfg->sampling_rate && plugin_type != PLUGIN_ID_SFPROBE) { /* sfprobe cares for itself */ chptr->s.rate = cfg->sampling_rate; if (cfg->acct_type == ACCT_NF) chptr->s.sf = &take_simple_systematic_skip; else chptr->s.sf = &take_simple_random_skip; } memcpy(&chptr->tag_filter, &cfg->ptf, sizeof(struct pretag_filter)); memcpy(&chptr->tag2_filter, &cfg->pt2f, sizeof(struct pretag_filter)); memcpy(&chptr->label_filter, &cfg->ptlf, sizeof(struct pretag_label_filter)); chptr->buf = 0; chptr->bufptr = chptr->buf; chptr->bufend = cfg->buffer_size-sizeof(struct ch_buf_hdr); // XXX: no need to map_shared() if using AMQP /* +PKT_MSG_SIZE has been introduced as a margin as a countermeasure against the reception of malicious NetFlow v9 templates */ chptr->rg.base = map_shared(0, cfg->pipe_size+PKT_MSG_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (chptr->rg.base == MAP_FAILED) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate pipe buffer. Exiting ...\n", cfg->name, cfg->type); exit_gracefully(1); } memset(chptr->rg.base, 0, cfg->pipe_size); chptr->rg.ptr = chptr->rg.base; chptr->rg.end = chptr->rg.base+cfg->pipe_size; chptr->status = map_shared(0, sizeof(struct ch_status), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (chptr->status == MAP_FAILED) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate status buffer. Exiting ...\n", cfg->name, cfg->type); exit_gracefully(1); } memset(chptr->status, 0, sizeof(struct ch_status)); break; } else chptr = NULL; index++; } return chptr; } void delete_pipe_channel(int pipe) { struct channels_list_entry *chptr; int index = 0, index2; while (index < MAX_N_PLUGINS) { chptr = &channels_list[index]; if (chptr->pipe == pipe) { chptr->aggregation = FALSE; chptr->aggregation_2 = FALSE; /* we ensure that any plugin is depending on the one being removed via the 'same_aggregate' flag */ if (!chptr->same_aggregate) { index2 = index; for (index2++; index2 < MAX_N_PLUGINS; index2++) { chptr = &channels_list[index2]; if (!chptr->aggregation && !chptr->aggregation_2) break; /* we finished channels */ if (chptr->same_aggregate) { chptr->same_aggregate = FALSE; break; } else break; /* we have nothing to do */ } } index2 = index; for (index2++; index2 < MAX_N_PLUGINS; index2++) { chptr = &channels_list[index2]; if (chptr->aggregation || chptr->aggregation_2) { memcpy(&channels_list[index], chptr, sizeof(struct channels_list_entry)); memset(chptr, 0, sizeof(struct channels_list_entry)); index++; } else break; /* we finished channels */ } break; } index++; } } /* trivial sorting(tm) :-) */ void sort_pipe_channels() { struct channels_list_entry ctmp; int x = 0, y = 0; while (x < MAX_N_PLUGINS) { if (!channels_list[x].aggregation && !channels_list[x].aggregation_2) break; y = x+1; while (y < MAX_N_PLUGINS) { if (!channels_list[y].aggregation && !channels_list[y].aggregation_2) break; if (channels_list[x].aggregation == channels_list[y].aggregation && channels_list[x].aggregation_2 == channels_list[y].aggregation_2) { channels_list[y].same_aggregate = TRUE; if (y == x+1) x++; else { memcpy(&ctmp, &channels_list[x+1], sizeof(struct channels_list_entry)); memcpy(&channels_list[x+1], &channels_list[y], sizeof(struct channels_list_entry)); memcpy(&channels_list[y], &ctmp, sizeof(struct channels_list_entry)); x++; } } y++; } x++; } } void init_pipe_channels() { memset(&channels_list, 0, MAX_N_PLUGINS*sizeof(struct channels_list_entry)); } void evaluate_sampling(struct sampling *smp, pm_counter_t *pkt_len, pm_counter_t *pkt_num, pm_counter_t *sample_pool) { pm_counter_t delta, pkts = *pkt_num; if (!smp->rate) { /* sampling is disabled */ smp->sample_pool = pkts; smp->sampled_pkts = pkts; return; } smp->sampled_pkts = 0; run_again: if (!smp->counter) smp->counter = (smp->sf)(smp->rate); delta = MIN(smp->counter, pkts); smp->counter -= delta; pkts -= delta; smp->sample_pool += delta; if (!smp->counter) { smp->sampled_pkts++; *sample_pool = smp->sample_pool; smp->sample_pool = 0; if (pkts > 0) goto run_again; } /* Let's handle flows meaningfully */ if (smp->sampled_pkts && *pkt_num > 1) { *pkt_len = ( *pkt_len / *pkt_num ) * smp->sampled_pkts; *pkt_num = smp->sampled_pkts; } } /* simple random algorithm */ pm_counter_t take_simple_random_skip(pm_counter_t mean) { pm_counter_t skip; if (mean > 1) { skip = ((random() % ((2 * mean) - 1)) + 1); srandom(random()); } else skip = 1; /* smp->rate == 1 */ return skip; } /* simple systematic algorithm */ pm_counter_t take_simple_systematic_skip(pm_counter_t mean) { pm_counter_t skip = mean; return skip; } /* return value: TRUE: We want it! FALSE: Discard it! */ int evaluate_filters(struct aggregate_filter *filter, u_char *pkt, struct pcap_pkthdr *pkthdr) { int index; if (*filter->num == 0) return TRUE; /* no entries in the filter array: aggregate filtering disabled */ for (index = 0; index < *filter->num; index++) { if (bpf_filter(filter->table[index]->bf_insns, pkt, pkthdr->len, pkthdr->caplen)) return TRUE; } return FALSE; } void recollect_pipe_memory(struct channels_list_entry *mychptr) { struct channels_list_entry *chptr; int index = 0; while (index < MAX_N_PLUGINS) { chptr = &channels_list[index]; if (mychptr->rg.base != chptr->rg.base) { munmap(chptr->rg.base, (chptr->rg.end-chptr->rg.base)+PKT_MSG_SIZE); munmap(chptr->status, sizeof(struct ch_status)); } index++; } } void init_random_seed() { struct timeval tv; gettimeofday(&tv, NULL); srandom((unsigned int)tv.tv_usec); } void fill_pipe_buffer() { struct channels_list_entry *chptr; int index; for (index = 0; channels_list[index].aggregation || channels_list[index].aggregation_2; index++) { chptr = &channels_list[index]; chptr->hdr.seq++; chptr->hdr.seq %= MAX_SEQNUM; ((struct ch_buf_hdr *)chptr->rg.ptr)->seq = chptr->hdr.seq; ((struct ch_buf_hdr *)chptr->rg.ptr)->num = chptr->hdr.num; if (chptr->plugin->cfg.pipe_zmq) { #ifdef WITH_ZMQ p_zmq_topic_send(&chptr->zmq_host, chptr->rg.ptr, chptr->bufsize); #endif } else { if (chptr->status->wakeup) { chptr->status->wakeup = chptr->request; if (write(chptr->pipe, &chptr->rg.ptr, CharPtrSz) != CharPtrSz) Log(LOG_WARNING, "WARN ( %s/%s ): Failed during write: %s\n", chptr->plugin->cfg.name, chptr->plugin->cfg.type, strerror(errno)); } } } } int check_pipe_buffer_space(struct channels_list_entry *mychptr, struct pkt_vlen_hdr_primitives *pvlen, int len) { int buf_space = 0; if (!mychptr) return ERR; /* init to base of current element */ buf_space = mychptr->bufend - mychptr->bufptr; /* subtract fixed part, current variable part and new var part (len) */ buf_space -= mychptr->datasize; if (pvlen) buf_space -= pvlen->tot_len; buf_space -= len; /* return virdict. if positive fix sizes. if negative take care of triggering a reprocess */ if (buf_space >= 0) { mychptr->var_size += len; return FALSE; } else { mychptr->bufptr += (mychptr->bufend - mychptr->bufptr); mychptr->reprocess = TRUE; mychptr->var_size = 0; return TRUE; } } void return_pipe_buffer_space(struct channels_list_entry *mychptr, int len) { if (!mychptr || !len) return; if (mychptr->var_size < len) return; mychptr->var_size -= len; } int check_shadow_status(struct packet_ptrs *pptrs, struct channels_list_entry *mychptr) { if (pptrs->shadow) { if (pptrs->tag && mychptr->aggregation & COUNT_TAG) return FALSE; else if (pptrs->tag2 && mychptr->aggregation & COUNT_TAG2) return FALSE; else return TRUE; } else return FALSE; } void load_plugin_filters(int link_type) { struct plugins_list_entry *list = plugins_list; while (list) { if ((*list->type.func)) { /* compiling aggregation filter if needed */ if (list->cfg.a_filter) { pcap_t *dev_desc; bpf_u_int32 localnet, netmask = 0; /* pcap library stuff */ char errbuf[PCAP_ERRBUF_SIZE], *count_token; int idx = 0; dev_desc = pcap_open_dead(link_type, 128); /* 128 bytes should be long enough */ if (config.pcap_if) pcap_lookupnet(config.pcap_if, &localnet, &netmask, errbuf); list->cfg.bpfp_a_table[idx] = malloc(sizeof(struct bpf_program)); while ( (count_token = extract_token(&list->cfg.a_filter, ',')) && idx < AGG_FILTER_ENTRIES ) { if (pcap_compile(dev_desc, list->cfg.bpfp_a_table[idx], count_token, 0, netmask) < 0) { Log(LOG_WARNING, "WARN: %s\nWARN ( %s/%s ): aggregation filter disabled.\n", pcap_geterr(dev_desc), list->cfg.name, list->cfg.type); } else { idx++; list->cfg.bpfp_a_table[idx] = malloc(sizeof(struct bpf_program)); } } list->cfg.bpfp_a_num = idx; } } list = list->next; } } int pkt_data_clean(void *pdata, int len) { memset(pdata, 0, len); return len; } int pkt_payload_clean(void *ppayload, int len) { memset(ppayload, 0, PpayloadSz); return PpayloadSz; } int pkt_msg_clean(void *ppayload, int len) { memset(ppayload, 0, PmsgSz); return PmsgSz; } int pkt_extras_clean(void *pextras, int len) { memset(pextras, 0, PdataSz+PextrasSz); return PdataSz+PextrasSz; } void plugin_pipe_zmq_compile_check() { #ifndef WITH_ZMQ Log(LOG_ERR, "ERROR ( %s/%s ): 'plugin_pipe_zmq' requires compiling with --enable-zmq. Exiting ..\n", config.name, config.type); exit_gracefully(1); #endif } void plugin_pipe_check(struct configuration *cfg) { if (!cfg->pipe_zmq) cfg->pipe_homegrown = TRUE; } void P_zmq_pipe_init(void *zh, int *pipe_fd, u_int32_t *seq) { plugin_pipe_zmq_compile_check(); #ifdef WITH_ZMQ if (zh) { struct p_zmq_host *zmq_host = zh; char log_id[LARGEBUFLEN]; p_zmq_plugin_pipe_init_plugin(zmq_host); snprintf(log_id, sizeof(log_id), "%s/%s", config.name, config.type); p_zmq_set_log_id(zmq_host, log_id); p_zmq_set_hwm(zmq_host, config.pipe_zmq_hwm); p_zmq_sub_setup(zmq_host); p_zmq_set_retry_timeout(zmq_host, config.pipe_zmq_retry); if (pipe_fd) (*pipe_fd) = p_zmq_get_fd(zmq_host); if (seq) (*seq) = 0; } #endif } pmacct-1.7.8/src/nl.c0000644000175000017500000007274014354105275013370 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "pmacct-dlt.h" #include "pretag_handlers.h" #include "plugin_hooks.h" #include "pkt_handlers.h" #include "ip_frag.h" #include "ip_flow.h" #include "net_aggr.h" #include "thread_pool.h" #include "isis/isis.h" #include "bgp/bgp.h" #include "bmp/bmp.h" #if defined (WITH_NDPI) #include "ndpi/ndpi.h" #endif struct tunnel_entry tunnel_handlers_list[] = { {"gtp", gtp_tunnel_func, gtp_tunnel_configurator}, {"", NULL, NULL}, }; void pm_pcap_cb(u_char *user, const struct pcap_pkthdr *pkthdr, const u_char *buf) { struct packet_ptrs pptrs; struct pm_pcap_callback_data *cb_data = (struct pm_pcap_callback_data *) user; struct pm_pcap_device *device = cb_data->device; struct plugin_requests req; u_int32_t iface32 = 0; u_int32_t ifacePresent = 0; memset(&req, 0, sizeof(req)); if (cb_data->sig.is_set) sigprocmask(SIG_BLOCK, &cb_data->sig.set, NULL); /* We process the packet with the appropriate data link layer function */ if (buf) { memset(&pptrs, 0, sizeof(pptrs)); pptrs.pkthdr = (struct pcap_pkthdr *) pkthdr; pptrs.packet_ptr = (u_char *) buf; pptrs.f_agent = cb_data->f_agent; pptrs.bpas_table = cb_data->bpas_table; pptrs.blp_table = cb_data->blp_table; pptrs.bmed_table = cb_data->bmed_table; pptrs.bta_table = cb_data->bta_table; pptrs.flow_type.traffic_type = PM_FTYPE_TRAFFIC; assert(cb_data); if (cb_data->has_tun_prims) { struct packet_ptrs *tpptrs; pptrs.tun_pptrs = malloc(sizeof(struct packet_ptrs)); memset(pptrs.tun_pptrs, 0, sizeof(struct packet_ptrs)); tpptrs = (struct packet_ptrs *) pptrs.tun_pptrs; tpptrs->pkthdr = malloc(sizeof(struct pcap_pkthdr)); memcpy(&tpptrs->pkthdr, &pptrs.pkthdr, sizeof(struct pcap_pkthdr)); tpptrs->packet_ptr = (u_char *) buf; tpptrs->flow_type.traffic_type = PM_FTYPE_TRAFFIC; } /* direction */ if (cb_data->device && cb_data->device->pcap_if && cb_data->device->pcap_if->direction) { pptrs.direction = cb_data->device->pcap_if->direction; } else if (config.pcap_direction) { pptrs.direction = config.pcap_direction; } else pptrs.direction = FALSE; /* input interface */ if (cb_data->ifindex_in) { pptrs.ifindex_in = cb_data->ifindex_in; } else if (cb_data->device && cb_data->device->id && cb_data->device->pcap_if && cb_data->device->pcap_if->direction) { if (cb_data->device->pcap_if->direction == PCAP_D_IN) { pptrs.ifindex_in = cb_data->device->id; } } else if (cb_data->device->id && config.pcap_direction == PCAP_D_IN) { pptrs.ifindex_in = cb_data->device->id; } else pptrs.ifindex_in = 0; /* output interface */ if (cb_data->ifindex_out) { pptrs.ifindex_out = cb_data->ifindex_out; } else if (cb_data->device && cb_data->device->id && cb_data->device->pcap_if && cb_data->device->pcap_if->direction) { if (cb_data->device->pcap_if->direction == PCAP_D_OUT) { pptrs.ifindex_out = cb_data->device->id; } } else if (cb_data->device->id && config.pcap_direction == PCAP_D_OUT) { pptrs.ifindex_out = cb_data->device->id; } else pptrs.ifindex_out = 0; if (config.pcap_arista_trailer_offset) { memcpy(&ifacePresent, buf + pkthdr->len - config.pcap_arista_trailer_offset, 4); if (ifacePresent == config.pcap_arista_trailer_flag_value) { memcpy(&iface32, buf + pkthdr->len - (config.pcap_arista_trailer_offset - 4), 4); pptrs.ifindex_out = iface32; } } (*device->data->handler)(pkthdr, &pptrs); if (pptrs.iph_ptr) { if ((*pptrs.l3_handler)(&pptrs)) { #if defined (WITH_NDPI) if (config.classifier_ndpi && pm_ndpi_wfl) { pptrs.ndpi_class = pm_ndpi_workflow_process_packet(pm_ndpi_wfl, &pptrs); } #endif if (config.nfacctd_isis) { isis_srcdst_lookup(&pptrs); } if (config.bgp_daemon) { BTA_find_id((struct id_table *)pptrs.bta_table, &pptrs, &pptrs.bta, &pptrs.bta2); bgp_srcdst_lookup(&pptrs, FUNC_TYPE_BGP); } if (config.bgp_daemon_peer_as_src_map) PM_find_id((struct id_table *)pptrs.bpas_table, &pptrs, &pptrs.bpas, NULL); if (config.bgp_daemon_src_local_pref_map) PM_find_id((struct id_table *)pptrs.blp_table, &pptrs, &pptrs.blp, NULL); if (config.bgp_daemon_src_med_map) PM_find_id((struct id_table *)pptrs.bmed_table, &pptrs, &pptrs.bmed, NULL); if (config.bmp_daemon) { BTA_find_id((struct id_table *)pptrs.bta_table, &pptrs, &pptrs.bta, &pptrs.bta2); bmp_srcdst_lookup(&pptrs); } set_index_pkt_ptrs(&pptrs); PM_evaluate_flow_type(&pptrs); exec_plugins(&pptrs, &req); } } } if (reload_map) { bta_map_caching = FALSE; sampling_map_caching = FALSE; load_networks(config.networks_file, &nt, &nc); if (config.bgp_daemon && config.bgp_daemon_peer_as_src_map) load_id_file(MAP_BGP_PEER_AS_SRC, config.bgp_daemon_peer_as_src_map, (struct id_table *)cb_data->bpas_table, &req, &bpas_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_local_pref_map) load_id_file(MAP_BGP_SRC_LOCAL_PREF, config.bgp_daemon_src_local_pref_map, (struct id_table *)cb_data->blp_table, &req, &blp_map_allocated); if (config.bgp_daemon && config.bgp_daemon_src_med_map) load_id_file(MAP_BGP_SRC_MED, config.bgp_daemon_src_med_map, (struct id_table *)cb_data->bmed_table, &req, &bmed_map_allocated); if (config.bgp_daemon) load_id_file(MAP_BGP_TO_XFLOW_AGENT, config.bgp_daemon_to_xflow_agent_map, (struct id_table *)cb_data->bta_table, &req, &bta_map_allocated); reload_map = FALSE; gettimeofday(&reload_map_tstamp, NULL); } if (reload_log) { reload_logs(PMACCTD_USAGE_HEADER); reload_log = FALSE; } if (cb_data->has_tun_prims && pptrs.tun_pptrs) { struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs.tun_pptrs; if (tpptrs->pkthdr) free(tpptrs->pkthdr); free(pptrs.tun_pptrs); } if (cb_data->sig.is_set) sigprocmask(SIG_UNBLOCK, &cb_data->sig.set, NULL); } int ip_handler(register struct packet_ptrs *pptrs) { register u_int8_t len = 0; register u_int16_t caplen = ((struct pcap_pkthdr *)pptrs->pkthdr)->caplen; register unsigned char *ptr; register u_int16_t off = pptrs->iph_ptr-pptrs->packet_ptr, off_l4; int ret = TRUE, num, is_fragment = 0; /* len: number of 32bit words forming the header */ len = IP_HL(((struct pm_iphdr *) pptrs->iph_ptr)); len <<= 2; ptr = pptrs->iph_ptr+len; off += len; /* check len */ if (off > caplen) return FALSE; /* IP packet truncated */ pptrs->l4_proto = ((struct pm_iphdr *)pptrs->iph_ptr)->ip_p; pptrs->payload_ptr = NULL; off_l4 = off; /* check fragments if needed */ if (config.handle_fragments) { if (pptrs->l4_proto == IPPROTO_TCP || pptrs->l4_proto == IPPROTO_UDP) { if (off+MyTLHdrSz > caplen) { if (!log_notification_isset(&log_notifications.snaplen_issue, ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec)) { Log(LOG_INFO, "INFO ( %s/core ): short IPv4 packet read (%u/%u/frags). Snaplen issue ?\n", config.name, caplen, off+MyTLHdrSz); log_notification_set(&log_notifications.max_classifiers, ((struct pcap_pkthdr *)pptrs->pkthdr)->ts.tv_sec, 180); return FALSE; } } pptrs->tlh_ptr = ptr; if (((struct pm_iphdr *)pptrs->iph_ptr)->ip_off & htons(IP_MF|IP_OFFMASK)) { is_fragment = TRUE; ret = ip_fragment_handler(pptrs); if (!ret) { if (!config.ext_sampling_rate) goto quit; else { pptrs->tlh_ptr = dummy_tlhdr; pptrs->tcp_flags = FALSE; if (off < caplen) pptrs->payload_ptr = ptr; ret = TRUE; goto quit; } } } /* Let's handle both fragments and packets. If we are facing any subsequent frag our pointer is in place; we handle unknown L4 protocols likewise. In case of "entire" TCP/UDP packets we have to jump the L4 header instead */ if (((struct pm_iphdr *)pptrs->iph_ptr)->ip_off & htons(IP_OFFMASK)); else if (pptrs->l4_proto == IPPROTO_UDP) { ptr += UDPHdrSz; off += UDPHdrSz; } else if (pptrs->l4_proto == IPPROTO_TCP) { ptr += ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_off << 2; off += ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_off << 2; } if (off < caplen) { pptrs->payload_ptr = ptr; if (pptrs->l4_proto == IPPROTO_UDP) { u_int16_t dst_port = ntohs(((struct pm_udphdr *)pptrs->tlh_ptr)->uh_dport); if (dst_port == UDP_PORT_VXLAN && (off + sizeof(struct vxlan_hdr) <= caplen)) { struct vxlan_hdr *vxhdr = (struct vxlan_hdr *) pptrs->payload_ptr; if (vxhdr->flags & VXLAN_FLAG_I) pptrs->vxlan_ptr = vxhdr->vni; pptrs->payload_ptr += sizeof(struct vxlan_hdr); if (pptrs->tun_pptrs) { struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; tpptrs->pkthdr->caplen = (pptrs->pkthdr->caplen - (pptrs->payload_ptr - pptrs->packet_ptr)); tpptrs->packet_ptr = pptrs->payload_ptr; eth_handler(tpptrs->pkthdr, tpptrs); if (tpptrs->iph_ptr) ((*tpptrs->l3_handler)(tpptrs)); } } } } } else { pptrs->tlh_ptr = dummy_tlhdr; if (off < caplen) pptrs->payload_ptr = ptr; } if (config.handle_flows) { pptrs->tcp_flags = FALSE; if (pptrs->l4_proto == IPPROTO_TCP) { if (off_l4+TCPFlagOff+1 > caplen) { Log(LOG_INFO, "INFO ( %s/core ): short IPv4 packet read (%u/%u/flows). Snaplen issue ?\n", config.name, caplen, off_l4+TCPFlagOff+1); return FALSE; } if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_SYN) pptrs->tcp_flags |= TH_SYN; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_FIN) pptrs->tcp_flags |= TH_FIN; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_RST) pptrs->tcp_flags |= TH_RST; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_ACK && pptrs->tcp_flags) pptrs->tcp_flags |= TH_ACK; } ip_flow_handler(pptrs); } /* XXX: optimize/short circuit here! */ pptrs->tcp_flags = FALSE; if (pptrs->l4_proto == IPPROTO_TCP && off_l4+TCPFlagOff+1 <= caplen) pptrs->tcp_flags = ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags; /* tunnel handlers here */ if (config.tunnel0 && !pptrs->tun_stack) { for (num = 0; pptrs->payload_ptr && !is_fragment && tunnel_registry[0][num].tf; num++) { if (tunnel_registry[0][num].proto == pptrs->l4_proto) { if (!tunnel_registry[0][num].port || (pptrs->tlh_ptr && tunnel_registry[0][num].port == ntohs(((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port))) { pptrs->tun_stack = num; ret = (*tunnel_registry[0][num].tf)(pptrs); } } } } else if (pptrs->tun_stack) { if (tunnel_registry[pptrs->tun_stack][pptrs->tun_layer].proto == pptrs->l4_proto) { if (!tunnel_registry[pptrs->tun_stack][pptrs->tun_layer].port || (pptrs->tlh_ptr && tunnel_registry[pptrs->tun_stack][pptrs->tun_layer].port == ntohs(((struct pm_tlhdr *)pptrs->tlh_ptr)->dst_port))) { ret = (*tunnel_registry[pptrs->tun_stack][pptrs->tun_layer].tf)(pptrs); } } } } pptrs->icmp_type = FALSE; pptrs->icmp_code = FALSE; if (pptrs->l4_proto == IPPROTO_ICMP) { pptrs->tlh_ptr = ptr; pptrs->icmp_type = ((struct pm_icmphdr *)pptrs->tlh_ptr)->type; pptrs->icmp_code = ((struct pm_icmphdr *)pptrs->tlh_ptr)->code; } quit: if (ret) { pptrs->flow_type.traffic_type = PM_FTYPE_IPV4; } return ret; } int ip6_handler(register struct packet_ptrs *pptrs) { struct ip6_frag *fhdr = NULL; register u_int16_t caplen = ((struct pcap_pkthdr *)pptrs->pkthdr)->caplen; u_int16_t plen = ntohs(((struct ip6_hdr *)pptrs->iph_ptr)->ip6_plen); u_int16_t off = pptrs->iph_ptr-pptrs->packet_ptr, off_l4; u_int32_t advance; u_int8_t nh; u_char *ptr = pptrs->iph_ptr; int ret = TRUE; /* length checks */ if (off+IP6HdrSz > caplen) return FALSE; /* IP packet truncated */ if (plen == 0 && ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_nxt == IPPROTO_HOPOPTS) { Log(LOG_INFO, "INFO ( %s/core ): NULL IPv6 payload length. Jumbo packets are currently not supported.\n", config.name); return FALSE; } pptrs->l4_proto = 0; pptrs->payload_ptr = NULL; nh = ((struct ip6_hdr *)pptrs->iph_ptr)->ip6_nxt; advance = IP6HdrSz; while ((off+advance <= caplen) && advance) { off += advance; ptr += advance; switch(nh) { case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_MOBILITY: nh = ((struct ip6_ext *)ptr)->ip6e_nxt; advance = (((struct ip6_ext *)ptr)->ip6e_len + 1) << 3; break; case IPPROTO_AH: nh = ((struct ip6_ext *)ptr)->ip6e_nxt; advance = sizeof(struct ah)+(((struct ah *)ptr)->ah_len << 2); /* hdr + sumlen */ break; case IPPROTO_FRAGMENT: fhdr = (struct ip6_frag *) ptr; nh = ((struct ip6_ext *)ptr)->ip6e_nxt; advance = sizeof(struct ip6_frag); break; /* XXX: case IPPROTO_ESP: */ /* XXX: case IPPROTO_IPCOMP: */ default: pptrs->tlh_ptr = ptr; pptrs->l4_proto = nh; goto end; } } end: off_l4 = off; if (config.handle_fragments) { if (pptrs->l4_proto == IPPROTO_TCP || pptrs->l4_proto == IPPROTO_UDP) { if (off+MyTLHdrSz > caplen) { Log(LOG_INFO, "INFO ( %s/core ): short IPv6 packet read (%u/%u/frags). Snaplen issue ?\n", config.name, caplen, off+MyTLHdrSz); return FALSE; } if (fhdr && (fhdr->ip6f_offlg & htons(IP6F_MORE_FRAG|IP6F_OFF_MASK))) { ret = ip6_fragment_handler(pptrs, fhdr); if (!ret) { if (!config.ext_sampling_rate) goto quit; else { pptrs->tlh_ptr = dummy_tlhdr; pptrs->tcp_flags = FALSE; if (off < caplen) pptrs->payload_ptr = ptr; ret = TRUE; goto quit; } } } /* Let's handle both fragments and packets. If we are facing any subsequent frag our pointer is in place; we handle unknown L4 protocols likewise. In case of "entire" TCP/UDP packets we have to jump the L4 header instead */ if (fhdr && (fhdr->ip6f_offlg & htons(IP6F_OFF_MASK))); else if (pptrs->l4_proto == IPPROTO_UDP) { ptr += UDPHdrSz; off += UDPHdrSz; } else if (pptrs->l4_proto == IPPROTO_TCP) { ptr += ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_off << 2; off += ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_off << 2; } if (off < caplen) { pptrs->payload_ptr = ptr; if (pptrs->l4_proto == IPPROTO_UDP) { u_int16_t dst_port = ntohs(((struct pm_udphdr *)pptrs->tlh_ptr)->uh_dport); if (dst_port == UDP_PORT_VXLAN && (off + sizeof(struct vxlan_hdr) <= caplen)) { struct vxlan_hdr *vxhdr = (struct vxlan_hdr *) pptrs->payload_ptr; if (vxhdr->flags & VXLAN_FLAG_I) pptrs->vxlan_ptr = vxhdr->vni; pptrs->payload_ptr += sizeof(struct vxlan_hdr); if (pptrs->tun_pptrs) { struct packet_ptrs *tpptrs = (struct packet_ptrs *) pptrs->tun_pptrs; tpptrs->pkthdr->caplen = (pptrs->pkthdr->caplen - (pptrs->payload_ptr - pptrs->packet_ptr)); tpptrs->packet_ptr = pptrs->payload_ptr; eth_handler(tpptrs->pkthdr, tpptrs); if (tpptrs->iph_ptr) ((*tpptrs->l3_handler)(tpptrs)); } } } } } else { pptrs->tlh_ptr = dummy_tlhdr; if (off < caplen) pptrs->payload_ptr = ptr; } if (config.handle_flows) { pptrs->tcp_flags = FALSE; if (pptrs->l4_proto == IPPROTO_TCP) { if (off_l4+TCPFlagOff+1 > caplen) { Log(LOG_INFO, "INFO ( %s/core ): short IPv6 packet read (%u/%u/flows). Snaplen issue ?\n", config.name, caplen, off_l4+TCPFlagOff+1); return FALSE; } if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_SYN) pptrs->tcp_flags |= TH_SYN; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_FIN) pptrs->tcp_flags |= TH_FIN; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_RST) pptrs->tcp_flags |= TH_RST; if (((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags & TH_ACK && pptrs->tcp_flags) pptrs->tcp_flags |= TH_ACK; } ip_flow6_handler(pptrs); } /* XXX: optimize/short circuit here! */ pptrs->tcp_flags = FALSE; if (pptrs->l4_proto == IPPROTO_TCP && off_l4+TCPFlagOff+1 <= caplen) pptrs->tcp_flags = ((struct pm_tcphdr *)pptrs->tlh_ptr)->th_flags; } pptrs->icmp_type = FALSE; pptrs->icmp_code = FALSE; if (pptrs->l4_proto == IPPROTO_ICMPV6) { pptrs->icmp_type = ((struct pm_icmphdr *)pptrs->tlh_ptr)->type; pptrs->icmp_code = ((struct pm_icmphdr *)pptrs->tlh_ptr)->code; } quit: if (ret) { pptrs->flow_type.traffic_type = PM_FTYPE_IPV6; } return ret; } int unknown_etype_handler(register struct packet_ptrs *pptrs) { /* NO-OP - just return TRUE so packet is counted */ return TRUE; } int PM_find_id(struct id_table *t, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2) { int x; pm_id_t ret = 0; if (!t) return 0; pretag_init_vars(pptrs, t); if (tag) *tag = 0; if (tag2) *tag2 = 0; if (pptrs) { pptrs->have_tag = FALSE; pptrs->have_tag2 = FALSE; } /* If we have any index defined, let's use it */ if (config.maps_index && pretag_index_have_one(t)) { struct id_entry *index_results[ID_TABLE_INDEX_RESULTS]; u_int32_t iterator; int num_results; num_results = pretag_index_lookup(t, pptrs, index_results, ID_TABLE_INDEX_RESULTS); for (iterator = 0; index_results[iterator] && iterator < num_results; iterator++) { ret = pretag_entry_process(index_results[iterator], pptrs, tag, tag2); if (!(ret & PRETAG_MAP_RCODE_JEQ)) return ret; } /* done */ return ret; } for (x = 0; x < t->ipv4_num; x++) { ret = pretag_entry_process(&t->e[x], pptrs, tag, tag2); if (!ret || ret > TRUE) { if (ret & PRETAG_MAP_RCODE_JEQ) { x = t->e[x].jeq.ptr->pos; x--; // yes, it will be automagically incremented by the for() cycle } else break; } } return ret; } void PM_print_stats(time_t now) { int device_idx; Log(LOG_NOTICE, "NOTICE ( %s/%s ): +++\n", config.name, config.type); if (config.pcap_if || config.pcap_interfaces_map) { for (device_idx = 0; device_idx < devices.num; device_idx++) { if (pcap_stats(devices.list[device_idx].dev_desc, &ps) < 0) { Log(LOG_INFO, "INFO ( %s/%s ): stats [%s,%u] time=%ld error='pcap_stats(): %s'\n", config.name, config.type, devices.list[device_idx].str, devices.list[device_idx].id, (long)now, pcap_geterr(devices.list[device_idx].dev_desc)); } Log(LOG_NOTICE, "NOTICE ( %s/%s ): stats [%s,%u] time=%ld received_packets=%u dropped_packets=%u\n", config.name, config.type, devices.list[device_idx].str, devices.list[device_idx].id, (long)now, ps.ps_recv, ps.ps_drop); } } Log(LOG_NOTICE, "NOTICE ( %s/%s ): ---\n", config.name, config.type); } void compute_once() { struct pkt_data dummy; CounterSz = sizeof(dummy.pkt_len); PdataSz = sizeof(struct pkt_data); PpayloadSz = sizeof(struct pkt_payload); PextrasSz = sizeof(struct pkt_extras); PbgpSz = sizeof(struct pkt_bgp_primitives); PlbgpSz = sizeof(struct pkt_legacy_bgp_primitives); PnatSz = sizeof(struct pkt_nat_primitives); PmplsSz = sizeof(struct pkt_mpls_primitives); PtunSz = sizeof(struct pkt_tunnel_primitives); PvhdrSz = sizeof(struct pkt_vlen_hdr_primitives); PmLabelTSz = sizeof(pm_label_t); PtLabelTSz = sizeof(pt_label_t); ChBufHdrSz = sizeof(struct ch_buf_hdr); CharPtrSz = sizeof(char *); IP4HdrSz = sizeof(struct pm_iphdr); MyTLHdrSz = sizeof(struct pm_tlhdr); TCPFlagOff = 13; MyTCPHdrSz = TCPFlagOff+1; PptrsSz = sizeof(struct packet_ptrs); UDPHdrSz = 8; IpFlowCmnSz = sizeof(struct ip_flow_common); HostAddrSz = sizeof(struct host_addr); IP6HdrSz = sizeof(struct ip6_hdr); IP6AddrSz = sizeof(struct in6_addr); } void tunnel_registry_init() { if (config.tunnel0) { char *tun_string = config.tunnel0, *tun_entry = NULL, *tun_type = NULL; int th_index = 0 /* tunnel handler index */, tr_index = 0 /* tunnel registry index */; while ((tun_entry = extract_token(&tun_string, ';'))) { tun_type = extract_token(&tun_entry, ','); for (th_index = 0; strcmp(tunnel_handlers_list[th_index].type, ""); th_index++) { if (!strcmp(tunnel_handlers_list[th_index].type, tun_type)) { if (tr_index < TUNNEL_REGISTRY_ENTRIES) { (*tunnel_handlers_list[th_index].tc)(&tunnel_registry[0][tr_index], tun_entry); tr_index++; } break; } } } } } int gtp_tunnel_configurator(struct tunnel_handler *th, char *opts) { th->proto = IPPROTO_UDP; th->port = atoi(opts); if (th->port) { th->tf = gtp_tunnel_func; } else { th->tf = NULL; Log(LOG_WARNING, "WARN ( %s/core ): GTP tunnel handler not loaded due to invalid options: '%s'\n", config.name, opts); } return 0; } int gtp_tunnel_func(register struct packet_ptrs *pptrs) { register u_int16_t caplen = ((struct pcap_pkthdr *)pptrs->pkthdr)->caplen; struct pm_gtphdr_v0 *gtp_hdr_v0 = (struct pm_gtphdr_v0 *) pptrs->payload_ptr; u_int16_t off = pptrs->payload_ptr-pptrs->packet_ptr; u_int16_t gtp_hdr_len, gtp_version; u_char *ptr = pptrs->payload_ptr; int ret, trial; gtp_version = (gtp_hdr_v0->flags >> 5) & 0x07; switch (gtp_version) { case 0: gtp_hdr_len = 4; break; case 1: gtp_hdr_len = 8; break; default: Log(LOG_INFO, "INFO ( %s/core ): unsupported GTP version %u\n", config.name, gtp_version); return FALSE; } if (off + gtp_hdr_len < caplen) { off += gtp_hdr_len; ptr += gtp_hdr_len; ret = 0; trial = 0; while (!ret && trial < MAX_GTP_TRIALS) { pptrs->iph_ptr = ptr; pptrs->tlh_ptr = NULL; pptrs->payload_ptr = NULL; pptrs->l4_proto = 0; pptrs->tcp_flags = 0; /* same trick used for MPLS BoS in ll.c: let's look at the first payload byte to guess which protocol we are speaking about */ switch (*pptrs->iph_ptr) { case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: pptrs->tun_layer++; ret = ip_handler(pptrs); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: pptrs->tun_layer++; ret = ip6_handler(pptrs); break; default: ret = FALSE; break; } /* next loop increment */ off++; ptr++; trial++; } } else { Log(LOG_INFO, "INFO ( %s/core ): short GTP packet read (%u/%u/tunnel). Snaplen issue ?\n", config.name, caplen, off + gtp_hdr_len); return FALSE; } return ret; } void reset_index_pkt_ptrs(struct packet_ptrs *pptrs) { pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_PACKET_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_MAC_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_VLAN_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_MPLS_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_L3_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_L4_PTR] = NULL; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_PAYLOAD_PTR] = NULL; pptrs->pkt_proto[CUSTOM_PRIMITIVE_L3_PTR] = FALSE; pptrs->pkt_proto[CUSTOM_PRIMITIVE_L4_PTR] = FALSE; } void set_index_pkt_ptrs(struct packet_ptrs *pptrs) { pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_PACKET_PTR] = pptrs->packet_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_MAC_PTR] = pptrs->mac_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_VLAN_PTR] = pptrs->vlan_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_MPLS_PTR] = pptrs->mpls_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_L3_PTR] = pptrs->iph_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_L4_PTR] = pptrs->tlh_ptr; pptrs->pkt_data_ptrs[CUSTOM_PRIMITIVE_PAYLOAD_PTR] = pptrs->payload_ptr; pptrs->pkt_proto[CUSTOM_PRIMITIVE_L3_PTR] = pptrs->l3_proto; pptrs->pkt_proto[CUSTOM_PRIMITIVE_L4_PTR] = pptrs->l4_proto; } void PM_evaluate_flow_type(struct packet_ptrs *pptrs) { if (pptrs->l3_proto == ETHERTYPE_IP) { pptrs->flow_type.traffic_type = PM_FTYPE_IPV4; } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { pptrs->flow_type.traffic_type = PM_FTYPE_IPV6; } } ssize_t recvfrom_savefile(struct pm_pcap_device *device, void **buf, struct sockaddr *src_addr, struct timeval **ts, int *round, struct packet_ptrs *savefile_pptrs) { ssize_t ret = 0; int pm_pcap_ret; read_packet: pm_pcap_ret = pcap_next_ex(device->dev_desc, &savefile_pptrs->pkthdr, (const u_char **)&savefile_pptrs->packet_ptr); if (pm_pcap_ret == 1 /* all good */) device->errors = FALSE; else if (pm_pcap_ret == -1 /* failed reading next packet */) { device->errors++; if (device->errors == PCAP_SAVEFILE_MAX_ERRORS) { Log(LOG_ERR, "ERROR ( %s/core ): pcap_ext_ex() max errors reached (%u). Exiting.\n", config.name, PCAP_SAVEFILE_MAX_ERRORS); exit_gracefully(1); } else { Log(LOG_WARNING, "WARN ( %s/core ): pcap_ext_ex() failed: %s. Skipping packet.\n", config.name, pcap_geterr(device->dev_desc)); return 0; } } else if (pm_pcap_ret == -2 /* last packet in a pcap_savefile */) { pcap_close(device->dev_desc); if (config.pcap_sf_replay < 0 || (config.pcap_sf_replay > 0 && (*round) < config.pcap_sf_replay)) { (*round)++; open_pcap_savefile(device, config.pcap_savefile); if (config.pcap_sf_delay) sleep(config.pcap_sf_delay); goto read_packet; } if (config.pcap_sf_wait) { fill_pipe_buffer(); Log(LOG_INFO, "INFO ( %s/core ): finished reading PCAP capture file\n", config.name); wait(NULL); } stop_all_childs(); } else { Log(LOG_ERR, "ERROR ( %s/core ): unexpected return code from pcap_next_ex(). Exiting.\n", config.name); exit_gracefully(1); } (*device->data->handler)(savefile_pptrs->pkthdr, savefile_pptrs); if (savefile_pptrs->iph_ptr) { (*savefile_pptrs->l3_handler)(savefile_pptrs); if (savefile_pptrs->payload_ptr) { if (ts) (*ts) = &savefile_pptrs->pkthdr->ts; (*buf) = savefile_pptrs->payload_ptr; ret = savefile_pptrs->pkthdr->caplen - (savefile_pptrs->payload_ptr - savefile_pptrs->packet_ptr); if (savefile_pptrs->l4_proto == IPPROTO_UDP || savefile_pptrs->l4_proto == IPPROTO_TCP) { if (savefile_pptrs->l3_proto == ETHERTYPE_IP) { raw_to_sa((struct sockaddr *)src_addr, (u_char *) &((struct pm_iphdr *)savefile_pptrs->iph_ptr)->ip_src.s_addr, (u_int16_t) ((struct pm_udphdr *)savefile_pptrs->tlh_ptr)->uh_sport, AF_INET); } else if (savefile_pptrs->l3_proto == ETHERTYPE_IPV6) { raw_to_sa((struct sockaddr *)src_addr, (u_char *) &((struct ip6_hdr *)savefile_pptrs->iph_ptr)->ip6_src, (u_int16_t) ((struct pm_udphdr *)savefile_pptrs->tlh_ptr)->uh_sport, AF_INET6); } } } } return ret; } ssize_t recvfrom_rawip(unsigned char *buf, size_t len, struct sockaddr *src_addr, struct packet_ptrs *local_pptrs) { ssize_t ret = 0; local_pptrs->packet_ptr = buf; local_pptrs->pkthdr->caplen = len; raw_handler(local_pptrs->pkthdr, local_pptrs); if (local_pptrs->iph_ptr) { (*local_pptrs->l3_handler)(local_pptrs); if (local_pptrs->payload_ptr) { ret = local_pptrs->pkthdr->caplen - (local_pptrs->payload_ptr - local_pptrs->packet_ptr); if (local_pptrs->l4_proto == IPPROTO_UDP) { if (local_pptrs->l3_proto == ETHERTYPE_IP) { raw_to_sa((struct sockaddr *)src_addr, (u_char *) &((struct pm_iphdr *)local_pptrs->iph_ptr)->ip_src.s_addr, (u_int16_t) ((struct pm_udphdr *)local_pptrs->tlh_ptr)->uh_sport, AF_INET); } else if (local_pptrs->l3_proto == ETHERTYPE_IPV6) { raw_to_sa((struct sockaddr *)src_addr, (u_char *) &((struct ip6_hdr *)local_pptrs->iph_ptr)->ip6_src, (u_int16_t) ((struct pm_udphdr *)local_pptrs->tlh_ptr)->uh_sport, AF_INET6); } } /* last action: cut L3 and L4 off the packet */ memmove(buf, local_pptrs->payload_ptr, ret); } } return ret; } void pm_pcap_add_filter(struct pm_pcap_device *dev_ptr) { /* pcap library stuff */ struct bpf_program filter; memset(&filter, 0, sizeof(filter)); if (pcap_compile(dev_ptr->dev_desc, &filter, config.clbuf, 0, PCAP_NETMASK_UNKNOWN) < 0) { Log(LOG_WARNING, "WARN ( %s/core ): %s (going on without a filter)\n", config.name, pcap_geterr(dev_ptr->dev_desc)); } else { if (pcap_setfilter(dev_ptr->dev_desc, &filter) < 0) { Log(LOG_WARNING, "WARN ( %s/core ): %s (going on without a filter)\n", config.name, pcap_geterr(dev_ptr->dev_desc)); } else pcap_freecode(&filter); } } pmacct-1.7.8/src/pmacct-version.h.in0000644000175000017500000000171614354105275016316 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PMACCT_VERSION_H_ #define _PMACCT_VERSION_H_ #define PMACCT_VERSION "@PMACCT_VERSION@" #endif /* _PMACCT_VERSION_H_ */ pmacct-1.7.8/src/sflow.c0000644000175000017500000011521014354105275014077 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* sflow v2/v4/v5 routines are based on sFlow toolkit 3.8 and later which is Copyright (C) InMon Corporation 2001 ALL RIGHTS RESERVED */ /* includes */ #include "pmacct.h" #include "sflow.h" #include "bgp/bgp.h" #include "sfacctd.h" #include "sfv5_module.h" #include "ip_flow.h" #include "ip_frag.h" #include "pmacct-data.h" #include "crc32.h" /*_________________---------------------------__________________ _________________ lengthCheck __________________ -----------------___________________________------------------ */ int lengthCheck(SFSample *sample, u_char *start, u_int32_t len) { u_int32_t actualLen = (u_char *)sample->datap - start; if (actualLen != len) { /* XXX: notify length mismatch */ return ERR; } return FALSE; } /*_________________---------------------------__________________ _________________ decodeLinkLayer __________________ -----------------___________________________------------------ store the offset to the start of the ipv4 header in the sequence_number field or -1 if not found. Decode the 802.1d if it's there. */ #define NFT_ETHHDR_SIZ 14 #define NFT_8022_SIZ 3 #define NFT_MAX_8023_LEN 1500 void decodeLinkLayer(SFSample *sample) { u_char *start = (u_char *)sample->header; u_char *end = start + sample->headerLen; u_char *ptr = start; u_int16_t caplen = end - (u_char *)sample->datap; /* assume not found */ sample->gotIPV4 = FALSE; sample->gotIPV6 = FALSE; if (caplen < NFT_ETHHDR_SIZ) return; /* not enough for an Ethernet header */ caplen -= NFT_ETHHDR_SIZ; memcpy(sample->eth_dst, ptr, 6); ptr += 6; memcpy(sample->eth_src, ptr, 6); ptr += 6; sample->eth_type = (ptr[0] << 8) + ptr[1]; ptr += 2; if (sample->eth_type == ETHERTYPE_8021Q || sample->eth_type == ETHERTYPE_8021AD) { /* VLAN - next two bytes */ u_int32_t vlanData = (ptr[0] << 8) + ptr[1]; u_int32_t vlan = vlanData & 0x0fff; u_int32_t priority = vlanData >> 13; if (caplen < 2) return; ptr += 2; /* _____________________________________ */ /* | pri | c | vlan-id | */ /* ------------------------------------- */ /* [priority = 3bits] [Canonical Format Flag = 1bit] [vlan-id = 12 bits] */ if (!sample->in_vlan && !sample->out_vlan) sample->in_vlan = vlan; if (!sample->in_priority && !sample->out_priority) sample->in_priority = priority; sample->eth_type = (ptr[0] << 8) + ptr[1]; ptr += 2; caplen -= 2; /* QinQ / 802.1AD */ if (sample->eth_type == ETHERTYPE_8021Q) { u_int32_t cvlanData, cvlan, cpriority; if (caplen < 4) { return; } cvlanData = (ptr[0] << 8) + ptr[1]; cvlan = cvlanData & 0x0fff; cpriority = cvlanData >> 13; sample->cvlan = cvlan; sample->cvlan_priority = cpriority; ptr += 2; sample->eth_type = (ptr[0] << 8) + ptr[1]; ptr += 2; caplen -= 4; } } if (sample->eth_type <= NFT_MAX_8023_LEN) { /* assume 802.3+802.2 header */ if (caplen < 8) return; /* check for SNAP */ if(ptr[0] == 0xAA && ptr[1] == 0xAA && ptr[2] == 0x03) { ptr += 3; if(ptr[0] != 0 || ptr[1] != 0 || ptr[2] != 0) { return; /* no further decode for vendor-specific protocol */ } ptr += 3; /* OUI == 00-00-00 means the next two bytes are the ethernet type (RFC 2895) */ sample->eth_type = (ptr[0] << 8) + ptr[1]; ptr += 2; caplen -= 8; } else { if (ptr[0] == 0x06 && ptr[1] == 0x06 && (ptr[2] & 0x01)) { /* IP over 8022 */ ptr += 3; /* force the eth_type to be IP so we can inline the IP decode below */ sample->eth_type = ETHERTYPE_IP; caplen -= 3; } else return; } } if (sample->eth_type == ETHERTYPE_MPLS || sample->eth_type == ETHERTYPE_MPLS_MULTI) { decodeMpls(sample, &ptr); caplen -= sample->lstk.depth * 4; } if (sample->eth_type == ETHERTYPE_IP) { sample->gotIPV4 = TRUE; sample->offsetToIPV4 = (ptr - start); } if (sample->eth_type == ETHERTYPE_IPV6) { sample->gotIPV6 = TRUE; sample->offsetToIPV6 = (ptr - start); } } /*_________________---------------------------__________________ _________________ decodeIPLayer4 __________________ -----------------___________________________------------------ */ void decodeIPLayer4(SFSample *sample, u_char *ptr, u_int32_t ipProtocol) { u_char *end = sample->header + sample->headerLen; if(ptr > (end - 8)) return; // not enough header bytes left switch(ipProtocol) { case 1: /* ICMP */ { struct SF_icmphdr icmp; memcpy(&icmp, ptr, sizeof(icmp)); sample->dcd_sport = icmp.type; sample->dcd_dport = icmp.code; } break; case 6: /* TCP */ { struct SF_tcphdr tcp; memcpy(&tcp, ptr, sizeof(tcp)); sample->dcd_sport = ntohs(tcp.th_sport); sample->dcd_dport = ntohs(tcp.th_dport); sample->dcd_tcpFlags = tcp.th_flags; if(sample->dcd_dport == 80) { int headerBytes = (tcp.th_off_and_unused >> 4) * 4; ptr += headerBytes; } } break; case 17: /* UDP */ { struct SF_udphdr udp; memcpy(&udp, ptr, sizeof(udp)); sample->dcd_sport = ntohs(udp.uh_sport); sample->dcd_dport = ntohs(udp.uh_dport); sample->udp_pduLen = ntohs(udp.uh_ulen); if (sample->dcd_dport == UDP_PORT_VXLAN) { ptr += sizeof(udp); decodeVXLAN(sample, ptr); } } break; default: /* some other protcol */ break; } } void decodeVXLAN(SFSample *sample, u_char *ptr) { struct vxlan_hdr *hdr = NULL; u_char *vni_ptr = NULL; u_int32_t vni; u_char *end = sample->header + sample->headerLen; if (ptr > (end - 8)) return; hdr = (struct vxlan_hdr *) ptr; if (hdr->flags & VXLAN_FLAG_I) { vni_ptr = hdr->vni; /* decode 24-bit label */ vni = *vni_ptr++; vni <<= 8; vni += *vni_ptr++; vni <<= 8; vni += *vni_ptr++; sample->vni = vni; ptr += sizeof(struct vxlan_hdr); if (sample->sppi) { SFSample *sppi = (SFSample *) sample->sppi; /* preps */ sppi->datap = (u_int32_t *) ptr; sppi->header = ptr; sppi->headerLen = (end - ptr); /* decoding inner packet */ decodeLinkLayer(sppi); if (sppi->gotIPV4) decodeIPV4(sppi); else if (sppi->gotIPV6) decodeIPV6(sppi); } } } /*_________________---------------------------__________________ _________________ decodeIPV4 __________________ -----------------___________________________------------------ */ void decodeIPV4(SFSample *sample) { if (sample->gotIPV4) { u_char *end = sample->header + sample->headerLen; u_char *ptr = sample->header + sample->offsetToIPV4; u_int16_t caplen = end - ptr; /* Create a local copy of the IP header (cannot overlay structure in case it is not quad-aligned...some platforms would core-dump if we tried that). It's OK coz this probably performs just as well anyway. */ struct SF_iphdr ip; if (caplen < IP4HdrSz) return; memcpy(&ip, ptr, sizeof(ip)); /* Value copy all ip elements into sample */ sample->dcd_srcIP.s_addr = ip.saddr; sample->dcd_dstIP.s_addr = ip.daddr; sample->dcd_ipProtocol = ip.protocol; sample->dcd_ipTos = ip.tos; sample->dcd_ipTTL = ip.ttl; /* check for fragments */ sample->ip_fragmentOffset = ntohs(ip.frag_off) & 0x1FFF; if (sample->ip_fragmentOffset == 0) { /* advance the pointer to the next protocol layer */ /* ip headerLen is expressed as a number of quads */ ptr += (ip.version_and_headerLen & 0x0f) * 4; if (ip.protocol == 4 /* ipencap */ || ip.protocol == 94 /* ipip */) { if (sample->sppi) { SFSample *sppi = (SFSample *) sample->sppi; /* preps */ sppi->datap = (u_int32_t *) ptr; sppi->header = ptr; sppi->headerLen = (end - ptr); sppi->offsetToIPV4 = 0; sppi->gotIPV4 = TRUE; decodeIPV4(sppi); } } else decodeIPLayer4(sample, ptr, ip.protocol); } } } /*_________________---------------------------__________________ _________________ decodeIPV6 __________________ -----------------___________________________------------------ */ void decodeIPV6(SFSample *sample) { u_int32_t label; u_int32_t nextHeader; u_char *end = sample->header + sample->headerLen; if(sample->gotIPV6) { u_char *ptr = sample->header + sample->offsetToIPV6; u_int16_t caplen = end - ptr; if (caplen < IP6HdrSz) return; // check the version { int ipVersion = (*ptr >> 4); if(ipVersion != 6) return; } // get the tos (priority) sample->dcd_ipTos = *ptr++ & 15; // 24-bit label label = *ptr++; label <<= 8; label += *ptr++; label <<= 8; label += *ptr++; // payload ptr += 2; // if payload is zero, that implies a jumbo payload // next header nextHeader = *ptr++; // TTL sample->dcd_ipTTL = *ptr++; {// src and dst address sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; memcpy(&sample->ipsrc.address, ptr, 16); ptr +=16; sample->ipdst.type = SFLADDRESSTYPE_IP_V6; memcpy(&sample->ipdst.address, ptr, 16); ptr +=16; } // skip over some common header extensions... // http://searchnetworking.techtarget.com/originalContent/0,289142,sid7_gci870277,00.html while(nextHeader == 0 || // hop nextHeader == 43 || // routing nextHeader == 44 || // fragment // nextHeader == 50 || // encryption - don't bother coz we'll not be able to read any further nextHeader == 51 || // auth nextHeader == 60) { // destination options u_int32_t optionLen, skip; nextHeader = ptr[0]; optionLen = 8 * (ptr[1] + 1); // second byte gives option len in 8-byte chunks, not counting first 8 skip = optionLen - 2; ptr += skip; if(ptr > end) return; // ran off the end of the header } // now that we have eliminated the extension headers, nextHeader should have what we want to // remember as the ip protocol... sample->dcd_ipProtocol = nextHeader; if (sample->dcd_ipProtocol == 4 /* ipencap */ || sample->dcd_ipProtocol == 94 /* ipip */) { if (sample->sppi) { SFSample *sppi = (SFSample *) sample->sppi; /* preps */ sppi->datap = (u_int32_t *) ptr; sppi->header = ptr; sppi->headerLen = (end - ptr); sppi->offsetToIPV4 = 0; sppi->gotIPV4 = TRUE; decodeIPV4(sppi); } } else decodeIPLayer4(sample, ptr, sample->dcd_ipProtocol); } } /*_________________---------------------------__________________ _________________ read data fns __________________ -----------------___________________________------------------ */ char *getPointer(SFSample *sample) { if ((u_char *)sample->datap > sample->endp) return NULL; return (char *)sample->datap; } u_int32_t getData32(SFSample *sample) { if ((u_char *)sample->datap > sample->endp) return 0; return ntohl(*(sample->datap)++); } u_int32_t getData32_nobswap(SFSample *sample) { if ((u_char *)sample->datap > sample->endp) return 0; return *(sample->datap)++; } u_int64_t getData64(SFSample *sample) { u_int64_t tmpLo, tmpHi; tmpHi = getData32(sample); tmpLo = getData32(sample); return (tmpHi << 32) + tmpLo; } void skipBytes(SFSample *sample, int skip) { int quads = (skip + 3) / 4; sample->datap += quads; // if((u_char *)sample->datap > sample->endp) return 0; } int skipBytesAndCheck(SFSample *sample, int skip) { int quads = (skip + 3) / 4; if ((u_char *)(sample->datap + quads) <= sample->endp) { sample->datap += quads; return quads; } else return ERR; } u_int32_t getString(SFSample *sample, char *buf, u_int32_t bufLen) { u_int32_t len, read_len; len = getData32(sample); // truncate if too long read_len = (len >= bufLen) ? (bufLen - 1) : len; memcpy(buf, sample->datap, read_len); buf[read_len] = '\0'; // null terminate skipBytes(sample, len); return len; } u_int32_t getAddress(SFSample *sample, SFLAddress *address) { address->type = getData32(sample); if(address->type == SFLADDRESSTYPE_IP_V4) address->address.ip_v4.s_addr = getData32_nobswap(sample); else { memcpy(address->address.ip_v6.s6_addr, sample->datap, 16); skipBytes(sample, 16); } return address->type; } char *printTag(u_int32_t tag, char *buf, int bufLen) { // should really be: snprintf(buf, buflen,...) but snprintf() is not always available sprintf(buf, "%lu:%lu", (unsigned long)(tag >> 12), (unsigned long)(tag & 0x00000FFF)); return buf; } /*_________________---------------------------__________________ _________________ readExtendedSwitch __________________ -----------------___________________________------------------ */ void readExtendedSwitch(SFSample *sample) { sample->in_vlan = getData32(sample); sample->in_priority = getData32(sample); sample->out_vlan = getData32(sample); sample->out_priority = getData32(sample); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_SWITCH; } /*_________________---------------------------__________________ _________________ readExtendedRouter __________________ -----------------___________________________------------------ */ void readExtendedRouter(SFSample *sample) { getAddress(sample, &sample->nextHop); sample->srcMask = getData32(sample); sample->dstMask = getData32(sample); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_ROUTER; } /*_________________---------------------------__________________ _________________ readExtendedGateway_v2 __________________ -----------------___________________________------------------ */ void readExtendedGateway_v2(SFSample *sample) { sample->my_as = getData32(sample); sample->src_as = getData32(sample); sample->src_peer_as = getData32(sample); sample->dst_as_path_len = getData32(sample); /* just point at the dst_as_path array */ if(sample->dst_as_path_len > 0) { // sample->dst_as_path = sample->datap; /* and skip over it in the input */ skipBytes(sample, sample->dst_as_path_len * 4); // fill in the dst and dst_peer fields too sample->dst_peer_as = ntohl(sample->dst_as_path[0]); sample->dst_as = ntohl(sample->dst_as_path[sample->dst_as_path_len - 1]); } sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; } /*_________________---------------------------__________________ _________________ readExtendedGateway __________________ -----------------___________________________------------------ */ void readExtendedGateway(SFSample *sample) { u_int32_t len_tot, len_asn, len_comm, idx; char asn_str[MAX_BGP_ASPATH], comm_str[MAX_BGP_STD_COMMS], space[] = " "; if(sample->datagramVersion >= 5) getAddress(sample, &sample->bgp_nextHop); sample->my_as = getData32(sample); sample->src_as = getData32(sample); sample->src_peer_as = getData32(sample); sample->dst_as_path_len = getData32(sample); if (sample->dst_as_path_len > 0) { for (idx = 0, len_tot = 0; idx < sample->dst_as_path_len; idx++) { u_int32_t seg_len, i; getData32(sample); /* seg_type */ seg_len = getData32(sample); for (i = 0; i < seg_len; i++) { u_int32_t asNumber; asNumber = getData32(sample); snprintf(asn_str, MAX_BGP_ASPATH-1, "%u", asNumber); len_asn = strlen(asn_str); len_tot = strlen(sample->dst_as_path); if ((len_tot+len_asn) < LARGEBUFLEN) { strncat(sample->dst_as_path, asn_str, (sizeof(sample->dst_as_path) - len_tot)); } else { sample->dst_as_path[LARGEBUFLEN-2] = '+'; sample->dst_as_path[LARGEBUFLEN-1] = '\0'; } /* mark the first one as the dst_peer_as */ if(i == 0 && idx == 0) sample->dst_peer_as = asNumber; /* mark the last one as the dst_as */ if (idx == (sample->dst_as_path_len - 1) && i == (seg_len - 1)) sample->dst_as = asNumber; else { if (strlen(sample->dst_as_path) < (LARGEBUFLEN-1)) strncat(sample->dst_as_path, space, 1); } } } } else sample->dst_as_path[0] = '\0'; sample->communities_len = getData32(sample); /* just point at the communities array */ if (sample->communities_len > 0) { for (idx = 0, len_tot = 0; idx < sample->communities_len; idx++) { u_int32_t comm, as, val; comm = getData32(sample); switch (comm) { case COMMUNITY_INTERNET: strcpy(comm_str, "internet"); break; case COMMUNITY_NO_EXPORT: strcpy(comm_str, "no-export"); break; case COMMUNITY_NO_ADVERTISE: strcpy (comm_str, "no-advertise"); break; case COMMUNITY_LOCAL_AS: strcpy (comm_str, "local-AS"); break; default: as = (comm >> 16) & 0xFFFF; val = comm & 0xFFFF; sprintf(comm_str, "%d:%d", as, val); break; } len_comm = strlen(comm_str); len_tot = strlen(sample->comms); if ((len_tot+len_comm) < LARGEBUFLEN) { strncat(sample->comms, comm_str, (sizeof(sample->comms) - len_tot)); } else { sample->comms[LARGEBUFLEN-2] = '+'; sample->comms[LARGEBUFLEN-1] = '\0'; } if (idx < (sample->communities_len - 1)) { if (strlen(sample->comms) < (LARGEBUFLEN-1)) strncat(sample->comms, space, 1); } } } else sample->comms[0] = '\0'; sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; sample->localpref = getData32(sample); } /*_________________---------------------------__________________ _________________ readExtendedUser __________________ -----------------___________________________------------------ */ void readExtendedUser(SFSample *sample) { if(sample->datagramVersion >= 5) sample->src_user_charset = getData32(sample); sample->src_user_len = getString(sample, sample->src_user, SA_MAX_EXTENDED_USER_LEN); if(sample->datagramVersion >= 5) sample->dst_user_charset = getData32(sample); sample->dst_user_len = getString(sample, sample->dst_user, SA_MAX_EXTENDED_USER_LEN); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_USER; } /*_________________---------------------------__________________ _________________ readExtendedUrl __________________ -----------------___________________________------------------ */ void readExtendedUrl(SFSample *sample) { sample->url_direction = getData32(sample); sample->url_len = getString(sample, sample->url, SA_MAX_EXTENDED_URL_LEN); if(sample->datagramVersion >= 5) sample->host_len = getString(sample, sample->host, SA_MAX_EXTENDED_HOST_LEN); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_URL; } /*_________________---------------------------__________________ _________________ mplsLabelStack __________________ -----------------___________________________------------------ */ void mplsLabelStack(SFSample *sample, u_int8_t direction) { if (direction == DIRECTION_IN) { sample->lstk.depth = getData32(sample); /* just point at the lablelstack array */ if (sample->lstk.depth > 0) sample->lstk.stack = (u_int32_t *)sample->datap; /* and skip over it in the input */ skipBytes(sample, sample->lstk.depth * 4); } else if (direction == DIRECTION_OUT) { sample->lstk_out.depth = getData32(sample); if (sample->lstk_out.depth > 0) sample->lstk_out.stack = (u_int32_t *)sample->datap; skipBytes(sample, sample->lstk_out.depth * 4); } } /*_________________---------------------------__________________ _________________ readExtendedMpls __________________ -----------------___________________________------------------ */ void readExtendedMpls(SFSample *sample) { getAddress(sample, &sample->mpls_nextHop); mplsLabelStack(sample, DIRECTION_IN); mplsLabelStack(sample, DIRECTION_OUT); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS; } /*_________________---------------------------__________________ _________________ readExtendedNat __________________ -----------------___________________________------------------ */ void readExtendedNat(SFSample *sample) { getAddress(sample, &sample->nat_src); getAddress(sample, &sample->nat_dst); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_NAT; } /*_________________---------------------------__________________ _________________ readExtendedMplsTunnel __________________ -----------------___________________________------------------ */ void readExtendedMplsTunnel(SFSample *sample) { #define SA_MAX_TUNNELNAME_LEN 100 char tunnel_name[SA_MAX_TUNNELNAME_LEN+1]; getString(sample, tunnel_name, SA_MAX_TUNNELNAME_LEN); sample->mpls_tunnel_id = getData32(sample); getData32(sample); /* tunnel_cos */ sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL; } /*_________________---------------------------__________________ _________________ readExtendedMplsVC __________________ -----------------___________________________------------------ */ void readExtendedMplsVC(SFSample *sample) { #define SA_MAX_VCNAME_LEN 100 char vc_name[SA_MAX_VCNAME_LEN+1]; getString(sample, vc_name, SA_MAX_VCNAME_LEN); sample->mpls_vll_vc_id = getData32(sample); getData32(sample); /* vc_cos */ sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_VC; } /*_________________---------------------------__________________ _________________ readExtendedMplsFTN __________________ -----------------___________________________------------------ */ void readExtendedMplsFTN(SFSample *sample) { #define SA_MAX_FTN_LEN 100 char ftn_descr[SA_MAX_FTN_LEN+1]; getString(sample, ftn_descr, SA_MAX_FTN_LEN); getData32(sample); /* ftn_mask */ sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_FTN; } /*_________________---------------------------__________________ _________________ readExtendedMplsLDP_FEC __________________ -----------------___________________________------------------ */ void readExtendedMplsLDP_FEC(SFSample *sample) { getData32(sample); /* fec_addr_prefix_len */ sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC; } /*_________________---------------------------__________________ _________________ readExtendedVlanTunnel __________________ -----------------___________________________------------------ */ void readExtendedVlanTunnel(SFSample *sample) { SFLLabelStack lstk; lstk.depth = getData32(sample); /* just point at the lablelstack array */ if(lstk.depth > 0) lstk.stack = (u_int32_t *)sample->datap; /* and skip over it in the input */ skipBytes(sample, lstk.depth * 4); sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL; } /*_________________---------------------------__________________ _________________ readExtendedProcess __________________ -----------------___________________________------------------ */ void readExtendedProcess(SFSample *sample) { u_int32_t num_processes, i; num_processes = getData32(sample); for (i = 0; i < num_processes; i++) skipBytes(sample, 4); } void readExtendedClass2(SFSample *sample) { if (config.classifier_ndpi) { #if defined (WITH_NDPI) sample->ndpi_class.master_protocol = getData32(sample); sample->ndpi_class.app_protocol = getData32(sample); #endif } else skipBytes(sample, 8); } void readExtendedTag(SFSample *sample) { sample->tag = getData64(sample); sample->tag2 = getData64(sample); } void decodeMpls(SFSample *sample, u_char **bp) { struct packet_ptrs dummy_pptrs; u_char *ptr, *end = sample->header + sample->headerLen; u_int16_t nl = 0, caplen; if (bp) ptr = (*bp); else ptr = (u_char *)sample->datap; caplen = end - ptr; memset(&dummy_pptrs, 0, sizeof(dummy_pptrs)); sample->eth_type = mpls_handler(ptr, &caplen, &nl, &dummy_pptrs); if (sample->eth_type == ETHERTYPE_IP) { sample->gotIPV4 = TRUE; sample->offsetToIPV4 = nl+(ptr-sample->header); } else if (sample->eth_type == ETHERTYPE_IPV6) { sample->gotIPV6 = TRUE; sample->offsetToIPV6 = nl+(ptr-sample->header); } if (nl) { sample->lstk.depth = nl / 4; sample->lstk.stack = (u_int32_t *) dummy_pptrs.mpls_ptr; if (bp) (*bp) += nl; } } void decodePPP(SFSample *sample) { struct packet_ptrs dummy_pptrs; struct pcap_pkthdr h; u_char *ptr = (u_char *)sample->datap, *end = sample->header + sample->headerLen; u_int16_t nl = 0; memset(&dummy_pptrs, 0, sizeof(dummy_pptrs)); h.caplen = end - ptr; dummy_pptrs.packet_ptr = ptr; ppp_handler(&h, &dummy_pptrs); sample->eth_type = dummy_pptrs.l3_proto; if (dummy_pptrs.mpls_ptr) { if (dummy_pptrs.iph_ptr) nl = dummy_pptrs.iph_ptr - dummy_pptrs.mpls_ptr; if (nl) { sample->lstk.depth = nl / 4; sample->lstk.stack = (u_int32_t *) dummy_pptrs.mpls_ptr; } } if (sample->eth_type == ETHERTYPE_IP) { sample->gotIPV4 = TRUE; sample->offsetToIPV4 = dummy_pptrs.iph_ptr - sample->header; } else if (sample->eth_type == ETHERTYPE_IPV6) { sample->gotIPV6 = TRUE; sample->offsetToIPV6 = dummy_pptrs.iph_ptr - sample->header; } } /*_________________---------------------------__________________ _________________ readFlowSample_header __________________ -----------------___________________________------------------ */ void readFlowSample_header(SFSample *sample) { sample->headerProtocol = getData32(sample); sample->sampledPacketSize = getData32(sample); if(sample->datagramVersion > 4) sample->stripped = getData32(sample); sample->headerLen = getData32(sample); sample->header = (u_char *)sample->datap; /* just point at the header */ switch(sample->headerProtocol) { /* the header protocol tells us where to jump into the decode */ case SFLHEADER_ETHERNET_ISO8023: decodeLinkLayer(sample); break; case SFLHEADER_IPv4: sample->gotIPV4 = TRUE; sample->offsetToIPV4 = 0; break; case SFLHEADER_IPv6: sample->gotIPV6 = TRUE; sample->offsetToIPV6 = 0; break; case SFLHEADER_MPLS: decodeMpls(sample, NULL); break; case SFLHEADER_PPP: decodePPP(sample); break; case SFLHEADER_ISO88024_TOKENBUS: case SFLHEADER_ISO88025_TOKENRING: case SFLHEADER_FDDI: case SFLHEADER_FRAME_RELAY: case SFLHEADER_X25: case SFLHEADER_SMDS: case SFLHEADER_AAL5: case SFLHEADER_AAL5_IP: default: /* XXX: nofity error */ break; } if (sample->gotIPV4) decodeIPV4(sample); else if (sample->gotIPV6) decodeIPV6(sample); skipBytes(sample, sample->headerLen); } /*_________________---------------------------__________________ _________________ readFlowSample_ethernet __________________ -----------------___________________________------------------ */ void readFlowSample_ethernet(SFSample *sample) { sample->eth_len = getData32(sample); memcpy(sample->eth_src, sample->datap, 6); skipBytes(sample, 6); memcpy(sample->eth_dst, sample->datap, 6); skipBytes(sample, 6); sample->eth_type = getData32(sample); if (sample->eth_type == ETHERTYPE_IP) sample->gotIPV4 = TRUE; else if (sample->eth_type == ETHERTYPE_IPV6) sample->gotIPV6 = TRUE; /* Commit eth_len to packet length: will be overwritten if we get SFLFLOW_IPV4 or SFLFLOW_IPV6; otherwise will get along as the best information we have */ if (!sample->sampledPacketSize) sample->sampledPacketSize = sample->eth_len; } /*_________________---------------------------__________________ _________________ readFlowSample_IPv4 __________________ -----------------___________________________------------------ */ void readFlowSample_IPv4(SFSample *sample) { sample->headerLen = sizeof(SFLSampled_ipv4); sample->header = (u_char *)sample->datap; /* just point at the header */ skipBytes(sample, sample->headerLen); { SFLSampled_ipv4 nfKey; memcpy(&nfKey, sample->header, sizeof(nfKey)); sample->sampledPacketSize = ntohl(nfKey.length); sample->dcd_srcIP = nfKey.src_ip; sample->dcd_dstIP = nfKey.dst_ip; sample->dcd_ipProtocol = ntohl(nfKey.protocol); sample->dcd_ipTos = ntohl(nfKey.tos); sample->dcd_sport = ntohl(nfKey.src_port); sample->dcd_dport = ntohl(nfKey.dst_port); } sample->gotIPV4 = TRUE; } /*_________________---------------------------__________________ _________________ readFlowSample_IPv6 __________________ -----------------___________________________------------------ */ void readFlowSample_IPv6(SFSample *sample) { sample->header = (u_char *)sample->datap; /* just point at the header */ sample->headerLen = sizeof(SFLSampled_ipv6); skipBytes(sample, sample->headerLen); { SFLSampled_ipv6 nfKey6; memcpy(&nfKey6, sample->header, sizeof(nfKey6)); sample->sampledPacketSize = ntohl(nfKey6.length); sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; memcpy(&sample->ipsrc.address, &nfKey6.src_ip, IP6AddrSz); sample->ipdst.type = SFLADDRESSTYPE_IP_V6; memcpy(&sample->ipdst.address, &nfKey6.dst_ip, IP6AddrSz); sample->dcd_ipProtocol = ntohl(nfKey6.protocol); sample->dcd_ipTos = ntohl(nfKey6.priority); sample->dcd_sport = ntohl(nfKey6.src_port); sample->dcd_dport = ntohl(nfKey6.dst_port); } sample->gotIPV6 = TRUE; } /*_________________---------------------------__________________ _________________ readv2v4FlowSample __________________ -----------------___________________________------------------ */ void readv2v4FlowSample(SFSample *sample, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req) { sample->samplesGenerated = getData32(sample); { u_int32_t samplerId = getData32(sample); sample->ds_class = samplerId >> 24; sample->ds_index = samplerId & 0x00ffffff; } sample->meanSkipCount = getData32(sample); sample->samplePool = getData32(sample); sample->dropEvents = getData32(sample); sample->inputPort = getData32(sample); sample->outputPort = getData32(sample); sample->packet_data_tag = getData32(sample); switch(sample->packet_data_tag) { case INMPACKETTYPE_HEADER: readFlowSample_header(sample); break; case INMPACKETTYPE_IPV4: readFlowSample_IPv4(sample); break; case INMPACKETTYPE_IPV6: readFlowSample_IPv6(sample); break; default: SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown v2/v4 Data Tag", (struct sockaddr *) pptrsv->v4.f_agent); xflow_status_table.tot_bad_datagrams++; break; } sample->extended_data_tag = 0; { u_int32_t x; sample->num_extended = getData32(sample); for(x = 0; x < sample->num_extended; x++) { u_int32_t extended_tag; extended_tag = getData32(sample); switch(extended_tag) { case INMEXTENDED_SWITCH: readExtendedSwitch(sample); break; case INMEXTENDED_ROUTER: readExtendedRouter(sample); break; case INMEXTENDED_GATEWAY: if(sample->datagramVersion == 2) readExtendedGateway_v2(sample); else readExtendedGateway(sample); break; case INMEXTENDED_USER: readExtendedUser(sample); break; case INMEXTENDED_URL: readExtendedUrl(sample); break; default: SF_notify_malf_packet(LOG_INFO, "INFO", "discarding unknown v2/v4 Extended Data Tag", (struct sockaddr *) pptrsv->v4.f_agent); xflow_status_table.tot_bad_datagrams++; break; } } } finalizeSample(sample, pptrsv, req); } /*_________________---------------------------__________________ _________________ readv5FlowSample __________________ -----------------___________________________------------------ */ void readv5FlowSample(SFSample *sample, int expanded, struct packet_ptrs_vector *pptrsv, struct plugin_requests *req, int finalize) { struct sfv5_modules_db_field *db_field = NULL; u_int32_t num_elements, sampleLength; u_char *sampleStart; sampleLength = getData32(sample); sampleStart = (u_char *)sample->datap; sample->samplesGenerated = getData32(sample); if(expanded) { sample->ds_class = getData32(sample); sample->ds_index = getData32(sample); } else { u_int32_t samplerId = getData32(sample); sample->ds_class = samplerId >> 24; sample->ds_index = samplerId & 0x00ffffff; } sample->meanSkipCount = getData32(sample); sample->samplePool = getData32(sample); sample->dropEvents = getData32(sample); if(expanded) { sample->inputPortFormat = getData32(sample); sample->inputPort = getData32(sample); sample->outputPortFormat = getData32(sample); sample->outputPort = getData32(sample); } else { u_int32_t inp, outp; inp = getData32(sample); outp = getData32(sample); sample->inputPortFormat = inp >> 30; sample->outputPortFormat = outp >> 30; sample->inputPort = inp; // skip 0x3fffffff mask sample->outputPort = outp; // skip 0x3fffffff mask } num_elements = getData32(sample); { u_int32_t el; for (el = 0; el < num_elements; el++) { u_int32_t tag, length; u_char *start; tag = getData32(sample); length = getData32(sample); start = (u_char *)sample->datap; switch(tag) { case SFLFLOW_HEADER: readFlowSample_header(sample); break; case SFLFLOW_ETHERNET: readFlowSample_ethernet(sample); break; case SFLFLOW_IPV4: readFlowSample_IPv4(sample); break; case SFLFLOW_IPV6: readFlowSample_IPv6(sample); break; case SFLFLOW_EX_SWITCH: readExtendedSwitch(sample); break; case SFLFLOW_EX_ROUTER: readExtendedRouter(sample); break; case SFLFLOW_EX_GATEWAY: readExtendedGateway(sample); break; case SFLFLOW_EX_USER: readExtendedUser(sample); break; case SFLFLOW_EX_URL: readExtendedUrl(sample); break; case SFLFLOW_EX_MPLS: readExtendedMpls(sample); break; case SFLFLOW_EX_NAT: readExtendedNat(sample); break; case SFLFLOW_EX_MPLS_TUNNEL: readExtendedMplsTunnel(sample); break; case SFLFLOW_EX_MPLS_VC: readExtendedMplsVC(sample); break; case SFLFLOW_EX_MPLS_FTN: readExtendedMplsFTN(sample); break; case SFLFLOW_EX_MPLS_LDP_FEC: readExtendedMplsLDP_FEC(sample); break; case SFLFLOW_EX_VLAN_TUNNEL: readExtendedVlanTunnel(sample); break; /* case SFLFLOW_EX_PROCESS: readExtendedProcess(sample); break; */ case SFLFLOW_EX_CLASS2: readExtendedClass2(sample); break; case SFLFLOW_EX_TAG: readExtendedTag(sample); break; default: if (skipBytesAndCheck(sample, length) == ERR) return; break; } db_field = sfv5_modules_db_get_next_ie(tag); if (db_field) { db_field->type = tag; db_field->ptr = start; db_field->len = length; } else Log(LOG_WARNING, "WARN ( %s/core ): readv5FlowSample(): no IEs available in SFv5 modules DB.\n", config.name); if (lengthCheck(sample, start, length) == ERR) return; } } if (lengthCheck(sample, sampleStart, sampleLength) == ERR) return; if (finalize) finalizeSample(sample, pptrsv, req); } void readv5CountersSample(SFSample *sample, int expanded, struct packet_ptrs_vector *pptrsv) { struct sfv5_modules_db_field *db_field = NULL; struct xflow_status_entry *xse = NULL; struct bgp_peer *peer = NULL; u_int32_t sampleLength, num_elements, idx; u_char *sampleStart; if (sfacctd_counter_backend_methods) { if (pptrsv) xse = (struct xflow_status_entry *) pptrsv->v4.f_status; if (xse) peer = (struct bgp_peer *) xse->sf_cnt; } sampleLength = getData32(sample); sampleStart = (u_char *)sample->datap; sample->cntSequenceNo = getData32(sample); if (expanded) { sample->ds_class = getData32(sample); sample->ds_index = getData32(sample); } else { u_int32_t samplerId = getData32(sample); sample->ds_class = samplerId >> 24; sample->ds_index = samplerId & 0x00ffffff; } num_elements = getData32(sample); for (idx = 0; idx < num_elements; idx++) { u_int32_t tag, length; u_char *start; char buf[51]; tag = getData32(sample); length = getData32(sample); start = (u_char *)sample->datap; Log(LOG_DEBUG, "DEBUG ( %s/core ): readv5CountersSample(): element tag %s.\n", config.name, printTag(tag, buf, 50)); db_field = sfv5_modules_db_get_next_ie(tag); if (db_field) { db_field->type = tag; db_field->ptr = start; db_field->len = length; } else Log(LOG_WARNING, "WARN ( %s/core ): readv5CountersSample(): no IEs available in SFv5 modules DB.\n", config.name); if (sfacctd_counter_backend_methods) sf_cnt_log_msg(peer, sample, sample->datagramVersion, length, "log", config.sfacctd_counter_output, tag); else skipBytes(sample, length); } if (lengthCheck(sample, sampleStart, sampleLength) == ERR) return; } /* seems like sFlow v2/v4 does not supply any meaningful information about the length of current sample. This is because we still need to parse the very first part of the sample */ void readv2v4CountersSample(SFSample *sample, struct packet_ptrs_vector *pptrsv) { struct xflow_status_entry *xse = NULL; struct bgp_peer *peer = NULL; int have_sample = FALSE; u_int32_t length = 0; if (sfacctd_counter_backend_methods) { if (pptrsv) xse = (struct xflow_status_entry *) pptrsv->v4.f_status; if (xse) peer = (struct bgp_peer *) xse->sf_cnt; } sample->cntSequenceNo = getData32(sample); { uint32_t samplerId = getData32(sample); sample->ds_class = samplerId >> 24; sample->ds_index = samplerId & 0x00ffffff; } sample->statsSamplingInterval = getData32(sample); sample->counterBlockVersion = getData32(sample); switch(sample->counterBlockVersion) { case INMCOUNTERSVERSION_GENERIC: case INMCOUNTERSVERSION_ETHERNET: case INMCOUNTERSVERSION_TOKENRING: case INMCOUNTERSVERSION_FDDI: case INMCOUNTERSVERSION_VG: case INMCOUNTERSVERSION_WAN: length += 88; break; case INMCOUNTERSVERSION_VLAN: break; default: return; } /* now see if there are any specific counter blocks to add */ switch(sample->counterBlockVersion) { case INMCOUNTERSVERSION_GENERIC: have_sample = TRUE; break; case INMCOUNTERSVERSION_ETHERNET: have_sample = TRUE; length += 52; break; case INMCOUNTERSVERSION_TOKENRING: length += 72; break; case INMCOUNTERSVERSION_FDDI: break; case INMCOUNTERSVERSION_VG: length += 80; break; case INMCOUNTERSVERSION_WAN: break; case INMCOUNTERSVERSION_VLAN: have_sample = TRUE; length += 28; break; default: return; } if (sfacctd_counter_backend_methods && have_sample) sf_cnt_log_msg(peer, sample, sample->datagramVersion, length, "log", config.sfacctd_counter_output, sample->counterBlockVersion); else skipBytes(sample, length); } pmacct-1.7.8/src/pgsql_plugin.h0000644000175000017500000000500414354105275015455 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include /* defines */ #define REPROCESS_SPECIFIC 1 #define REPROCESS_BULK 2 #include "plugin_common.h" /* prototypes */ void pgsql_plugin(int, struct configuration *, void *); int PG_cache_dbop(struct DBdesc *, struct db_cache *, struct insert_data *); int PG_cache_dbop_copy(struct DBdesc *, struct db_cache *, struct insert_data *); void PG_cache_purge(struct db_cache *[], int, struct insert_data *); int PG_evaluate_history(int); int PG_compose_static_queries(); void PG_compose_conn_string(struct DBdesc *, char *, int, char *); void PG_Lock(struct DBdesc *); void PG_DB_Connect(struct DBdesc *, char *); void PG_DB_Close(struct BE_descs *); void PG_create_dyn_table(struct DBdesc *, char *); int PG_affected_rows(PGresult *); void PG_create_backend(struct DBdesc *); void PG_set_callbacks(struct sqlfunc_cb_registry *); void PG_init_default_values(struct insert_data *); void PG_postgresql_get_version(); /* global vars */ extern int typed; /* variables */ extern char pgsql_user[]; extern char pgsql_pwd[]; extern char pgsql_db[]; extern char pgsql_table[]; extern char pgsql_table_v2[]; extern char pgsql_table_v3[]; extern char pgsql_table_v4[]; extern char pgsql_table_v5[]; extern char pgsql_table_v6[]; extern char pgsql_table_v7[]; extern char pgsql_table_v8[]; extern char pgsql_table_bgp[]; extern char pgsql_table_uni[]; extern char pgsql_table_uni_v2[]; extern char pgsql_table_uni_v3[]; extern char pgsql_table_uni_v4[]; extern char pgsql_table_uni_v5[]; extern char pgsql_table_as[]; extern char pgsql_table_as_v2[]; extern char pgsql_table_as_v3[]; extern char pgsql_table_as_v4[]; extern char pgsql_table_as_v5[]; extern char typed_str[]; extern char unified_str[]; pmacct-1.7.8/src/base64.h0000644000175000017500000000130014354105275014030 0ustar paolopaolo/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef _BASE64_H_ #define _BASE64_H_ unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); void base64_freebuf(unsigned char *); #endif /* _BASE64_H_ */ pmacct-1.7.8/src/amqp_common.h0000644000175000017500000000731314354105275015264 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef AMQP_COMMON_H #define AMQP_COMMON_H /* includes */ #include #include #include "plugin_common.h" /* defines */ #define AMQP_DEFAULT_RETRY 60 #define PM_AMQP_MIN_FRAME_SIZE 4096 /* structures */ struct p_amqp_host { char *user; char *passwd; char *exchange; char *exchange_type; char *routing_key; struct p_table_rr rk_rr; char *host; char *vhost; int persistent_msg; u_int8_t content_type; u_int32_t frame_max; int heartbeat_interval; amqp_connection_state_t conn; amqp_socket_t *socket; amqp_rpc_reply_t ret; amqp_bytes_t queue; struct amqp_basic_properties_t_ msg_props; int status; struct p_broker_timers btimers; }; /* prototypes */ extern void p_amqp_init_host(struct p_amqp_host *); extern void p_amqp_init_routing_key_rr(struct p_amqp_host *); extern void p_amqp_set_user(struct p_amqp_host *, char *); extern void p_amqp_set_passwd(struct p_amqp_host *, char *); extern void p_amqp_set_exchange(struct p_amqp_host *, char *); extern void p_amqp_set_routing_key(struct p_amqp_host *, char *); extern void p_amqp_set_routing_key_rr(struct p_amqp_host *, int); extern void p_amqp_set_exchange_type(struct p_amqp_host *, char *); extern void p_amqp_set_host(struct p_amqp_host *, char *); extern void p_amqp_set_vhost(struct p_amqp_host *, char *); extern void p_amqp_set_persistent_msg(struct p_amqp_host *, int); extern void p_amqp_set_frame_max(struct p_amqp_host *, u_int32_t); extern void p_amqp_set_heartbeat_interval(struct p_amqp_host *, int); extern void p_amqp_set_content_type_json(struct p_amqp_host *); extern void p_amqp_set_content_type_binary(struct p_amqp_host *); extern char *p_amqp_get_routing_key(struct p_amqp_host *); extern int p_amqp_get_routing_key_rr(struct p_amqp_host *); extern int p_amqp_get_sockfd(struct p_amqp_host *); extern void p_amqp_get_version(); extern void p_amqp_unset_routing_key(struct p_amqp_host *); extern int p_amqp_connect_to_publish(struct p_amqp_host *); extern int p_amqp_publish_string(struct p_amqp_host *, char *); extern int p_amqp_publish_binary(struct p_amqp_host *, void *, u_int32_t); extern void p_amqp_close(struct p_amqp_host *, int); extern int p_amqp_is_alive(struct p_amqp_host *); extern int write_and_free_json_amqp(void *, void *); extern int write_binary_amqp(void *, void *, size_t); extern int write_string_amqp(void *, char *); /* global vars */ extern struct p_amqp_host amqpp_amqp_host; extern struct p_amqp_host bgp_daemon_msglog_amqp_host; extern struct p_amqp_host bmp_daemon_msglog_amqp_host; extern struct p_amqp_host sfacctd_counter_amqp_host; extern struct p_amqp_host telemetry_daemon_msglog_amqp_host; extern char rabbitmq_user[]; extern char rabbitmq_pwd[]; extern char default_amqp_exchange[]; extern char default_amqp_exchange_type[]; extern char default_amqp_routing_key[]; extern char default_amqp_host[]; extern char default_amqp_vhost[]; #endif //AMQP_COMMON_H pmacct-1.7.8/src/conntrack.h0000644000175000017500000000533314354105275014740 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CONNTRACK_H #define CONNTRACK_H /* defines */ #define CONNTRACK_GENERIC_LIFETIME 20 #define DEFAULT_CONNTRACK_BUFFER_SIZE 8192000 /* 8 Mb */ #define MAX_CONNTRACKS 256 /* structures */ typedef void (*conntrack_helper)(time_t, struct packet_ptrs *); struct conntrack_helper_entry { char protocol[MAX_PROTOCOL_LEN]; conntrack_helper ct_helper; }; struct conntrack_ipv4 { u_int32_t ip_src; u_int32_t ip_dst; u_int16_t port_src; u_int16_t port_dst; u_int8_t proto; pm_class_t class; /* timestamp renewal flag ? */ time_t stamp; time_t expiration; conntrack_helper helper; struct conntrack_ipv4 *next; }; struct conntrack_ipv6 { u_int32_t ip_src[4]; u_int32_t ip_dst[4]; u_int16_t port_src; u_int16_t port_dst; u_int8_t proto; pm_class_t class; /* timestamp renewal flag ? */ time_t stamp; time_t expiration; conntrack_helper helper; struct conntrack_ipv6 *next; }; extern void init_conntrack_table(); extern void conntrack_ftp_helper(time_t, struct packet_ptrs *); extern void conntrack_sip_helper(time_t, struct packet_ptrs *); extern void conntrack_rtsp_helper(time_t, struct packet_ptrs *); extern void search_conntrack(struct ip_flow_common *, struct packet_ptrs *, unsigned int); extern void search_conntrack_ipv4(struct ip_flow_common *, struct packet_ptrs *, unsigned int); extern void insert_conntrack_ipv4(time_t, u_int32_t, u_int32_t, u_int16_t, u_int16_t, u_int8_t, pm_class_t, conntrack_helper, time_t); extern void search_conntrack_ipv6(struct ip_flow_common *, struct packet_ptrs *, unsigned int); extern void insert_conntrack_ipv6(time_t, struct in6_addr *, struct in6_addr *, u_int16_t, u_int16_t, u_int8_t, pm_class_t, conntrack_helper, time_t); extern struct conntrack_ipv4 *conntrack_ipv4_table; extern struct conntrack_ipv6 *conntrack_ipv6_table; extern struct conntrack_helper_entry __attribute__((unused)) conntrack_helper_list[4]; #endif //CONNTRACK_H pmacct-1.7.8/src/pretag-data.h0000644000175000017500000002275414354105275015155 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ const struct _map_dictionary_line tag_map_dictionary[] = { {"id", PT_map_id_handler}, {"id2", PT_map_id2_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"engine_type", PT_map_engine_type_handler}, {"engine_id", PT_map_engine_id_handler}, {"source_id", PT_map_engine_id_handler}, {"nexthop", PT_map_nexthop_handler}, {"bgp_nexthop", PT_map_bgp_nexthop_handler}, {"filter", PT_map_filter_handler}, {"agent_id", PT_map_agent_id_handler}, {"flowset_id", PT_map_flowset_id_handler}, {"sample_type", PT_map_sample_type_handler}, {"direction", PT_map_direction_handler}, {"nat_event", PT_map_nat_event_handler}, /* XXX: to be deprecated */ {"src_as", PT_map_src_as_handler}, {"dst_as", PT_map_dst_as_handler}, {"peer_src_as", PT_map_peer_src_as_handler}, {"peer_dst_as", PT_map_peer_dst_as_handler}, {"src_local_pref", PT_map_src_local_pref_handler}, {"local_pref", PT_map_local_pref_handler}, {"src_roa", PT_map_src_roa_handler}, {"dst_roa", PT_map_dst_roa_handler}, {"src_comms", PT_map_src_comms_handler}, {"comms", PT_map_comms_handler}, {"mpls_vpn_rd", PT_map_mpls_vpn_rd_handler}, {"mpls_pw_id", PT_map_mpls_pw_id_handler}, {"src_mac", PT_map_src_mac_handler}, {"dst_mac", PT_map_dst_mac_handler}, {"vlan", PT_map_vlan_id_handler}, {"cvlan", PT_map_cvlan_id_handler}, {"src_net", PT_map_src_net_handler}, {"dst_net", PT_map_dst_net_handler}, {"is_multicast", PT_map_is_multicast_handler}, {"set_tag", PT_map_id_handler}, {"set_tag2", PT_map_id2_handler}, {"set_label", PT_map_label_handler}, {"set_tos", PT_map_set_tos_handler}, {"label", PT_map_entry_label_handler}, {"jeq", PT_map_jeq_handler}, {"return", PT_map_return_handler}, {"stack", PT_map_stack_handler}, {"fwdstatus", PT_map_fwd_status_handler}, /* XXX: to be deprecated */ {"fwd_status", PT_map_fwd_status_handler}, {"is_bi_flow", PT_map_is_bi_flow_handler}, {"is_nsel", PT_map_is_nsel_handler}, {"is_nel", PT_map_is_nel_handler}, {"", NULL} }; const struct _map_index_internal_dictionary_line tag_map_index_entries_dictionary[] = { {PRETAG_IP, PT_map_index_entries_ip_handler}, {PRETAG_IN_IFACE, PT_map_index_entries_input_handler}, {PRETAG_OUT_IFACE, PT_map_index_entries_output_handler}, {PRETAG_BGP_NEXTHOP, PT_map_index_entries_bgp_nexthop_handler}, {PRETAG_SRC_AS, PT_map_index_entries_src_as_handler}, {PRETAG_DST_AS, PT_map_index_entries_dst_as_handler}, {PRETAG_PEER_SRC_AS, PT_map_index_entries_peer_src_as_handler}, {PRETAG_PEER_DST_AS, PT_map_index_entries_peer_dst_as_handler}, {PRETAG_MPLS_LABEL_BOTTOM, PT_map_index_entries_mpls_label_bottom_handler}, {PRETAG_MPLS_VPN_ID, PT_map_index_entries_mpls_vpn_id_handler}, {PRETAG_MPLS_VPN_RD, PT_map_index_entries_mpls_vpn_rd_handler}, {PRETAG_MPLS_PW_ID, PT_map_index_entries_mpls_pw_id_handler}, {PRETAG_SRC_MAC, PT_map_index_entries_src_mac_handler}, {PRETAG_DST_MAC, PT_map_index_entries_dst_mac_handler}, {PRETAG_VLAN_ID, PT_map_index_entries_vlan_id_handler}, {PRETAG_CVLAN_ID, PT_map_index_entries_cvlan_id_handler}, {PRETAG_SRC_NET, PT_map_index_entries_src_net_handler}, {PRETAG_DST_NET, PT_map_index_entries_dst_net_handler}, {PRETAG_IS_MULTICAST, PT_map_index_entries_is_multicast_handler}, {PRETAG_FWDSTATUS_ID, PT_map_index_entries_fwd_status_handler}, {PRETAG_NULL, PT_map_index_entries_null_handler}, {0, NULL} }; const struct _map_index_dictionary_line tag_map_index_fdata_dictionary[] = { {PRETAG_IP, PT_map_index_fdata_ip_handler}, {PRETAG_IN_IFACE, PT_map_index_fdata_input_handler}, {PRETAG_OUT_IFACE, PT_map_index_fdata_output_handler}, {PRETAG_BGP_NEXTHOP, PT_map_index_fdata_bgp_nexthop_handler}, {PRETAG_SRC_AS, PT_map_index_fdata_src_as_handler}, {PRETAG_DST_AS, PT_map_index_fdata_dst_as_handler}, {PRETAG_PEER_SRC_AS, PT_map_index_fdata_peer_src_as_handler}, {PRETAG_PEER_DST_AS, PT_map_index_fdata_peer_dst_as_handler}, {PRETAG_MPLS_LABEL_BOTTOM, PT_map_index_fdata_mpls_label_bottom_handler}, {PRETAG_MPLS_VPN_ID, PT_map_index_fdata_mpls_vpn_id_handler}, {PRETAG_MPLS_VPN_RD, PT_map_index_fdata_mpls_vpn_rd_handler}, {PRETAG_MPLS_PW_ID, PT_map_index_fdata_mpls_pw_id_handler}, {PRETAG_SRC_MAC, PT_map_index_fdata_src_mac_handler}, {PRETAG_DST_MAC, PT_map_index_fdata_dst_mac_handler}, {PRETAG_VLAN_ID, PT_map_index_fdata_vlan_id_handler}, {PRETAG_CVLAN_ID, PT_map_index_fdata_cvlan_id_handler}, {PRETAG_SRC_NET, PT_map_index_fdata_src_net_handler}, {PRETAG_DST_NET, PT_map_index_fdata_dst_net_handler}, {PRETAG_IS_MULTICAST, PT_map_index_fdata_is_multicast_handler}, {PRETAG_FWDSTATUS_ID, PT_map_index_fdata_fwd_status_handler}, {PRETAG_NULL, PT_map_index_fdata_null_handler}, {0, NULL} }; const struct _map_index_size_dictionary_line tag_map_index_entries_size_dictionary[] = { {PRETAG_IP, sizeof(struct host_addr)}, {PRETAG_IN_IFACE, sizeof(u_int32_t)}, {PRETAG_OUT_IFACE, sizeof(u_int32_t)}, {PRETAG_BGP_NEXTHOP, sizeof(struct host_addr)}, {PRETAG_SRC_AS, sizeof(u_int32_t)}, {PRETAG_DST_AS, sizeof(u_int32_t)}, {PRETAG_PEER_SRC_AS, sizeof(u_int32_t)}, {PRETAG_PEER_DST_AS, sizeof(u_int32_t)}, {PRETAG_MPLS_LABEL_BOTTOM, sizeof(u_int32_t)}, {PRETAG_MPLS_VPN_ID, sizeof(u_int32_t)}, {PRETAG_MPLS_VPN_RD, sizeof(rd_t)}, {PRETAG_SRC_MAC, ETH_ADDR_LEN}, {PRETAG_DST_MAC, ETH_ADDR_LEN}, {PRETAG_VLAN_ID, sizeof(u_int16_t)}, {PRETAG_CVLAN_ID, sizeof(u_int16_t)}, {PRETAG_SRC_NET, (sizeof(struct host_addr) /* net */ + sizeof(u_int8_t) /* mask */)}, {PRETAG_DST_NET, (sizeof(struct host_addr) /* net */ + sizeof(u_int8_t) /* mask */)}, {PRETAG_IS_MULTICAST, sizeof(u_int8_t)}, {PRETAG_FWDSTATUS_ID, sizeof(u_int8_t)}, {PRETAG_NULL, sizeof(u_int8_t)}, {0, 0} }; const struct _map_dictionary_line tag_map_tee_dictionary[] = { {"id", PT_map_id_handler}, {"id2", PT_map_id2_handler}, {"set_tag", PT_map_id_handler}, {"set_tag2", PT_map_id2_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"src_mac", PT_map_src_mac_handler}, {"dst_mac", PT_map_dst_mac_handler}, {"vlan", PT_map_vlan_id_handler}, {"src_net", PT_map_src_net_handler}, {"dst_net", PT_map_dst_net_handler}, {"bgp_nexthop", PT_map_bgp_nexthop_handler}, {"engine_type", PT_map_engine_type_handler}, {"engine_id", PT_map_engine_id_handler}, {"source_id", PT_map_engine_id_handler}, {"agent_id", PT_map_agent_id_handler}, {"label", PT_map_entry_label_handler}, {"jeq", PT_map_jeq_handler}, {"return", PT_map_return_handler}, {"stack", PT_map_stack_handler}, {"", NULL} }; const struct _map_dictionary_line tag_map_nonflow_dictionary[] = { {"set_tag", PT_map_id_handler}, {"ip", PT_map_ip_handler}, {"set_label", PT_map_label_handler}, {"", NULL} }; const struct _map_dictionary_line bpas_map_dictionary[] = { {"id", PT_map_id_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"bgp_nexthop", BPAS_map_bgp_nexthop_handler}, {"peer_dst_as", BPAS_map_bgp_peer_dst_as_handler}, {"src_mac", PT_map_src_mac_handler}, {"vlan", PT_map_vlan_id_handler}, {"src_net", PT_map_src_net_handler}, {"dst_net", PT_map_dst_net_handler}, {"filter", PT_map_filter_handler}, {"", NULL} }; const struct _map_dictionary_line bta_map_dictionary[] = { {"id", PT_map_id_handler}, {"bgp_ip", PT_map_id_handler}, {"bgp_port", BTA_map_lookup_bgp_port_handler}, {"bmp_ip", PT_map_id_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"filter", PT_map_filter_handler}, {"", NULL} }; const struct _map_dictionary_line sampling_map_dictionary[] = { {"id", PT_map_id_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"", NULL} }; const struct _map_dictionary_line bitr_map_dictionary[] = { {"id", PT_map_id_handler}, {"ip", PT_map_ip_handler}, {"in", PT_map_input_handler}, {"out", PT_map_output_handler}, {"bgp_nexthop", PT_map_bgp_nexthop_handler}, {"mpls_vpn_id", BITR_map_mpls_vpn_id_handler}, {"mpls_label_bottom", BITR_map_mpls_label_bottom_handler}, {"", NULL} }; const struct _map_dictionary_line custom_primitives_map_dictionary[] = { {"name", custom_primitives_map_name_handler}, {"packet_ptr", custom_primitives_map_packet_ptr_handler}, {"field_type", custom_primitives_map_field_type_handler}, {"len", custom_primitives_map_len_handler}, {"semantics", custom_primitives_map_semantics_handler}, {"", NULL} }; const struct _map_dictionary_line pm_pcap_interfaces_map_dictionary[] = { {"ifindex", pm_pcap_interfaces_map_ifindex_handler}, {"ifname", pm_pcap_interfaces_map_ifname_handler}, {"direction", pm_pcap_interfaces_map_direction_handler}, {"", NULL} }; pmacct-1.7.8/src/cfg_handlers.h0000644000175000017500000010534314354105275015377 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CFG_HANDLER_H #define CFG_HANDLER_H /* prototypes */ extern int parse_truefalse(char *); extern int parse_truefalse_nonzero(char *); extern int validate_truefalse(int); extern void cfg_key_legacy_warning(char *, char *); extern int cfg_key_debug(char *, char *, char *); extern int cfg_key_debug_internal_msg(char *, char *, char *); extern int cfg_key_syslog(char *, char *, char *); extern int cfg_key_logfile(char *, char *, char *); extern int cfg_key_pidfile(char *, char *, char *); extern int cfg_key_daemonize(char *, char *, char *); extern int cfg_key_propagate_signals(char *, char *, char *); extern int cfg_key_proc_name(char *, char *, char *); extern int cfg_key_proc_priority(char *, char *, char *); extern int cfg_key_cluster_name(char *, char *, char *); extern int cfg_key_cluster_id(char *, char *, char *); extern int cfg_key_redis_host(char *, char *, char *); extern int cfg_key_redis_db(char *, char *, char *); extern int cfg_key_aggregate(char *, char *, char *); extern int cfg_key_aggregate_primitives(char *, char *, char *); extern int cfg_key_snaplen(char *, char *, char *); extern int cfg_key_aggregate_filter(char *, char *, char *); extern int cfg_key_aggregate_unknown_etype(char *, char *, char *); extern int cfg_key_dtls_path(char *, char *, char *); extern int cfg_key_writer_id_string(char *, char *, char *); extern int cfg_key_pcap_filter(char *, char *, char *); extern int cfg_key_pcap_protocol(char *, char *, char *); extern int cfg_key_pcap_savefile(char *, char *, char *); extern int cfg_key_pcap_savefile_wait(char *, char *, char *); extern int cfg_key_pcap_savefile_delay(char *, char *, char *); extern int cfg_key_pcap_savefile_replay(char *, char *, char *); extern int cfg_key_pcap_direction(char *, char *, char *); extern int cfg_key_pcap_ifindex(char *, char *, char *); extern int cfg_key_pcap_interfaces_map(char *, char *, char *); extern int cfg_key_pcap_arista_trailer_offset(char *, char *, char *); extern int cfg_key_pcap_arista_trailer_flag_value(char *, char *, char *); extern int cfg_key_use_ip_next_hop(char *, char *, char *); extern int cfg_key_thread_stack(char *, char *, char *); extern int cfg_key_pcap_interface(char *, char *, char *); extern int cfg_key_pcap_interface_wait(char *, char *, char *); extern int cfg_key_files_umask(char *, char *, char *); extern int cfg_key_files_uid(char *, char *, char *); extern int cfg_key_files_gid(char *, char *, char *); extern int cfg_key_promisc(char *, char *, char *); extern int cfg_key_num_protos(char *, char *, char *); extern int cfg_key_num_hosts(char *, char *, char *); extern int cfg_key_imt_path(char *, char *, char *); extern int cfg_key_imt_passwd(char *, char *, char *); extern int cfg_key_imt_buckets(char *, char *, char *); extern int cfg_key_imt_mem_pools_number(char *, char *, char *); extern int cfg_key_imt_mem_pools_size(char *, char *, char *); extern int cfg_key_sql_db(char *, char *, char *); extern int cfg_key_sql_table(char *, char *, char *); extern int cfg_key_sql_table_schema(char *, char *, char *); extern int cfg_key_sql_table_version(char *, char *, char *); extern int cfg_key_sql_table_type(char *, char *, char *); extern int cfg_key_sql_conn_ca_file(char *, char *, char *); extern int cfg_key_sql_host(char *, char *, char *); extern int cfg_key_sql_port(char *, char *, char *); extern int cfg_key_sql_data(char *, char *, char *); extern int cfg_key_sql_user(char *, char *, char *); extern int cfg_key_sql_passwd(char *, char *, char *); extern int cfg_key_sql_refresh_time(char *, char *, char *); extern int cfg_key_sql_startup_delay(char *, char *, char *); extern int cfg_key_sql_optimize_clauses(char *, char *, char *); extern int cfg_key_sql_history(char *, char *, char *); extern int cfg_key_sql_history_offset(char *, char *, char *); extern int cfg_key_sql_history_roundoff(char *, char *, char *); extern int cfg_key_sql_recovery_backup_host(char *, char *, char *); extern int cfg_key_sql_trigger_exec(char *, char *, char *); extern int cfg_key_sql_trigger_time(char *, char *, char *); extern int cfg_key_sql_cache_entries(char *, char *, char *); extern int cfg_key_sql_dont_try_update(char *, char *, char *); extern int cfg_key_sql_preprocess(char *, char *, char *); extern int cfg_key_sql_preprocess_type(char *, char *, char *); extern int cfg_key_sql_multi_values(char *, char *, char *); extern int cfg_key_sql_locking_style(char *, char *, char *); extern int cfg_key_sql_use_copy(char *, char *, char *); extern int cfg_key_sql_delimiter(char *, char *, char *); extern int cfg_key_timestamps_rfc3339(char *, char *, char *); extern int cfg_key_timestamps_utc(char *, char *, char *); extern int cfg_key_timestamps_secs(char *, char *, char *); extern int cfg_key_timestamps_since_epoch(char *, char *, char *); extern int cfg_key_mongo_insert_batch(char *, char *, char *); extern int cfg_key_message_broker_output(char *, char *, char *); extern int cfg_key_avro_buffer_size(char *, char *, char *); extern int cfg_key_avro_schema_file(char *, char *, char *); extern int cfg_key_amqp_exchange_type(char *, char *, char *); extern int cfg_key_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_amqp_frame_max(char *, char *, char *); extern int cfg_key_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_amqp_vhost(char *, char *, char *); extern int cfg_key_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_amqp_avro_schema_routing_key(char *, char *, char *); extern int cfg_key_amqp_avro_schema_refresh_time(char *, char *, char *); extern int cfg_key_kafka_broker_port(char *, char *, char *); extern int cfg_key_kafka_partition(char *, char *, char *); extern int cfg_key_kafka_partition_dynamic(char *, char *, char *); extern int cfg_key_kafka_partition_key(char *, char *, char *); extern int cfg_key_kafka_avro_schema_topic(char *, char *, char *); extern int cfg_key_kafka_avro_schema_refresh_time(char *, char *, char *); extern int cfg_key_kafka_avro_schema_registry(char *, char *, char *); extern int cfg_key_kafka_config_file(char *, char *, char *); extern int cfg_key_plugin_pipe_size(char *, char *, char *); extern int cfg_key_plugin_buffer_size(char *, char *, char *); extern int cfg_key_plugin_pipe_zmq(char *, char *, char *); extern int cfg_key_plugin_pipe_zmq_retry(char *, char *, char *); extern int cfg_key_plugin_pipe_zmq_profile(char *, char *, char *); extern int cfg_key_plugin_pipe_zmq_hwm(char *, char *, char *); extern int cfg_key_plugin_exit_any(char *, char *, char *); extern int cfg_key_networks_mask(char *, char *, char *); extern int cfg_key_networks_file(char *, char *, char *); extern int cfg_key_networks_file_filter(char *, char *, char *); extern int cfg_key_networks_file_no_lpm(char *, char *, char *); extern int cfg_key_networks_no_mask_if_zero(char *, char *, char *); extern int cfg_key_networks_cache_entries(char *, char *, char *); extern int cfg_key_ports_file(char *, char *, char *); extern int cfg_key_protos_file(char *, char *, char *); extern int cfg_key_tos_file(char *, char *, char *); extern int cfg_key_print_cache_entries(char *, char *, char *); extern int cfg_key_print_markers(char *, char *, char *); extern int cfg_key_print_output(char *, char *, char *); extern int cfg_key_print_output_file(char *, char *, char *); extern int cfg_key_print_output_file_append(char *, char *, char *); extern int cfg_key_print_write_empty_file(char *, char *, char *); extern int cfg_key_print_output_lock_file(char *, char *, char *); extern int cfg_key_print_output_separator(char *, char *, char *); extern int cfg_key_print_output_custom_lib(char *, char *, char *); extern int cfg_key_print_output_custom_cfg_file(char *, char *, char *); extern int cfg_key_print_latest_file(char *, char *, char *); extern int cfg_key_nfacctd_port(char *, char *, char *); extern int cfg_key_nfacctd_ip(char *, char *, char *); extern int cfg_key_nfacctd_interface(char *, char *, char *); extern int cfg_key_nfacctd_ipv6_only(char *, char *, char *); extern int cfg_key_nfacctd_rp_ebpf_prog(char *, char *, char *); extern int cfg_key_nfacctd_allow_file(char *, char *, char *); extern int cfg_key_nfacctd_time_secs(char *, char *, char *); extern int cfg_key_nfacctd_time_new(char *, char *, char *); extern int cfg_key_nfacctd_as_new(char *, char *, char *); extern int cfg_key_nfacctd_net(char *, char *, char *); extern int cfg_key_nfacctd_disable_checks(char *, char *, char *); extern int cfg_key_nfacctd_disable_opt_scope_check(char *, char *, char *); extern int cfg_key_nfacctd_mcast_groups(char *, char *, char *); extern int cfg_key_nfacctd_pipe_size(char *, char *, char *); extern int cfg_key_nfacctd_pro_rating(char *, char *, char *); extern int cfg_key_nfacctd_templates_file(char *, char *, char *); extern int cfg_key_nfacctd_templates_receiver(char *, char *, char *); extern int cfg_key_nfacctd_templates_port(char *, char *, char *); extern int cfg_key_nfacctd_account_options(char *, char *, char *); extern int cfg_key_nfacctd_stitching(char *, char *, char *); extern int cfg_key_nfacctd_kafka_broker_host(char *, char *, char *); extern int cfg_key_nfacctd_kafka_broker_port(char *, char *, char *); extern int cfg_key_nfacctd_kafka_topic(char *, char *, char *); extern int cfg_key_nfacctd_kafka_config_file(char *, char *, char *); extern int cfg_key_nfacctd_zmq_address(char *, char *, char *); extern int cfg_key_nfacctd_dtls_port(char *, char *, char *); extern int cfg_key_mpls_label_stack_encode_as_array(char *, char *, char *); extern int cfg_key_pmacctd_force_frag_handling(char *, char *, char *); extern int cfg_key_pmacctd_frag_buffer_size(char *, char *, char *); extern int cfg_key_pmacctd_flow_buffer_size(char *, char *, char *); extern int cfg_key_pmacctd_flow_buffer_buckets(char *, char *, char *); extern int cfg_key_pmacctd_conntrack_buffer_size(char *, char *, char *); extern int cfg_key_pmacctd_flow_lifetime(char *, char *, char *); extern int cfg_key_pmacctd_flow_tcp_lifetime(char *, char *, char *); extern int cfg_key_pmacctd_ext_sampling_rate(char *, char *, char *); extern int cfg_key_pmacctd_nonroot(char *, char *, char *); extern int cfg_key_sfacctd_renormalize(char *, char *, char *); extern int cfg_key_sfacctd_counter_output(char *, char *, char *); extern int cfg_key_sfacctd_counter_file(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_host(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_vhost(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_user(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_passwd(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_exchange(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_exchange_type(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_routing_key(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_frame_max(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_sfacctd_counter_amqp_retry(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_broker_host(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_broker_port(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_topic(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_partition(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_partition_key(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_retry(char *, char *, char *); extern int cfg_key_sfacctd_counter_kafka_config_file(char *, char *, char *); extern int cfg_key_telemetry_daemon(char *, char *, char *); extern int cfg_key_telemetry_port_tcp(char *, char *, char *); extern int cfg_key_telemetry_port_udp(char *, char *, char *); extern int cfg_key_telemetry_ip(char *, char *, char *); extern int cfg_key_telemetry_interface(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_port(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_ip(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_interface(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_ipv6_only(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_nmsgs(char *, char *, char *); extern int cfg_key_telemetry_udp_notif_rp_ebpf_prog(char *, char *, char *); extern int cfg_key_telemetry_ipv6_only(char *, char *, char *); extern int cfg_key_telemetry_zmq_address(char *, char *, char *); extern int cfg_key_telemetry_kafka_broker_host(char *, char *, char *); extern int cfg_key_telemetry_kafka_broker_port(char *, char *, char *); extern int cfg_key_telemetry_kafka_topic(char *, char *, char *); extern int cfg_key_telemetry_kafka_config_file(char *, char *, char *); extern int cfg_key_telemetry_decoder(char *, char *, char *); extern int cfg_key_telemetry_max_peers(char *, char *, char *); extern int cfg_key_telemetry_peer_timeout(char *, char *, char *); extern int cfg_key_telemetry_tag_map(char *, char *, char *); extern int cfg_key_telemetry_allow_file(char *, char *, char *); extern int cfg_key_telemetry_pipe_size(char *, char *, char *); extern int cfg_key_telemetry_ip_precedence(char *, char *, char *); extern int cfg_key_telemetry_msglog_output(char *, char *, char *); extern int cfg_key_telemetry_msglog_file(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_host(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_vhost(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_user(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_passwd(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_exchange(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_exchange_type(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_routing_key(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_frame_max(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_telemetry_msglog_amqp_retry(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_broker_host(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_broker_port(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_topic(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_topic_rr(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_partition(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_partition_key(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_retry(char *, char *, char *); extern int cfg_key_telemetry_msglog_kafka_config_file(char *, char *, char *); extern int cfg_key_telemetry_dump_output(char *, char *, char *); extern int cfg_key_telemetry_dump_file(char *, char *, char *); extern int cfg_key_telemetry_dump_latest_file(char *, char *, char *); extern int cfg_key_telemetry_dump_refresh_time(char *, char *, char *); extern int cfg_key_telemetry_dump_time_slots(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_host(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_vhost(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_user(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_passwd(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_exchange(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_exchange_type(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_routing_key(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_frame_max(char *, char *, char *); extern int cfg_key_telemetry_dump_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_broker_host(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_broker_port(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_topic(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_topic_rr(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_partition(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_partition_key(char *, char *, char *); extern int cfg_key_telemetry_dump_kafka_config_file(char *, char *, char *); extern int cfg_key_telemetry_dump_workers(char *, char *, char *); extern int cfg_key_maps_refresh(char *, char *, char *); extern int cfg_key_maps_index(char *, char *, char *); extern int cfg_key_maps_entries(char *, char *, char *); extern int cfg_key_maps_row_len(char *, char *, char *); extern int cfg_key_pre_tag_map(char *, char *, char *); extern int cfg_key_pre_tag_filter(char *, char *, char *); extern int cfg_key_pre_tag2_filter(char *, char *, char *); extern int cfg_key_pre_tag_label_filter(char *, char *, char *); extern int cfg_key_pre_tag_label_encode_as_map(char *, char *, char *); extern int cfg_key_tcpflags_encode_as_array(char *, char *, char *); extern int cfg_key_fwd_status_encode_as_string(char *, char *, char *); extern int cfg_key_tos_encode_as_dscp(char *, char *, char *); extern int cfg_key_post_tag(char *, char *, char *); extern int cfg_key_post_tag2(char *, char *, char *); extern int cfg_key_sampling_rate(char *, char *, char *); extern int cfg_key_sampling_map(char *, char *, char *); extern int cfg_key_classifier_ndpi_num_roots(char *, char *, char *); extern int cfg_key_classifier_ndpi_max_flows(char *, char *, char *); extern int cfg_key_classifier_ndpi_proto_guess(char *, char *, char *); extern int cfg_key_classifier_ndpi_idle_scan_period(char *, char *, char *); extern int cfg_key_classifier_ndpi_idle_max_time(char *, char *, char *); extern int cfg_key_classifier_ndpi_idle_scan_budget(char *, char *, char *); extern int cfg_key_classifier_ndpi_giveup_proto_tcp(char *, char *, char *); extern int cfg_key_classifier_ndpi_giveup_proto_udp(char *, char *, char *); extern int cfg_key_classifier_ndpi_giveup_proto_other(char *, char *, char *); extern int cfg_key_nfprobe_timeouts(char *, char *, char *); extern int cfg_key_nfprobe_hoplimit(char *, char *, char *); extern int cfg_key_nfprobe_maxflows(char *, char *, char *); extern int cfg_key_nfprobe_receiver(char *, char *, char *); extern int cfg_key_nfprobe_dtls(char *, char *, char *); extern int cfg_key_nfprobe_dtls_verify_cert(char *, char *, char *); extern int cfg_key_nfprobe_version(char *, char *, char *); extern int cfg_key_nfprobe_engine(char *, char *, char *); extern int cfg_key_nfprobe_peer_as(char *, char *, char *); extern int cfg_key_nfprobe_source_ip(char *, char *, char *); extern int cfg_key_nfprobe_ip_precedence(char *, char *, char *); extern int cfg_key_nfprobe_direction(char *, char *, char *); extern int cfg_key_nfprobe_ifindex(char *, char *, char *); extern int cfg_key_nfprobe_ifindex_override(char *, char *, char *); extern int cfg_key_nfprobe_tstamp_usec(char *, char *, char *); extern int cfg_key_nfprobe_dont_cache(char *, char *, char *); extern int cfg_key_sfprobe_receiver(char *, char *, char *); extern int cfg_key_sfprobe_agentip(char *, char *, char *); extern int cfg_key_sfprobe_agentsubid(char *, char *, char *); extern int cfg_key_sfprobe_ifspeed(char *, char *, char *); extern int cfg_key_tee_receivers(char *, char *, char *); extern int cfg_key_tee_transparent(char *, char *, char *); extern int cfg_key_tee_max_receivers(char *, char *, char *); extern int cfg_key_tee_max_receiver_pools(char *, char *, char *); extern int cfg_key_tee_pipe_size(char *, char *, char *); extern int cfg_key_tee_kafka_config_file(char *, char *, char *); extern int cfg_key_bgp_daemon(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_output(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_file(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_avro_schema_file(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_host(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_vhost(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_user(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_passwd(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_exchange(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_exchange_type(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_routing_key(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_frame_max(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_amqp_retry(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_broker_host(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_broker_port(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_topic(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_topic_rr(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_partition(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_partition_key(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_retry(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_config_file(char *, char *, char *); extern int cfg_key_bgp_daemon_msglog_kafka_avro_schema_registry(char *, char *, char *); extern int cfg_key_bgp_daemon_max_peers(char *, char *, char *); extern int cfg_key_bgp_daemon_ip(char *, char *, char *); extern int cfg_key_bgp_daemon_interface(char *, char *, char *); extern int cfg_key_bgp_daemon_ipv6_only(char *, char *, char *); extern int cfg_key_bgp_daemon_id(char *, char *, char *); extern int cfg_key_bgp_daemon_as(char *, char *, char *); extern int cfg_key_bgp_daemon_port(char *, char *, char *); extern int cfg_key_bgp_daemon_rp_ebpf_prog(char *, char *, char *); extern int cfg_key_bgp_daemon_ip_precedence(char *, char *, char *); extern int cfg_key_bgp_daemon_allow_file(char *, char *, char *); extern int cfg_key_bgp_daemon_add_path_ignore(char *, char *, char *); extern int cfg_key_bgp_daemon_tag_map(char *, char *, char *); extern int cfg_key_bgp_daemon_aspath_radius(char *, char *, char *); extern int cfg_key_bgp_daemon_stdcomm_pattern(char *, char *, char *); extern int cfg_key_bgp_daemon_extcomm_pattern(char *, char *, char *); extern int cfg_key_bgp_daemon_lrgcomm_pattern(char *, char *, char *); extern int cfg_key_bgp_daemon_stdcomm_pattern_to_asn(char *, char *, char *); extern int cfg_key_bgp_daemon_lrgcomm_pattern_to_asn(char *, char *, char *); extern int cfg_key_bgp_blackhole_stdcomm_list(char *, char *, char *); extern int cfg_key_bgp_daemon_peer_src_as_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_std_comm_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_ext_comm_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_lrg_comm_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_as_path_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_local_pref_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_med_type(char *, char *, char *); extern int cfg_key_bgp_daemon_src_roa_type(char *, char *, char *); extern int cfg_key_bgp_daemon_peer_as_skip_subas(char *, char *, char *); extern int cfg_key_bgp_daemon_peer_src_as_map(char *, char *, char *); extern int cfg_key_bgp_daemon_src_local_pref_map(char *, char *, char *); extern int cfg_key_bgp_daemon_src_med_map(char *, char *, char *); extern int cfg_key_bgp_daemon_to_xflow_agent_map(char *, char *, char *); extern int cfg_key_bgp_daemon_follow_default(char *, char *, char *); extern int cfg_key_bgp_daemon_follow_nexthop(char *, char *, char *); extern int cfg_key_bgp_daemon_follow_nexthop_external(char *, char *, char *); extern int cfg_key_bgp_daemon_disable_router_id_check(char *, char *, char *); extern int cfg_key_bgp_daemon_neighbors_file(char *, char *, char *); extern int cfg_key_bgp_daemon_md5_file(char *, char *, char *); extern int cfg_key_bgp_daemon_table_peer_buckets(char *, char *, char *); extern int cfg_key_bgp_daemon_table_per_peer_buckets(char *, char *, char *); extern int cfg_key_bgp_daemon_table_attr_hash_buckets(char *, char *, char *); extern int cfg_key_bgp_daemon_table_per_peer_hash(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_output(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_file(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_latest_file(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_avro_schema_file(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_refresh_time(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_time_slots(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_host(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_vhost(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_user(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_passwd(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_exchange(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_exchange_type(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_routing_key(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_frame_max(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_broker_host(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_broker_port(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_topic(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_topic_rr(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_partition(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_partition_key(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_config_file(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_kafka_avro_schema_registry(char *, char *, char *); extern int cfg_key_bgp_daemon_table_dump_workers(char *, char *, char *); extern int cfg_key_bgp_daemon_batch(char *, char *, char *); extern int cfg_key_bgp_daemon_batch_interval(char *, char *, char *); extern int cfg_key_bgp_daemon_pipe_size(char *, char *, char *); extern int cfg_key_bgp_lg(char *, char *, char *); extern int cfg_key_bgp_lg_ip(char *, char *, char *); extern int cfg_key_bgp_lg_port(char *, char *, char *); extern int cfg_key_bgp_lg_threads(char *, char *, char *); extern int cfg_key_bgp_lg_user(char *, char *, char *); extern int cfg_key_bgp_lg_passwd(char *, char *, char *); extern int cfg_key_bgp_xconnect_map(char *, char *, char *); extern int cfg_key_bmp_daemon(char *, char *, char *); extern int cfg_key_bmp_daemon_ip(char *, char *, char *); extern int cfg_key_bmp_daemon_interface(char *, char *, char *); extern int cfg_key_bmp_daemon_ipv6_only(char *, char *, char *); extern int cfg_key_bmp_daemon_port(char *, char *, char *); extern int cfg_key_bmp_daemon_rp_ebpf_prog(char *, char *, char *); extern int cfg_key_bmp_daemon_tag_map(char *, char *, char *); extern int cfg_key_bmp_daemon_pipe_size(char *, char *, char *); extern int cfg_key_bmp_daemon_max_peers(char *, char *, char *); extern int cfg_key_bmp_daemon_allow_file(char *, char *, char *); extern int cfg_key_bmp_daemon_ip_precedence(char *, char *, char *); extern int cfg_key_bmp_daemon_batch(char *, char *, char *); extern int cfg_key_bmp_daemon_batch_interval(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_output(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_file(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_avro_schema_file(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_host(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_vhost(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_user(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_passwd(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_exchange(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_exchange_type(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_routing_key(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_frame_max(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_amqp_retry(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_broker_host(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_broker_port(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_topic(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_topic_rr(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_partition(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_partition_key(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_retry(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_config_file(char *, char *, char *); extern int cfg_key_bmp_daemon_msglog_kafka_avro_schema_registry(char *, char *, char *); extern int cfg_key_bmp_daemon_table_peer_buckets(char *, char *, char *); extern int cfg_key_bmp_daemon_table_per_peer_buckets(char *, char *, char *); extern int cfg_key_bmp_daemon_table_attr_hash_buckets(char *, char *, char *); extern int cfg_key_bmp_daemon_table_per_peer_hash(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_output(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_workers(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_file(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_avro_schema_file(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_latest_file(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_refresh_time(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_time_slots(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_host(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_vhost(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_user(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_passwd(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_exchange(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_exchange_type(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_routing_key(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_routing_key_rr(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_persistent_msg(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_frame_max(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_amqp_heartbeat_interval(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_broker_host(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_broker_port(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_topic(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_topic_rr(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_partition(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_partition_key(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_config_file(char *, char *, char *); extern int cfg_key_bmp_daemon_dump_kafka_avro_schema_registry(char *, char *, char *); extern int cfg_key_nfacctd_bmp_daemon_parse_proxy_header(char *, char *, char *); extern int cfg_key_nfacctd_flow_to_rd_map(char *, char *, char *); extern int cfg_key_nfacctd_isis(char *, char *, char *); extern int cfg_key_nfacctd_isis_ip(char *, char *, char *); extern int cfg_key_nfacctd_isis_net(char *, char *, char *); extern int cfg_key_nfacctd_isis_iface(char *, char *, char *); extern int cfg_key_nfacctd_isis_mtu(char *, char *, char *); extern int cfg_key_nfacctd_isis_msglog(char *, char *, char *); extern int cfg_key_rpki_roas_file(char *, char *, char *); extern int cfg_key_rpki_rtr_cache(char *, char *, char *); extern int cfg_key_rpki_rtr_cache_version(char *, char *, char *); extern int cfg_key_rpki_rtr_cache_pipe_size(char *, char *, char *); extern int cfg_key_rpki_rtr_cache_ip_precedence(char *, char *, char *); extern int cfg_key_igp_daemon_map(char *, char *, char *); extern int cfg_key_igp_daemon_map_msglog(char *, char *, char *); extern int cfg_key_geoip_ipv4_file(char *, char *, char *); extern int cfg_key_geoip_ipv6_file(char *, char *, char *); extern int cfg_key_geoipv2_file(char *, char *, char *); extern int cfg_key_uacctd_group(char *, char *, char *); extern int cfg_key_uacctd_nl_size(char *, char *, char *); extern int cfg_key_uacctd_threshold(char *, char *, char *); extern int cfg_key_tunnel_0(char *, char *, char *); extern int cfg_key_dump_max_writers(char *, char *, char *); extern int cfg_key_tmp_asa_bi_flow(char *, char *, char *); extern int cfg_key_tmp_bgp_lookup_compare_ports(char *, char *, char *); extern int cfg_key_tmp_bgp_daemon_route_refresh(char *, char *, char *); extern int cfg_key_tmp_bgp_daemon_origin_type_int(char *, char *, char *); extern int cfg_key_tmp_telemetry_daemon_udp_notif_legacy(char *, char *, char *); extern int cfg_key_tmp_telemetry_decode_cisco_v1_json_string(char *, char *, char *); extern void parse_time(char *, char *, int *, int *); extern void cfg_get_primitive_index_value(u_int64_t, u_int64_t *, u_int64_t *); extern void cfg_set_primitive_index_value(u_int64_t, u_int64_t , u_int64_t *); extern void cfg_set_aggregate(char *, u_int64_t [], u_int64_t, char *); #endif //CFG_HANDLER_H pmacct-1.7.8/src/log.h0000644000175000017500000000512514354105275013536 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef LOG_H #define LOG_H /* includes */ #include #include /* defines */ #define LOGSTRLEN LONGSRVBUFLEN struct _facility_map { char string[10]; int num; }; static const struct _facility_map facility_map[] = { {"auth", LOG_AUTH}, {"mail", LOG_MAIL}, {"daemon", LOG_DAEMON}, {"kern", LOG_KERN}, {"user", LOG_USER}, {"local0", LOG_LOCAL0}, {"local1", LOG_LOCAL1}, {"local2", LOG_LOCAL2}, {"local3", LOG_LOCAL3}, {"local4", LOG_LOCAL4}, {"local5", LOG_LOCAL5}, {"local6", LOG_LOCAL6}, {"local7", LOG_LOCAL7}, {"-1", -1}, }; struct log_notification { time_t stamp; u_int8_t knob; int timeout; }; struct _log_notifications { struct log_notification snaplen_issue; struct log_notification max_classifiers; struct log_notification bgp_peers_throttling; struct log_notification bgp_peers_limit; struct log_notification bmp_peers_throttling; struct log_notification bmp_peers_limit; struct log_notification geoip_ipv4_file_null; struct log_notification geoip_ipv6_file_null; #if defined (WITH_NDPI) struct log_notification ndpi_cache_full; struct log_notification ndpi_tmp_frag_warn; #endif struct log_notification tee_plugin_cant_bridge_af; }; /* prototypes */ extern void Log(short int, char *, ...) #ifdef __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; extern int parse_log_facility(const char *); extern void log_notification_init(struct log_notification *); extern void log_notifications_init(struct _log_notifications *); extern int log_notification_set(struct log_notification *, time_t, int); extern int log_notification_unset(struct log_notification *); extern int log_notification_isset(struct log_notification *, time_t); /* global vars */ extern struct _log_notifications log_notifications; #endif //LOG_H pmacct-1.7.8/src/setproctitle.h0000644000175000017500000000254414354105275015500 0ustar paolopaolo/* * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * * $Id$ */ #ifdef __hpux # undef SPT_TYPE // # define SPT_TYPE SPT_PSTAT #endif #ifdef _AIX3 # define SPT_PADCHAR '\0' #endif #ifdef AIX # define SPT_PADCHAR '\0' #endif #if defined (__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN #endif #if defined(__linux__) # undef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV # define SPT_PADCHAR '\0' #endif #if !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) # define SPT_TYPE SPT_PSTAT #endif #if defined(HAVE_SETPROCTITLE) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN #endif char pmacctd_globstr[] = "pmacctd\0"; char nfacctd_globstr[] = "nfacctd\0"; char sfacctd_globstr[] = "sfacctd\0"; char uacctd_globstr[] = "uacctd\0"; char pmtele_globstr[] = "pmtelemetryd\0"; char pmbgpd_globstr[] = "pmbgpd\0"; char pmbmpd_globstr[] = "pmbmpd\0"; pmacct-1.7.8/src/plugin_cmn_custom.c0000644000175000017500000001002014354105275016463 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2019 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Includes */ #include "pmacct.h" #include "plugin_cmn_custom.h" /* global variables */ struct pm_custom_output custom_print_plugin; /* Functions */ void custom_output_setup(char *custom_lib, char *custom_cfg_file, struct pm_custom_output *custom_output) { #ifdef WITH_DLOPEN const char *error; Log(LOG_INFO, "INFO ( %s/%s ): Loading custom output from: %s\n", config.name, config.type, custom_lib); custom_output->lib_handle = dlopen(custom_lib, RTLD_LAZY); if (!custom_output->lib_handle) { Log(LOG_ERR, "ERROR ( %s/%s ): Could not load custom output library %s: %s\n", config.name, config.type, custom_lib, dlerror()); exit_gracefully(1); } /* ie. to init internal structures */ custom_output->plugin_init = dlsym(custom_output->lib_handle, "plugin_init"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. to destroy internal structures */ custom_output->plugin_destroy = dlsym(custom_output->lib_handle, "plugin_destroy"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. at purge time, given input data, to compose an object to flush */ custom_output->print = dlsym(custom_output->lib_handle, "print"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. at purge time initialize output backend (ie. open file, connect to broker) and optionally perform other start actions (ie. write start marker) */ custom_output->output_init = dlsym(custom_output->lib_handle, "output_init"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. at purge time close output backend (ie. close file, disconnect from broker) and optionally perform other start actions (ie. write end marker) */ custom_output->output_close = dlsym(custom_output->lib_handle, "output_close"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. at purge time write data to the backend and optionally perform other actions (ie. flushing buffers, if buffered output) */ custom_output->output_flush = dlsym(custom_output->lib_handle, "output_flush"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } /* ie. nicely return error messages back */ custom_output->get_error_text = dlsym(custom_output->lib_handle, "get_error_text"); if ((error = dlerror()) != NULL) { Log(LOG_ERR, "ERROR ( %s/%s ): %s from %s\n", config.name, config.type, error, custom_lib); exit_gracefully(1); } if (0 != custom_output->plugin_init(custom_cfg_file)) { Log(LOG_ERR, "ERROR ( %s/%s ): Initialisation of custom output failed: %s\n", config.name, config.type, custom_output->get_error_text()); exit_gracefully(1); } #endif } pmacct-1.7.8/src/thread_pool.c0000644000175000017500000001637514354105275015261 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2021 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Original thread pool implementation for pmacct is: Copyright (C) 2006 Francois Deppierraz */ /* includes */ #include "pmacct.h" #include "thread_pool.h" thread_pool_t *allocate_thread_pool(int count) { int i, rc; thread_pool_t *pool; thread_pool_item_t *worker; pthread_attr_t attr, *attr_ptr = NULL; size_t default_stack_size; if (count <= 0) { Log(LOG_WARNING, "WARN ( %s/%s ): allocate_thread_pool() requires count > 0\n", config.name, config.type); return NULL; } // Allocate pool pool = malloc(sizeof(thread_pool_t)); assert(pool); memset(pool, 0, sizeof(thread_pool_t)); // Allocate pool mutex pool->mutex = malloc(sizeof(pthread_mutex_t)); assert(pool->mutex); pthread_mutex_init(pool->mutex, NULL); // Allocate pool condition pool->cond = malloc(sizeof(pthread_cond_t)); assert(pool->cond); pthread_cond_init(pool->cond, NULL); pool->count = count; /* Threads lists */ pool->list = malloc(count * sizeof(struct thread_pool_item_t *)); memset(pool->list, 0, count * sizeof(struct thread_pool_item_t *)); pool->free_list = NULL; for (i = 0; i < pool->count; i++) { worker = malloc(sizeof(thread_pool_item_t)); assert(worker); worker->id = (i + 1); worker->owner = pool; worker->mutex = malloc(sizeof(pthread_mutex_t)); assert(worker->mutex); pthread_mutex_init(worker->mutex, NULL); worker->cond = malloc(sizeof(pthread_cond_t)); assert(worker->cond); pthread_cond_init(worker->cond, NULL); /* Default state */ worker->go = ERR; worker->quit = FALSE; worker->usage = FALSE; /* Create the thread */ worker->thread = malloc(sizeof(pthread_t)); assert(worker->thread); rc = pthread_attr_init(&attr); if (rc) { Log(LOG_ERR, "ERROR ( %s/%s ): pthread_attr_init(): %s\n", config.name, config.type, strerror(rc)); deallocate_thread_pool(&pool); return NULL; } if (config.thread_stack && config.thread_stack < MIN_TH_STACK_SIZE) { config.thread_stack = MIN_TH_STACK_SIZE; Log(LOG_INFO, "INFO ( %s/%s ): thread_stack re-defined to minimum: %u\n", config.name, config.type, MIN_TH_STACK_SIZE); } /* Thread stack handling: * if thread_stack is defined, apply it; * if thread_stack is found not good but system default is good (ie. equal or greater than MIN_TH_STACK_SIZE), apply system default; * if system default is not good (ie. less than MIN_TH_STACK_SIZE), apply MIN_TH_STACK_SIZE; * if nothing of the above works bail out. */ pthread_attr_getstacksize(&attr, &default_stack_size); if (config.thread_stack) { rc = pthread_attr_setstacksize(&attr, config.thread_stack); if (rc && default_stack_size >= MIN_TH_STACK_SIZE) rc = pthread_attr_setstacksize(&attr, default_stack_size); } if (rc || default_stack_size < MIN_TH_STACK_SIZE) rc = pthread_attr_setstacksize(&attr, MIN_TH_STACK_SIZE); if (!rc) { size_t confd_stack_size; attr_ptr = &attr; pthread_attr_getstacksize(&attr, &confd_stack_size); if (confd_stack_size != config.thread_stack && confd_stack_size != default_stack_size) Log(LOG_INFO, "INFO ( %s/%s ): pthread_attr_setstacksize(): %lu\n", config.name, config.type, (unsigned long)confd_stack_size); } else { Log(LOG_ERR, "ERROR ( %s/%s ): pthread_attr_setstacksize(): %s\n", config.name, config.type, strerror(rc)); deallocate_thread_pool(&pool); return NULL; } rc = pthread_create(worker->thread, attr_ptr, thread_runner, worker); if (rc) { Log(LOG_ERR, "ERROR ( %s/%s ): pthread_create(): %s\n", config.name, config.type, strerror(rc)); deallocate_thread_pool(&pool); return NULL; } // Wait for thread init pthread_mutex_lock(worker->mutex); while (worker->go != 0) pthread_cond_wait(worker->cond, worker->mutex); pthread_mutex_unlock(worker->mutex); // Add to lists worker->next = pool->free_list; pool->free_list = worker; pool->list[i] = worker; } return pool; } void deallocate_thread_pool(thread_pool_t **pool) { thread_pool_t *pool_ptr = NULL; thread_pool_item_t *worker = NULL; int i = 0; if (!pool || !(*pool)) return; pool_ptr = (*pool); /* Let's give send_to_pool() some advantage in case it was just called */ sleep(1); for (i = 0; i < pool_ptr->count; i++) { worker = pool_ptr->list[i]; /* Let him finish */ pthread_mutex_lock(worker->mutex); worker->go = TRUE; worker->quit = TRUE; pthread_mutex_unlock(worker->mutex); pthread_cond_signal(worker->cond); pthread_join((*worker->thread), NULL); /* Free memory */ pthread_mutex_destroy(worker->mutex); free(worker->mutex); pthread_cond_destroy(worker->cond); free(worker->cond); free(worker->thread); free(worker); } if (pool_ptr->mutex) free(pool_ptr->mutex); if (pool_ptr->cond) free(pool_ptr->cond); free((*pool)); (*pool) = NULL; } void *thread_runner(void *arg) { thread_pool_item_t *self = (thread_pool_item_t *) arg; int ret = FALSE; pthread_mutex_lock(self->mutex); self->go = FALSE; pthread_cond_signal(self->cond); pthread_mutex_unlock(self->mutex); while (!self->quit) { /* Wait for some work */ pthread_mutex_lock(self->mutex); while (!self->go) { pthread_cond_wait(self->cond, self->mutex); } /* Pre-flight check in case we were unlocked by deallocate_thread_pool() */ if (self->quit) break; /* Doing our job */ ret = (*self->function)(self->data); if (ret == ERR) self->quit = TRUE; self->usage++; self->go = FALSE; pthread_mutex_unlock(self->mutex); pthread_mutex_lock(self->owner->mutex); self->next = self->owner->free_list; self->owner->free_list = self; pthread_cond_signal(self->owner->cond); pthread_mutex_unlock(self->owner->mutex); } pthread_exit(NULL); } void send_to_pool(thread_pool_t *pool, void *function, void *data) { thread_pool_item_t *worker; pthread_mutex_lock(pool->mutex); while (pool->free_list == NULL) { pthread_cond_wait(pool->cond, pool->mutex); } /* Get a free thread */ worker = pool->free_list; pool->free_list = worker->next; pthread_mutex_unlock(pool->mutex); /* Give it some work to do */ pthread_mutex_lock(worker->mutex); worker->function = function; worker->data = data; worker->go = TRUE; pthread_cond_signal(worker->cond); pthread_mutex_unlock(worker->mutex); } pmacct-1.7.8/src/pretag_handlers.c0000644000175000017500000045671114354105275016125 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pmacct.h" #include "bgp/bgp_packet.h" #include "bgp/bgp.h" #include "nfacctd.h" #include "sflow.h" #include "sfacctd.h" #include "pretag_handlers.h" #include "net_aggr.h" #include "bgp/bgp.h" #include "rpki/rpki.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "pkt_handlers.h" int PT_map_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct host_addr a; char *endptr = NULL, *incptr; pm_id_t j = 0, z = 0; int x, inc = 0, len = 0; e->id = 0; e->flags = FALSE; /* If we parse a bgp_agent_map and spot a '.' within the string let's check if we are given a valid IPv4 address */ if (acct_type == MAP_BGP_TO_XFLOW_AGENT && strchr(value, '.')) { memset(&a, 0, sizeof(a)); str_to_addr(value, &a); if (a.family == AF_INET) j = a.address.ipv4.s_addr; else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] ID does not appear to be a valid IPv4 address.\n", config.name, config.type, filename); return TRUE; } } /* If we parse a bgp_agent_map and spot a ':' within the string let's check if we are given a valid IPv6 address */ else if (acct_type == MAP_BGP_TO_XFLOW_AGENT && strchr(value, ':')) { memset(&a, 0, sizeof(a)); str_to_addr(value, &a); if (a.family == AF_INET6) { ip6_addr_32bit_cpy(&j, &a.address.ipv6, 0, 0, 1); ip6_addr_32bit_cpy(&z, &a.address.ipv6, 0, 2, 3); e->flags = BTA_MAP_RCODE_ID_ID2; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] ID does not appear to be a valid IPv6 address.\n", config.name, config.type, filename); return TRUE; } } else if (acct_type == MAP_FLOW_TO_RD && strchr(value, ':')) { rd_t rd; bgp_str2rd(&rd, value); memcpy(&j, &rd, sizeof(rd)); } /* If we spot the word "bgp", let's check this is a map that supports it */ else if ((acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_SRC_LOCAL_PREF || acct_type == MAP_BGP_SRC_MED) && !strncmp(value, "bgp", strlen("bgp"))) { e->flags = BPAS_MAP_RCODE_BGP; } else { if ((incptr = strstr(value, "++"))) { inc = TRUE; *incptr = '\0'; } len = strlen(value); for (x = 0; x < len; x++) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid set_tag/id specified (non-digit chars).\n", config.name, config.type, filename); return TRUE; } } j = strtoull(value, &endptr, 10); if (j > UINT64_MAX) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid set_tag/id specified (too big).\n", config.name, config.type, filename); return TRUE; } } e->id = j; if (z) e->id2 = z; if (inc) e->id_inc = TRUE; if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM || acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE) { for (x = 0; e->set_func[x]; x++) { if (e->set_func_type[x] == PRETAG_SET_TAG) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'set_tag' (id) clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } e->set_func[x] = pretag_id_handler; e->set_func_type[x] = PRETAG_SET_TAG; } return FALSE; } int PT_map_id2_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { char *endptr = NULL, *incptr; pm_id_t j; int x, inc = 0, len = 0; if ((incptr = strstr(value, "++"))) { inc = TRUE; *incptr = '\0'; } len = strlen(value); for (x = 0; x < len; x++) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid set_tag2/id2 specified (non-digit chars).\n", config.name, config.type, filename); return TRUE; } } j = strtoull(value, &endptr, 10); if (j > UINT64_MAX) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid set_tag2/id2 specified (too big).\n", config.name, config.type, filename); return TRUE; } e->id2 = j; if (inc) e->id2_inc = TRUE; if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM) { for (x = 0; e->set_func[x]; x++) { if (e->set_func_type[x] == PRETAG_SET_TAG2) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'set_tag2' (id2) clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } e->set_func[x] = pretag_id2_handler; e->set_func_type[x] = PRETAG_SET_TAG2; } return FALSE; } int PT_map_label_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x, len; // XXX: isprint check? len = strlen(value); /* light validation for this case */ if (config.pretag_label_encode_as_map) { char *value_copy, *token; char *map_key, *map_value; value_copy = strdup(value); if (value_copy) { for (token = strtok(value_copy, DEFAULT_SEP); token; token = strtok(NULL, DEFAULT_SEP)) { map_key = token; map_value = strchr(token, PRETAG_LABEL_KV_SEP_INT); if (map_value) { (*map_value) = '\0'; map_value++; if (!strlen(map_key) || !strlen(map_value)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Missing pretag_label_encode_as_map key or value.\n", config.name, config.type, filename); free(value_copy); return TRUE; } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Missing pretag_label_encode_as_map separator.\n", config.name, config.type, filename); free(value_copy); return TRUE; } } free(value_copy); } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] PT_map_label_handler() failed strdup()\n", config.name, config.type, filename); return TRUE; } } if (pretag_malloc_label(&e->label, len + 1 /* null */)) return TRUE; strcpy(e->label.val, value); e->label.len = len; e->label.val[e->label.len] = '\0'; if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM || acct_type == ACCT_PMBGP || acct_type == ACCT_PMBMP || acct_type == ACCT_PMTELE) { for (x = 0; e->set_func[x]; x++) { if (e->set_func_type[x] == PRETAG_SET_LABEL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'set_label' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } e->set_func[x] = pretag_label_handler; e->set_func_type[x] = PRETAG_SET_LABEL; } return FALSE; } int PT_map_ip_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; if (!str_to_addr_mask(value, &e->key.agent_ip.a, &e->key.agent_mask)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad IP address or prefix '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IP) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'ip' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } e->func[x] = pretag_dummy_ip_handler; if (e->func[x]) e->func_type[x] = PRETAG_IP; return FALSE; } int PT_map_input_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, len; char *endptr; if (acct_type == MAP_SAMPLING) sampling_map_caching = FALSE; if (acct_type == MAP_BGP_TO_XFLOW_AGENT) bta_map_caching = FALSE; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.input.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'in' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } e->key.input.n = strtoul(value, &endptr, 10); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IN_IFACE) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'input' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_input_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_input_handler; else if (config.acct_type == ACCT_PM) e->func[x] = PM_pretag_input_handler; if (e->func[x]) e->func_type[x] = PRETAG_IN_IFACE; return FALSE; } int PT_map_output_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, len; char *endptr; if (acct_type == MAP_SAMPLING) sampling_map_caching = FALSE; if (acct_type == MAP_BGP_TO_XFLOW_AGENT) bta_map_caching = FALSE; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.output.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'out' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } e->key.output.n = strtoul(value, &endptr, 10); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_OUT_IFACE) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'output' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_output_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_output_handler; else if (config.acct_type == ACCT_PM) e->func[x] = PM_pretag_output_handler; if (e->func[x]) e->func_type[x] = PRETAG_OUT_IFACE; return FALSE; } int PT_map_nexthop_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.nexthop.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (!str_to_addr(value, &e->key.nexthop.a)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad nexthop address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_NEXTHOP) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'nexthop' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_nexthop_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_nexthop_handler; if (e->func[x]) e->func_type[x] = PRETAG_NEXTHOP; return FALSE; } int PT_map_bgp_nexthop_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, have_bgp = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.bgp_nexthop.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (!str_to_addr(value, &e->key.bgp_nexthop.a)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad BGP nexthop address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_BGP_NEXTHOP) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'bgp_nexthop' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_net & NF_NET_BGP) { e->func[x] = pretag_bgp_bgp_nexthop_handler; have_bgp = TRUE; e->func_type[x] = PRETAG_BGP_NEXTHOP; x++; } /* XXX: IGP? */ if (config.nfacctd_net & NF_NET_KEEP && config.acct_type == ACCT_NF) { e->func[x] = pretag_bgp_nexthop_handler; e->func_type[x] = PRETAG_BGP_NEXTHOP; return FALSE; } else if (config.nfacctd_net & NF_NET_KEEP && config.acct_type == ACCT_SF) { e->func[x] = SF_pretag_bgp_nexthop_handler; e->func_type[x] = PRETAG_BGP_NEXTHOP; return FALSE; } if (have_bgp) return FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'bgp_nexthop' is not supported when a 'networks_file' is specified or by the 'pmacctd' daemon.\n", config.name, config.type, filename); return TRUE; } int BPAS_map_bgp_nexthop_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.bgp_nexthop.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (!str_to_addr(value, &e->key.bgp_nexthop.a)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad BGP nexthop address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++); if (config.bgp_daemon) { e->func[x] = BPAS_bgp_nexthop_handler; e->func_type[x] = PRETAG_BGP_NEXTHOP; } return FALSE; } int BPAS_map_bgp_peer_dst_as_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0; char *endptr; e->key.peer_dst_as.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.peer_dst_as.n = tmp; for (x = 0; e->func[x]; x++); if (config.bgp_daemon) { e->func[x] = BPAS_bgp_peer_dst_as_handler; e->func_type[x] = PRETAG_BGP_NEXTHOP; } return FALSE; } int BITR_map_mpls_label_bottom_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0; char *endptr; e->key.mpls_label_bottom.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.mpls_label_bottom.n = tmp; for (x = 0; e->func[x]; x++); /* Currently supported only in nfacctd */ if (config.acct_type == ACCT_NF) e->func[x] = BITR_mpls_label_bottom_handler; if (e->func[x]) e->func_type[x] = PRETAG_MPLS_LABEL_BOTTOM; return FALSE; } int BITR_map_mpls_vpn_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; char *endptr; e->key.mpls_vpn_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.mpls_vpn_id.n = strtoul(value, &endptr, 10); if (!e->key.mpls_vpn_id.n) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad MPLS VPN ID value '%u'.\n", config.name, config.type, filename, e->key.mpls_vpn_id.n); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_MPLS_VPN_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'mpls_vpn_id' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = BITR_mpls_vpn_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_MPLS_VPN_ID; return FALSE; } int PT_map_engine_type_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, j, len; e->key.engine_type.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'engine_type' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } j = atoi(value); if (j > 255) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'engine_type' value (range: 0 >= value > 256).\n", config.name, config.type, filename); return TRUE; } e->key.engine_type.n = j; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_ENGINE_TYPE) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'engine_type' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_engine_type_handler; if (e->func[x]) e->func_type[x] = PRETAG_ENGINE_TYPE; return FALSE; } int PT_map_engine_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, len; char *endptr; e->key.engine_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'engine_id' or 'source_id' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } e->key.engine_id.n = strtoul(value, &endptr, 10); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_ENGINE_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'engine_id' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_engine_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_ENGINE_ID; return FALSE; } int PT_map_filter_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct pm_pcap_device dev; bpf_u_int32 localnet, netmask; /* pcap library stuff */ char errbuf[PCAP_ERRBUF_SIZE]; int x; if (acct_type == MAP_BGP_TO_XFLOW_AGENT) { if (strncmp(value, "ip", 2) && strncmp(value, "ip6", 3) && strncmp(value, "vlan and ip", 11) && strncmp(value, "vlan and ip6", 12)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bgp_agent_map filter supports only 'ip', 'ip6', 'vlan and ip' and 'vlan and ip6' keywords\n", config.name, config.type, filename); return TRUE; } } memset(&dev, 0, sizeof(struct pm_pcap_device)); // XXX: fix if multiple interfaces if (devices.list[0].dev_desc) dev.link_type = pcap_datalink(devices.list[0].dev_desc); else if (config.uacctd_group) dev.link_type = DLT_RAW; else dev.link_type = 1; dev.dev_desc = pcap_open_dead(dev.link_type, 128); /* snaplen=eth_header+pm_iphdr+pm_tlhdr */ pcap_lookupnet(config.pcap_if, &localnet, &netmask, errbuf); if (pcap_compile(dev.dev_desc, &e->key.filter, value, 0, netmask) < 0) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] malformed filter: %s\n", config.name, config.type, filename, pcap_geterr(dev.dev_desc)); return TRUE; } pcap_close(dev.dev_desc); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_FILTER) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'filter' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } e->func[x] = pretag_filter_handler; if (e->func[x]) e->func_type[x] = PRETAG_FILTER; req->bpf_filter = TRUE; return FALSE; } int PT_map_agent_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.agent_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.agent_id.n = atoi(value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SF_AGENTID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'agent_id' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_agent_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_SF_AGENTID; return FALSE; } int PT_map_flowset_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.flowset_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.flowset_id.n = htons(atoi(value)); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_FLOWSET_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'flowset_id' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_flowset_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_FLOWSET_ID; return FALSE; } int PT_map_sample_type_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { char *token = NULL; u_int32_t tmp; int x = 0; e->key.sample_type.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (acct_type == ACCT_SF && strchr(value, ':')) { while ((token = extract_token(&value, ':'))) { switch (x) { case 0: tmp = atoi(token); if (tmp > 1048575) { // 2^20-1: 20 bit Enterprise value Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid sFlow 'sample_type' value.\n", config.name, config.type, filename); return TRUE; } e->key.sample_type.n = tmp; e->key.sample_type.n <<= 12; break; case 1: tmp = atoi(token); if (tmp > 4095) { // 2^12-1: 12 bit Format value Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid sFlow 'sample_type' value.\n", config.name, config.type, filename); return TRUE; } e->key.sample_type.n |= tmp; break; default: Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid sFlow 'sample_type' value.\n", config.name, config.type, filename); return TRUE; } x++; } } else if (acct_type == ACCT_NF) { if (!strncmp(value, "flow-ipv4", strlen("flow-ipv4"))) { e->key.sample_type.n = PM_FTYPE_IPV4; } else if (!strncmp(value, "flow-ipv6", strlen("flow-ipv6"))) { e->key.sample_type.n = PM_FTYPE_IPV6; } else if (!strncmp(value, "flow", strlen("flow"))) { e->key.sample_type.n = PM_FTYPE_TRAFFIC; } else if (!strncmp(value, "flow-mpls-ipv4", strlen("flow-mpls-ipv4"))) { e->key.sample_type.n = PM_FTYPE_MPLS_IPV4; } else if (!strncmp(value, "flow-mpls-ipv6", strlen("flow-mpls-ipv6"))) { e->key.sample_type.n = PM_FTYPE_MPLS_IPV6; } else if (!strncmp(value, "event", strlen("event"))) { e->key.sample_type.n = NF9_FTYPE_EVENT; } else if (!strncmp(value, "option", strlen("option"))) { e->key.sample_type.n = NF9_FTYPE_OPTION; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid NetFlow/IPFIX 'sample_type' value.\n", config.name, config.type, filename); return TRUE; } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid 'sample_type' value.\n", config.name, config.type, filename); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SAMPLE_TYPE) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'sample_type' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_sample_type_handler; else if (config.acct_type == ACCT_NF) e->func[x] = pretag_sample_type_handler; if (e->func[x]) e->func_type[x] = PRETAG_SAMPLE_TYPE; return FALSE; } int PT_map_is_bi_flow_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int value_tf, x = 0; e->key.is_bi_flow.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); value_tf = parse_truefalse(value); if (value_tf < 0) { return ERR; } e->key.is_bi_flow.n = value_tf; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IS_BI_FLOW) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'is_bi_flow' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_is_bi_flow_handler; return FALSE; } int PT_map_is_nsel_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int value_tf, x = 0; e->key.is_nsel.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); value_tf = parse_truefalse(value); if (value_tf < 0) { return ERR; } e->key.is_nsel.n = value_tf; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IS_NSEL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'is_nsel' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_is_nsel_handler; return FALSE; } int PT_map_is_nel_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int value_tf, x = 0; e->key.is_nel.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); value_tf = parse_truefalse(value); if (value_tf < 0) { return ERR; } e->key.is_nel.n = value_tf; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IS_NEL) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'is_nel' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_is_nel_handler; return FALSE; } int PT_map_direction_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.direction.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.direction.n = atoi(value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_DIRECTION) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'direction' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_direction_handler; else if (config.acct_type == ACCT_NF) e->func[x] = pretag_direction_handler; else if (config.acct_type == ACCT_PM) e->func[x] = PM_pretag_direction_handler; if (e->func[x]) e->func_type[x] = PRETAG_DIRECTION; return FALSE; } int PT_map_nat_event_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.nat_event.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.nat_event.n = atoi(value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_NAT_EVENT) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'nat_event' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_nat_event_handler; if (e->func[x]) e->func_type[x] = PRETAG_NAT_EVENT; return FALSE; } int PT_map_src_as_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0, have_bgp = 0; char *endptr; e->key.src_as.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.src_as.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_AS) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_as' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_bgp_src_as_handler; e->func_type[x] = PRETAG_SRC_AS; have_bgp = TRUE; x++; } if ((config.nfacctd_as & NF_AS_NEW || config.acct_type == ACCT_PM) && config.networks_file) { req->bpf_filter = TRUE; e->func[x] = PM_pretag_src_as_handler; e->func_type[x] = PRETAG_SRC_AS; return FALSE; } else if (config.nfacctd_as & NF_AS_KEEP && config.acct_type == ACCT_NF) { e->func[x] = pretag_src_as_handler; e->func_type[x] = PRETAG_SRC_AS; return FALSE; } else if (config.nfacctd_as & NF_AS_KEEP && config.acct_type == ACCT_SF) { e->func[x] = SF_pretag_src_as_handler; e->func_type[x] = PRETAG_SRC_AS; return FALSE; } if (have_bgp) return FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'src_as' requires either 'networks_file' or '%s_as: false' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_dst_as_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0, have_bgp = 0; char *endptr; e->key.dst_as.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.dst_as.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_DST_AS) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'dst_as' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_bgp_dst_as_handler; e->func_type[x] = PRETAG_DST_AS; have_bgp = TRUE; x++; } if ((config.nfacctd_as & NF_AS_NEW || config.acct_type == ACCT_PM) && config.networks_file) { req->bpf_filter = TRUE; e->func[x] = PM_pretag_dst_as_handler; e->func_type[x] = PRETAG_DST_AS; return FALSE; } else if (config.nfacctd_as & NF_AS_KEEP && config.acct_type == ACCT_NF) { e->func[x] = pretag_dst_as_handler; e->func_type[x] = PRETAG_DST_AS; return FALSE; } else if (config.nfacctd_as & NF_AS_KEEP && config.acct_type == ACCT_SF) { e->func[x] = SF_pretag_dst_as_handler; e->func_type[x] = PRETAG_DST_AS; return FALSE; } if (have_bgp) return FALSE; Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'dst_as' requires either 'networks_file' or '%s_as: false' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_peer_src_as_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0; char *endptr; e->key.peer_src_as.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.peer_src_as.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_PEER_SRC_AS) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'peer_src_as' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_peer_src_as_handler; e->func_type[x] = PRETAG_PEER_SRC_AS; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'peer_src_as' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_peer_dst_as_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { as_t tmp; int x = 0; char *endptr; e->key.peer_dst_as.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.peer_dst_as.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_PEER_DST_AS) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'peer_dst_as' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_peer_dst_as_handler; e->func_type[x] = PRETAG_PEER_DST_AS; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'peer_dst_as' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_src_local_pref_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { u_int32_t tmp; int x = 0; char *endptr; e->key.src_local_pref.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.src_local_pref.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_LOCAL_PREF) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_local_pref' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_src_local_pref_handler; e->func_type[x] = PRETAG_SRC_LOCAL_PREF; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'src_local_pref' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_local_pref_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { u_int32_t tmp; int x = 0; char *endptr; e->key.local_pref.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = strtoul(value, &endptr, 10); e->key.local_pref.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_LOCAL_PREF) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'local_pref' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_local_pref_handler; e->func_type[x] = PRETAG_LOCAL_PREF; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'local_pref' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_src_roa_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.src_roa.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.src_roa.n = rpki_str2roa(value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_ROA) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_roa' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_src_roa_handler; e->func_type[x] = PRETAG_SRC_ROA; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'src_roa' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_dst_roa_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; e->key.dst_roa.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.dst_roa.n = rpki_str2roa(value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_DST_ROA) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'dst_roa' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP) { e->func[x] = pretag_dst_roa_handler; e->func_type[x] = PRETAG_DST_ROA; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'dst_roa' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_src_comms_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, idx = 0; char *token; memset(e->key.src_comms, 0, sizeof(e->key.src_comms)); /* Negation not supported here */ while ( (token = extract_token(&value, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { e->key.src_comms[idx] = malloc(MAX_BGP_STD_COMMS); if (!e->key.src_comms[idx]) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (PT_map_src_comms_handler). Exiting.\n", config.name, config.type, filename); exit_gracefully(1); } strlcpy(e->key.src_comms[idx], token, MAX_BGP_STD_COMMS); trim_spaces(e->key.src_comms[idx]); idx++; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_STD_COMM) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_comms' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP && e->key.src_comms[0]) { e->func[x] = pretag_src_comms_handler; e->func_type[x] = PRETAG_SRC_STD_COMM; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'src_comms' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_comms_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, idx = 0; char *token; memset(e->key.comms, 0, sizeof(e->key.comms)); /* Negation not supported here */ while ( (token = extract_token(&value, ',')) && idx < MAX_BGP_COMM_PATTERNS ) { e->key.comms[idx] = malloc(MAX_BGP_STD_COMMS); if (!e->key.comms[idx]) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (PT_map_comms_handler). Exiting.\n", config.name, config.type, filename); exit_gracefully(1); } strlcpy(e->key.comms[idx], token, MAX_BGP_STD_COMMS); trim_spaces(e->key.comms[idx]); idx++; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_STD_COMM) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'comms' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.nfacctd_as & NF_AS_BGP && e->key.comms[0]) { e->func[x] = pretag_comms_handler; e->func_type[x] = PRETAG_STD_COMM; return FALSE; } Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'comms' requires '%s_as_new: [ bgp | longest ]' to be specified.\n", config.name, config.type, filename, config.progname); return TRUE; } int PT_map_mpls_vpn_rd_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, ret; memset(&e->key.mpls_vpn_rd, 0, sizeof(e->key.mpls_vpn_rd)); e->key.mpls_vpn_rd.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); ret = bgp_str2rd(&e->key.mpls_vpn_rd.rd, value); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_MPLS_VPN_RD) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'mpls_vpn_rd' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (ret) { e->func[x] = pretag_mpls_vpn_rd_handler; e->func_type[x] = PRETAG_MPLS_VPN_RD; return FALSE; } else return TRUE; } int PT_map_mpls_pw_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; char *endptr; e->key.mpls_pw_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); e->key.mpls_pw_id.n = strtoul(value, &endptr, 10); for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_MPLS_PW_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'mpls_pw_id' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_mpls_pw_id_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_mpls_pw_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_MPLS_PW_ID; return FALSE; } int PT_map_src_mac_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.src_mac.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (string_etheraddr(value, e->key.src_mac.a)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad source MAC address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_MAC) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_mac' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_src_mac_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_src_mac_handler; if (e->func[x]) e->func_type[x] = PRETAG_SRC_MAC; return FALSE; } int PT_map_dst_mac_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.dst_mac.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (string_etheraddr(value, e->key.dst_mac.a)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad destination MAC address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_DST_MAC) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'dst_mac' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_dst_mac_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_dst_mac_handler; if (e->func[x]) e->func_type[x] = PRETAG_DST_MAC; return FALSE; } int PT_map_vlan_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int tmp, x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.vlan_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = atoi(value); if (tmp < 0 || tmp > 4096) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'vlan' need to be in the following range: 0 > value > 4096.\n", config.name, config.type, filename); return TRUE; } e->key.vlan_id.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_VLAN_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'vlan' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_vlan_id_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_vlan_id_handler; if (e->func[x]) e->func_type[x] = PRETAG_VLAN_ID; return FALSE; } int PT_map_cvlan_id_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int tmp, x = 0; e->key.cvlan_id.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = atoi(value); if (tmp < 0 || tmp > 4096) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'cvlan' need to be in the following range: 0 > value > 4096.\n", config.name, config.type, filename); return TRUE; } e->key.cvlan_id.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_CVLAN_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'cvlan' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_cvlan_id_handler; /* else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_vlan_id_handler; */ if (e->func[x]) e->func_type[x] = PRETAG_CVLAN_ID; return FALSE; } int PT_map_src_net_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.src_net.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (!str_to_addr_mask(value, &e->key.src_net.a, &e->key.src_net.m)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad source network address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_SRC_NET) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'src_net' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_src_net_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_src_net_handler; if (e->func[x]) e->func_type[x] = PRETAG_SRC_NET; return FALSE; } int PT_map_dst_net_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.dst_net.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); if (!str_to_addr_mask(value, &e->key.dst_net.a, &e->key.dst_net.m)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad destination network address '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_DST_NET) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'dst_net' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_dst_net_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_dst_net_handler; if (e->func[x]) e->func_type[x] = PRETAG_DST_NET; return FALSE; } int PT_map_is_multicast_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int value_tf, x = 0; e->key.is_multicast.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); value_tf = parse_truefalse(value); if (value_tf < 0) { return ERR; } e->key.is_multicast.n = value_tf; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_IS_MULTICAST) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'is_multicast' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_is_multicast_handler; else if (config.acct_type == ACCT_SF) e->func[x] = SF_pretag_is_multicast_handler; if (e->func[x]) e->func_type[x] = PRETAG_IS_MULTICAST; return FALSE; } int PT_map_set_tos_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, len; char *endptr; e->set_tos.set = TRUE; len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'set_tos' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } e->set_tos.n = strtoul(value, &endptr, 10); for (x = 0; e->set_func[x]; x++) { if (e->set_func_type[x] == PRETAG_SET_TOS) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'set_tos' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } /* feature currently only supported in nfacctd */ if (config.acct_type == ACCT_NF) e->set_func[x] = pretag_set_tos_handler; if (e->set_func[x]) e->set_func_type[x] = PRETAG_SET_TOS; return FALSE; } int BTA_map_lookup_bgp_port_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int x = 0, len; char *endptr; e->key.lookup_bgp_port.set = TRUE; len = strlen(value); while (x < len) { if (!isdigit(value[x])) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bad 'bgp_port' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } x++; } e->key.lookup_bgp_port.n = strtoul(value, &endptr, 10); for (x = 0; e->set_func[x]; x++) { if (e->set_func_type[x] == PRETAG_LOOKUP_BGP_PORT) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'bgp_port' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } /* feature currently only supported in bgp_agent_map */ if (acct_type == MAP_BGP_TO_XFLOW_AGENT) e->set_func[x] = BTA_lookup_bgp_port_handler; if (e->set_func[x]) e->set_func_type[x] = PRETAG_LOOKUP_BGP_PORT; return FALSE; } int PT_map_entry_label_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int len; len = MIN((strlen(value) + 1), MAX_LABEL_LEN); e->entry_label = malloc(len); if (!e->entry_label) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (PT_map_entry_label_handler). Exiting.\n", config.name, config.type, filename); exit_gracefully(1); } else memset(e->entry_label, 0, len); if (strlen(value) >= MAX_LABEL_LEN) { strncpy(e->entry_label, value, (MAX_LABEL_LEN - 1)); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] entry label '%s' cut to '%s'.\n", config.name, config.type, filename, value, e->entry_label); } else strcpy(e->entry_label, value); return FALSE; } int PT_map_jeq_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int len; len = MIN((strlen(value) + 1), MAX_LABEL_LEN); e->jeq.label = malloc(len); if (!e->jeq.label) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (PT_map_jeq_handler). Exiting.\n", config.name, config.type, filename); exit_gracefully(1); } else memset(e->jeq.label, 0, len); if (strlen(value) >= MAX_LABEL_LEN) { strncpy(e->jeq.label, value, (MAX_LABEL_LEN - 1)); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] JEQ label '%s' cut to '%s'.\n", config.name, config.type, filename, value, e->jeq.label); } else strcpy(e->jeq.label, value); pt_set_jeq(&((struct id_table *) req->key_value_table)->flags); return FALSE; } int PT_map_return_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int res = parse_truefalse(value); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] RETURN is in the process of being discontinued.\n", config.name, config.type, filename); Log(LOG_WARNING, "WARN ( %s/%s ): [%s] %s: %s\n", config.name, config.type, filename, GET_IN_TOUCH_MSG, MANTAINER); if (res < 0) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unknown RETURN value: '%s'. Ignoring.\n", config.name, config.type, filename, value); else e->ret = res; return FALSE; } int PT_map_stack_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { e->stack.func = NULL; if (*value == '+' || !strncmp(value, "sum", 3)) e->stack.func = PT_stack_sum; else if (!strncmp(value, "or", 2)) e->stack.func = PT_stack_logical_or; else Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unknown STACK operator: '%s'. Ignoring.\n", config.name, config.type, filename, value); return FALSE; } int PT_map_fwd_status_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { int tmp, x = 0; if (req->ptm_c.load_ptm_plugin == PLUGIN_ID_TEE) req->ptm_c.load_ptm_res = TRUE; e->key.fwd_status.neg = pt_check_neg(&value, &((struct id_table *) req->key_value_table)->flags); tmp = atoi(value); if (tmp < 0 || tmp > 256) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] 'fwd_status' need to be in the following range: 0 > value > 256.\n", config.name, config.type, filename); return TRUE; } e->key.fwd_status.n = tmp; for (x = 0; e->func[x]; x++) { if (e->func_type[x] == PRETAG_FWDSTATUS_ID) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Multiple 'fwd_status' clauses part of the same statement.\n", config.name, config.type, filename); return TRUE; } } if (config.acct_type == ACCT_NF) e->func[x] = pretag_fwd_status_handler; if (e->func[x]) e->func_type[x] = PRETAG_FWDSTATUS_ID; return FALSE; } int pretag_dummy_ip_handler(struct packet_ptrs *pptrs, void *unused, void *e) { return FALSE; } int pretag_input_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t input16 = htons(entry->key.input.n); u_int32_t input32 = htonl(entry->key.input.n); u_int8_t neg = entry->key.input.neg; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_INPUT_SNMP].len == 2) { if (!memcmp(&input16, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, tpl->tpl[NF9_INPUT_SNMP].len)) return (FALSE | neg); } else if (tpl->tpl[NF9_INPUT_SNMP].len == 4) { if (!memcmp(&input32, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, tpl->tpl[NF9_INPUT_SNMP].len)) return (FALSE | neg); } else if (tpl->tpl[NF9_INPUT_PHYSINT].len == 4) { if (!memcmp(&input32, pptrs->f_data+tpl->tpl[NF9_INPUT_PHYSINT].off, tpl->tpl[NF9_INPUT_PHYSINT].len)) return (FALSE | neg); } return (TRUE ^ neg); case 5: if (input16 == ((struct struct_export_v5 *)pptrs->f_data)->input) return (FALSE | neg); else return (TRUE ^ neg); default: return TRUE; } } int pretag_output_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t output16 = htons(entry->key.output.n); u_int32_t output32 = htonl(entry->key.output.n); u_int8_t neg = entry->key.output.neg; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_OUTPUT_SNMP].len == 2) { if (!memcmp(&output16, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, tpl->tpl[NF9_OUTPUT_SNMP].len)) return (FALSE | neg); } else if (tpl->tpl[NF9_OUTPUT_SNMP].len == 4) { if (!memcmp(&output32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, tpl->tpl[NF9_OUTPUT_SNMP].len)) return (FALSE | neg); } else if (tpl->tpl[NF9_OUTPUT_PHYSINT].len == 4) { if (!memcmp(&output32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_PHYSINT].off, tpl->tpl[NF9_OUTPUT_PHYSINT].len)) return (FALSE | neg); } return (TRUE ^ neg); case 5: if (output16 == ((struct struct_export_v5 *)pptrs->f_data)->output) return (FALSE | neg); else return (TRUE ^ neg); default: return TRUE; } } int pretag_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (entry->key.nexthop.a.family == AF_INET) { if (!memcmp(&entry->key.nexthop.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_NEXT_HOP].off, tpl->tpl[NF9_IPV4_NEXT_HOP].len)) return (FALSE | entry->key.nexthop.neg); } else if (entry->key.nexthop.a.family == AF_INET6) { if (!memcmp(&entry->key.nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_NEXT_HOP].off, tpl->tpl[NF9_IPV6_NEXT_HOP].len)) return (FALSE | entry->key.nexthop.neg); } return (TRUE ^ entry->key.nexthop.neg); case 5: if (entry->key.nexthop.a.address.ipv4.s_addr == ((struct struct_export_v5 *)pptrs->f_data)->nexthop.s_addr) return (FALSE | entry->key.nexthop.neg); else return (TRUE ^ entry->key.nexthop.neg); default: return TRUE; } } int pretag_bgp_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (entry->last_matched == PRETAG_BGP_NEXTHOP) return FALSE; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, config.nfacctd_net, NF_NET_KEEP)) return TRUE; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (entry->key.bgp_nexthop.a.family == AF_INET) { if (tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].off, tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len)) return (FALSE | entry->key.bgp_nexthop.neg); } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].off, tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len)) return (FALSE | entry->key.bgp_nexthop.neg); } } else if (entry->key.nexthop.a.family == AF_INET6) { if (tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].off, tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len)) return (FALSE | entry->key.bgp_nexthop.neg); } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].off, tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len)) return (FALSE | entry->key.bgp_nexthop.neg); } } return (TRUE ^ entry->key.bgp_nexthop.neg); case 5: if (entry->key.bgp_nexthop.a.address.ipv4.s_addr == ((struct struct_export_v5 *)pptrs->f_data)->nexthop.s_addr) return (FALSE | entry->key.bgp_nexthop.neg); else return (TRUE ^ entry->key.bgp_nexthop.neg); default: return TRUE; } } int pretag_bgp_bgp_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; int ret = -1; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, config.nfacctd_net, NF_NET_BGP)) goto way_out; if (dst_ret) { if (pptrs->bgp_nexthop_info) info = (struct bgp_info *) pptrs->bgp_nexthop_info; else info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { ret = memcmp(&entry->key.bgp_nexthop.a.address.ipv4, &info->attr->mp_nexthop.address.ipv4, 4); } else if (info->attr->mp_nexthop.family == AF_INET6) { ret = memcmp(&entry->key.bgp_nexthop.a.address.ipv6, &info->attr->mp_nexthop.address.ipv6, 16); } else { ret = memcmp(&entry->key.bgp_nexthop.a.address.ipv4, &info->attr->nexthop, 4); } } } way_out: if (!ret) { entry->last_matched = PRETAG_BGP_NEXTHOP; return (FALSE | entry->key.bgp_nexthop.neg); } else if (config.nfacctd_net & NF_NET_KEEP) return FALSE; else return (TRUE ^ entry->key.bgp_nexthop.neg); } int pretag_engine_type_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; switch(hdr->version) { case 5: if (entry->key.engine_type.n == ((struct struct_header_v5 *)pptrs->f_header)->engine_type) return (FALSE | entry->key.engine_type.neg); else return (TRUE ^ entry->key.engine_type.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_engine_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; u_int32_t value; switch(hdr->version) { case 10: { struct struct_header_ipfix *hdr = (struct struct_header_ipfix *) pptrs->f_header; value = ntohl(hdr->source_id); if (entry->key.engine_id.n == value) return (FALSE | entry->key.engine_id.neg); else return (TRUE ^ entry->key.engine_id.neg); } case 9: { struct struct_header_v9 *hdr = (struct struct_header_v9 *) pptrs->f_header; value = ntohl(hdr->source_id); if (entry->key.engine_id.n == value) return (FALSE | entry->key.engine_id.neg); else return (TRUE ^ entry->key.engine_id.neg); } case 5: if (entry->key.engine_id.n == ((struct struct_header_v5 *)pptrs->f_header)->engine_id) return (FALSE | entry->key.engine_id.neg); else return (TRUE ^ entry->key.engine_id.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_flowset_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (!pptrs->f_tpl) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl) { if (entry->key.flowset_id.n == tpl->template_id) return (FALSE | entry->key.flowset_id.neg); else return (TRUE ^ entry->key.flowset_id.neg); } else return TRUE; /* template not received yet */ default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_filter_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (bpf_filter(entry->key.filter.bf_insns, pptrs->packet_ptr, pptrs->pkthdr->len, pptrs->pkthdr->caplen)) return FALSE; /* matched filter */ else return TRUE; } int pretag_src_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t asn16 = 0; u_int32_t asn32 = 0; if (entry->last_matched == PRETAG_SRC_AS) return FALSE; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_SRC_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 2); asn32 = ntohs(asn16); } else if (tpl->tpl[NF9_SRC_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 4); asn32 = ntohl(asn32); } break; case 5: asn32 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->src_as); break; default: break; } if (entry->key.src_as.n == asn32) return (FALSE | entry->key.src_as.neg); else return (TRUE ^ entry->key.src_as.neg); } int pretag_bgp_src_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; as_t asn = 0; if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (info->attr->aspath) { asn = evaluate_last_asn(info->attr->aspath); } } } if (entry->key.src_as.n == asn) { entry->last_matched = PRETAG_SRC_AS; return (FALSE | entry->key.src_as.neg); } else if (config.nfacctd_as & NF_AS_KEEP) return FALSE; else return (TRUE ^ entry->key.src_as.neg); } int pretag_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t asn16 = 0; u_int32_t asn32 = 0; if (entry->last_matched == PRETAG_DST_AS) return FALSE; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DST_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 2); asn32 = ntohs(asn16); } else if (tpl->tpl[NF9_DST_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 4); asn32 = ntohl(asn32); } break; case 5: asn32 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->dst_as); break; default: break; } if (entry->key.dst_as.n == asn32) return (FALSE | entry->key.dst_as.neg); else return (TRUE ^ entry->key.dst_as.neg); } int pretag_bgp_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; as_t asn = 0; if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (info->attr->aspath) { asn = evaluate_last_asn(info->attr->aspath); } } } if (entry->key.dst_as.n == asn) { entry->last_matched = PRETAG_DST_AS; return (FALSE | entry->key.dst_as.neg); } else if (config.nfacctd_as & NF_AS_KEEP) return FALSE; else return (TRUE ^ entry->key.dst_as.neg); } int pretag_peer_src_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; as_t asn = 0; if (config.bgp_daemon_peer_as_src_type == BGP_SRC_PRIMITIVES_MAP) { asn = pptrs->bpas; } else if (config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_BGP) { if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (info->attr->aspath && info->attr->aspath->str) { asn = evaluate_first_asn(info->attr->aspath->str); } } } } if (entry->key.peer_src_as.n == asn) return (FALSE | entry->key.peer_src_as.neg); else return (TRUE ^ entry->key.peer_src_as.neg); } int pretag_peer_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; as_t asn = 0; if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (info->attr->aspath && info->attr->aspath->str) { asn = evaluate_first_asn(info->attr->aspath->str); } } } if (entry->key.peer_dst_as.n == asn) return (FALSE | entry->key.peer_dst_as.neg); else return (TRUE ^ entry->key.peer_dst_as.neg); } int pretag_src_local_pref_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; u_int32_t local_pref = 0; if (config.bgp_daemon_src_local_pref_type == BGP_SRC_PRIMITIVES_MAP) { local_pref = pptrs->blp; } else if (config.bgp_daemon_src_local_pref_type & BGP_SRC_PRIMITIVES_BGP) { if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { local_pref = info->attr->local_pref; } } } if (entry->key.src_local_pref.n == local_pref) return (FALSE | entry->key.src_local_pref.neg); else return (TRUE ^ entry->key.src_local_pref.neg); } int pretag_local_pref_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; u_int32_t local_pref = 0; if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { local_pref = info->attr->local_pref; } } if (entry->key.local_pref.n == local_pref) return (FALSE | entry->key.local_pref.neg); else return (TRUE ^ entry->key.local_pref.neg); } int pretag_src_roa_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; u_int8_t roa = ROA_STATUS_UNKNOWN; if (config.bgp_daemon_src_roa_type & BGP_SRC_PRIMITIVES_BGP) { if (src_ret) roa = pptrs->src_roa; } if (entry->key.src_roa.n == roa) return (FALSE | entry->key.src_roa.neg); else return (TRUE ^ entry->key.src_roa.neg); } int pretag_dst_roa_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; u_int8_t roa = ROA_STATUS_UNKNOWN; if (entry->key.dst_roa.n == roa) return (FALSE | entry->key.dst_roa.neg); else return (TRUE ^ entry->key.dst_roa.neg); } int pretag_src_comms_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; char tmp_stdcomms[MAX_BGP_STD_COMMS]; memset(tmp_stdcomms, 0, sizeof(tmp_stdcomms)); if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr && info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, entry->key.src_comms, MAX_BGP_STD_COMMS); } } if (strlen(tmp_stdcomms)) return FALSE; else return TRUE; } int pretag_comms_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; char tmp_stdcomms[MAX_BGP_STD_COMMS]; memset(tmp_stdcomms, 0, sizeof(tmp_stdcomms)); if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr && info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, entry->key.comms, MAX_BGP_STD_COMMS); } } if (strlen(tmp_stdcomms)) return FALSE; else return TRUE; } int pretag_sample_type_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; u_int8_t flow_type = pptrs->flow_type.traffic_type; if (entry->key.sample_type.n == PM_FTYPE_TRAFFIC) { if (flow_type >= PM_FTYPE_TRAFFIC && flow_type <= PM_FTYPE_TRAFFIC_MAX) { flow_type = PM_FTYPE_TRAFFIC; } } if (entry->key.sample_type.n == flow_type) return (FALSE | entry->key.sample_type.neg); else return (TRUE ^ entry->key.sample_type.neg); } int pretag_is_bi_flow_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (entry->key.is_bi_flow.n == pptrs->flow_type.is_bi) return (FALSE | entry->key.is_bi_flow.neg); else return (TRUE ^ entry->key.is_bi_flow.neg); } int pretag_is_nsel_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t nsel = FALSE; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FW_EVENT].len) { nsel = TRUE; } break; default: break; /* this field does not exist */ } if ((entry->key.is_nsel.n && nsel) || (!entry->key.is_nsel.n && !nsel)) { return (FALSE | entry->key.is_nsel.neg); } else { return (TRUE ^ entry->key.is_nsel.neg); } } int pretag_is_nel_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t nel = FALSE; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_NAT_EVENT].len) { nel = TRUE; } break; default: break; /* this field does not exist */ } if ((entry->key.is_nel.n && nel) || (!entry->key.is_nel.n && !nel)) { return (FALSE | entry->key.is_nel.neg); } else { return (TRUE ^ entry->key.is_nel.neg); } } int pretag_direction_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t direction = 0; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DIRECTION].len == 1) { memcpy(&direction, pptrs->f_data+tpl->tpl[NF9_DIRECTION].off, 1); } if (entry->key.direction.n == direction) return (FALSE | entry->key.direction.neg); else return (TRUE ^ entry->key.direction.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_nat_event_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t nat_event = 0; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_NAT_EVENT].len == 1) { memcpy(&nat_event, pptrs->f_data+tpl->tpl[NF9_NAT_EVENT].off, 1); } if (entry->key.nat_event.n == nat_event) return (FALSE | entry->key.nat_event.neg); else return (TRUE ^ entry->key.nat_event.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_mpls_vpn_rd_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; int ret = -1; /* XXX: no src_ret lookup? */ if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr_extra) { ret = memcmp(&entry->key.mpls_vpn_rd.rd, &info->attr_extra->rd, sizeof(rd_t)); } } if (!ret) return (FALSE | entry->key.mpls_vpn_rd.neg); else return (TRUE ^ entry->key.mpls_vpn_rd.neg); } int pretag_mpls_pw_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t tmp32 = 0, mpls_pw_id = 0;; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PSEUDOWIREID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_PSEUDOWIREID].off, 4); mpls_pw_id = ntohl(tmp32); } if (entry->key.mpls_pw_id.n == mpls_pw_id) return (FALSE | entry->key.mpls_pw_id.neg); else return (TRUE ^ entry->key.mpls_pw_id.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_src_mac_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_SRC_MAC].len) { if (!memcmp(&entry->key.src_mac.a, pptrs->f_data+tpl->tpl[NF9_IN_SRC_MAC].off, MIN(tpl->tpl[NF9_IN_SRC_MAC].len, 6))) return (FALSE | entry->key.src_mac.neg); } return (TRUE ^ entry->key.src_mac.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_dst_mac_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_DST_MAC].len) { if (!memcmp(&entry->key.dst_mac.a, pptrs->f_data+tpl->tpl[NF9_IN_DST_MAC].off, MIN(tpl->tpl[NF9_IN_DST_MAC].len, 6))) return (FALSE | entry->key.dst_mac.neg); } return (TRUE ^ entry->key.dst_mac.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_vlan_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t tmp16 = 0, vlan_id = 0; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_VLAN].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off, MIN(tpl->tpl[NF9_IN_VLAN].len, 2)); } else if (tpl->tpl[NF9_DOT1QVLANID].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_DOT1QVLANID].off, MIN(tpl->tpl[NF9_DOT1QVLANID].len, 2)); } vlan_id = ntohs(tmp16); if (entry->key.vlan_id.n == vlan_id) return (FALSE | entry->key.vlan_id.neg); else return (TRUE ^ entry->key.vlan_id.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_src_net_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct host_addr addr; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IPV4_SRC_ADDR].len) { memcpy(&addr.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV4_SRC_ADDR].len, 4)); addr.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_SRC_PREFIX].len) { memcpy(&addr.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_SRC_PREFIX].len, 4)); addr.family = AF_INET; } if (tpl->tpl[NF9_IPV6_SRC_ADDR].len) { memcpy(&addr.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV6_SRC_ADDR].len, 16)); addr.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_SRC_PREFIX].len) { memcpy(&addr.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_SRC_PREFIX].len, 16)); addr.family = AF_INET6; } break; case 5: addr.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->srcaddr.s_addr; addr.family = AF_INET; break; default: return TRUE; } if (!host_addr_mask_cmp(&entry->key.src_net.a, &entry->key.src_net.m, &addr)) return (FALSE | entry->key.src_net.neg); else return (TRUE ^ entry->key.src_net.neg); } int pretag_dst_net_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; struct host_addr addr; if (!pptrs->f_data) return TRUE; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IPV4_DST_ADDR].len) { memcpy(&addr.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV4_DST_ADDR].len, 4)); addr.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_DST_PREFIX].len) { memcpy(&addr.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_DST_PREFIX].len, 4)); addr.family = AF_INET; } if (tpl->tpl[NF9_IPV6_DST_ADDR].len) { memcpy(&addr.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV6_DST_ADDR].len, 16)); addr.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_DST_PREFIX].len) { memcpy(&addr.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_DST_PREFIX].len, 16)); addr.family = AF_INET6; } break; case 5: addr.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->dstaddr.s_addr; addr.family = AF_INET; break; default: return TRUE; } if (!host_addr_mask_cmp(&entry->key.dst_net.a, &entry->key.dst_net.m, &addr)) return (FALSE | entry->key.dst_net.neg); else return (TRUE ^ entry->key.dst_net.neg); } int pretag_is_multicast_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int8_t multicast = FALSE; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_DST_MAC].len) { multicast = IS_MAC_MULTICAST(pptrs->f_data+tpl->tpl[NF9_IN_DST_MAC].off); } break; default: break; /* this field does not exist */ } if ((entry->key.is_multicast.n && multicast) || (!entry->key.is_multicast.n && !multicast)) { return (FALSE | entry->key.is_multicast.neg); } else { return (TRUE ^ entry->key.is_multicast.neg); } } int pretag_fwd_status_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t fwd_status = 0; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: /* being specific on the length because IANA defines this field as unsigned32 but vendor implementation suggests this is defined as 1 octet */ if (tpl->tpl[NF9_FWD_STATUS].len == 1) { memcpy(&fwd_status, pptrs->f_data+tpl->tpl[NF9_FWD_STATUS].off, MIN(tpl->tpl[NF9_FWD_STATUS].len, 1)); } else return TRUE; u_int32_t comp = (entry->key.fwd_status.n & 0xC0); if (comp == entry->key.fwd_status.n) { /* We have a generic (unknown) status provided so we then take everything that match that. */ u_int32_t base = (fwd_status & 0xC0); if ( comp == base ) return (FALSE | entry->key.fwd_status.neg); else return (TRUE ^ entry->key.fwd_status.neg); } else { /* We have a specific code so lets handle that. */ if (entry->key.fwd_status.n == fwd_status) return (FALSE | entry->key.fwd_status.neg); else return (TRUE ^ entry->key.fwd_status.neg); } default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_cvlan_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t tmp16 = 0, cvlan_id = 0; if (!pptrs->f_data) return TRUE; switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DOT1QCVLANID].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_DOT1QCVLANID].off, MIN(tpl->tpl[NF9_DOT1QCVLANID].len, 2)); } cvlan_id = ntohs(tmp16); if (entry->key.cvlan_id.n == cvlan_id) return (FALSE | entry->key.cvlan_id.neg); else return (TRUE ^ entry->key.cvlan_id.neg); default: return TRUE; /* this field does not exist: condition is always true */ } } int pretag_set_tos_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; memcpy(&pptrs->set_tos, &entry->set_tos, sizeof(s_uint8_t)); return PRETAG_MAP_RCODE_SET_TOS; } int BTA_lookup_bgp_port_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; memcpy(&pptrs->lookup_bgp_port, &entry->key.lookup_bgp_port, sizeof(s_uint16_t)); return BTA_MAP_RCODE_LOOKUP_BGP_PORT; } int pretag_id_handler(struct packet_ptrs *pptrs, void *id, void *e) { struct id_entry *entry = e; pm_id_t *tid = id; *tid = entry->id; if (!entry->id && entry->flags == BPAS_MAP_RCODE_BGP) { struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (info->attr->aspath && info->attr->aspath->str) { *tid = evaluate_first_asn(info->attr->aspath->str); if (!(*tid) && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, (as_t *)tid, FALSE); } } if (!(*tid) && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, (as_t *)tid, FALSE); } } } } } } if (entry->id_inc) entry->id++; if (entry->flags == BTA_MAP_RCODE_ID_ID2) { return BTA_MAP_RCODE_ID_ID2; /* cap */ } return PRETAG_MAP_RCODE_ID; /* cap */ } int pretag_id2_handler(struct packet_ptrs *pptrs, void *id, void *e) { struct id_entry *entry = e; pm_id_t *tid = id; *tid = entry->id2; if (entry->id2_inc) entry->id2++; return PRETAG_MAP_RCODE_ID2; /* cap */ } int pretag_label_handler(struct packet_ptrs *pptrs, void *id, void *e) { struct id_entry *entry = e; pt_label_t *out_label = (pt_label_t *) id; if (out_label) { pretag_copy_label(out_label, &entry->label); } return PRETAG_MAP_RCODE_LABEL; /* cap */ } int SF_pretag_input_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.input.n == sample->inputPort) return (FALSE | entry->key.input.neg); else return (TRUE ^ entry->key.input.neg); } int SF_pretag_output_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.output.n == sample->outputPort) return (FALSE | entry->key.output.neg); else return (TRUE ^ entry->key.output.neg); } int SF_pretag_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.nexthop.a.family == AF_INET) { if (!memcmp(&entry->key.nexthop.a.address.ipv4, &sample->nextHop.address.ip_v4, 4)) return (FALSE | entry->key.nexthop.neg); } else if (entry->key.nexthop.a.family == AF_INET6) { if (!memcmp(&entry->key.nexthop.a.address.ipv6, &sample->nextHop.address.ip_v6, IP6AddrSz)) return (FALSE | entry->key.nexthop.neg); } return (TRUE ^ entry->key.nexthop.neg); } int SF_pretag_bgp_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->last_matched == PRETAG_BGP_NEXTHOP) return FALSE; /* check network-related primitives against fallback scenarios */ if (!evaluate_lm_method(pptrs, TRUE, config.nfacctd_net, NF_NET_KEEP)) return TRUE; if (entry->key.bgp_nexthop.a.family == AF_INET) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv4, &sample->bgp_nextHop.address.ip_v4, 4)) return (FALSE | entry->key.bgp_nexthop.neg); } else if (entry->key.bgp_nexthop.a.family == AF_INET6) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv6, &sample->bgp_nextHop.address.ip_v6, IP6AddrSz)) return (FALSE | entry->key.bgp_nexthop.neg); } return (TRUE ^ entry->key.bgp_nexthop.neg); } int SF_pretag_agent_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.agent_id.n == sample->agentSubId) return (FALSE | entry->key.agent_id.neg); else return (TRUE ^ entry->key.agent_id.neg); } int SF_pretag_sample_type_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (entry->key.sample_type.n == pptrs->sample_type) return (FALSE | entry->key.sample_type.neg); else return (TRUE ^ entry->key.sample_type.neg); } int SF_pretag_direction_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if ((sample->inputPort == sample->ds_index && entry->key.direction.n == 0) || (sample->outputPort == sample->ds_index && entry->key.direction.n == 1)) { return (FALSE | entry->key.direction.neg); } else return (TRUE ^ entry->key.direction.neg); } int SF_pretag_src_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; /* If in a fallback scenario, ie. NF_AS_BGP + NF_AS_KEEP set, check BGP first */ if (config.nfacctd_as & NF_AS_BGP && pptrs->bgp_src) return FALSE; if (entry->key.src_as.n == sample->src_as) return (FALSE | entry->key.src_as.neg); else return (TRUE ^ entry->key.src_as.neg); } int SF_pretag_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; /* If in a fallback scenario, ie. NF_AS_BGP + NF_AS_KEEP set, check BGP first */ if (config.nfacctd_as & NF_AS_BGP && pptrs->bgp_dst) return FALSE; if (entry->key.dst_as.n == sample->dst_as) return (FALSE | entry->key.dst_as.neg); else return (TRUE ^ entry->key.dst_as.neg); } int SF_pretag_src_mac_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (!memcmp(entry->key.src_mac.a, sample->eth_src, ETH_ADDR_LEN)) return (FALSE | entry->key.src_mac.neg); else return (TRUE ^ entry->key.src_mac.neg); } int SF_pretag_dst_mac_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (!memcmp(entry->key.dst_mac.a, sample->eth_dst, ETH_ADDR_LEN)) return (FALSE | entry->key.dst_mac.neg); else return (TRUE ^ entry->key.dst_mac.neg); } int SF_pretag_vlan_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.vlan_id.n == sample->in_vlan || entry->key.vlan_id.n == sample->out_vlan) return (FALSE | entry->key.vlan_id.neg); else return (TRUE ^ entry->key.vlan_id.neg); } int SF_pretag_mpls_pw_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; if (entry->key.mpls_pw_id.n == sample->mpls_vll_vc_id) return (FALSE | entry->key.mpls_pw_id.neg); else return (TRUE ^ entry->key.mpls_pw_id.neg); } int SF_pretag_src_net_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *sf_addr = &sample->ipsrc; struct host_addr addr; if (sample->gotIPV4) { addr.address.ipv4.s_addr = sample->dcd_srcIP.s_addr; addr.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&addr.address.ipv6, &sf_addr->address.ip_v6, IP6AddrSz); addr.family = AF_INET6; } if (!host_addr_mask_cmp(&entry->key.src_net.a, &entry->key.src_net.m, &addr)) return (FALSE | entry->key.src_net.neg); else return (TRUE ^ entry->key.src_net.neg); } int SF_pretag_dst_net_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *sf_addr = &sample->ipdst; struct host_addr addr; if (sample->gotIPV4) { addr.address.ipv4.s_addr = sample->dcd_dstIP.s_addr; addr.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&addr.address.ipv6, &sf_addr->address.ip_v6, IP6AddrSz); addr.family = AF_INET6; } if (!host_addr_mask_cmp(&entry->key.dst_net.a, &entry->key.dst_net.m, &addr)) return (FALSE | entry->key.dst_net.neg); else return (TRUE ^ entry->key.dst_net.neg); } int SF_pretag_is_multicast_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; SFSample *sample = (SFSample *) pptrs->f_data; u_int8_t multicast; multicast = IS_MAC_MULTICAST(sample->eth_dst); if ((entry->key.is_multicast.n && multicast) || (!entry->key.is_multicast.n && !multicast)) { return (FALSE | entry->key.is_multicast.neg); } else { return (TRUE ^ entry->key.is_multicast.neg); } } int PM_pretag_src_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; as_t res = search_pretag_src_as(&nt, &nc, pptrs); if (entry->key.src_as.n == res) return (FALSE | entry->key.src_as.neg); else return (TRUE ^ entry->key.src_as.neg); } int PM_pretag_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; as_t res = search_pretag_dst_as(&nt, &nc, pptrs); if (entry->key.dst_as.n == res) return (FALSE | entry->key.dst_as.neg); else return (TRUE ^ entry->key.dst_as.neg); } int PM_pretag_input_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (entry->key.input.n == pptrs->ifindex_in) return (FALSE | entry->key.input.neg); else return (TRUE ^ entry->key.input.neg); } int PM_pretag_output_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (entry->key.output.n == pptrs->ifindex_out) return (FALSE | entry->key.output.neg); else return (TRUE ^ entry->key.output.neg); } int PM_pretag_direction_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; if (entry->key.direction.n == pptrs->direction) return (FALSE | entry->key.output.neg); else return (TRUE ^ entry->key.output.neg); } pm_id_t PT_stack_sum(pm_id_t tag, pm_id_t pre) { return tag + pre; } pm_id_t PT_stack_logical_or(pm_id_t tag, pm_id_t pre) { return tag | pre; } int BPAS_bgp_nexthop_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (entry->key.bgp_nexthop.a.family == AF_INET) { if (info->attr->mp_nexthop.family == AF_INET) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv4, &info->attr->mp_nexthop.address.ipv4, 4)) return (FALSE | entry->key.bgp_nexthop.neg); } else { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv4, &info->attr->nexthop, 4)) return (FALSE | entry->key.bgp_nexthop.neg); } } else if (entry->key.nexthop.a.family == AF_INET6) { if (!memcmp(&entry->key.bgp_nexthop.a.address.ipv6, &info->attr->mp_nexthop.address.ipv6, 16)) return (FALSE | entry->key.bgp_nexthop.neg); } } } return (TRUE ^ entry->key.bgp_nexthop.neg); } int BPAS_bgp_peer_dst_as_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; as_t asn = 0; if (src_ret) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr) { if (info->attr->aspath && info->attr->aspath->str) { asn = evaluate_first_asn(info->attr->aspath->str); if (!asn && config.bgp_daemon_stdcomm_pattern_to_asn) { char tmp_stdcomms[MAX_BGP_STD_COMMS]; if (info->attr->community && info->attr->community->str) { evaluate_comm_patterns(tmp_stdcomms, info->attr->community->str, std_comm_patterns_to_asn, MAX_BGP_STD_COMMS); copy_stdcomm_to_asn(tmp_stdcomms, &asn, FALSE); } } if (!asn && config.bgp_daemon_lrgcomm_pattern_to_asn) { char tmp_lrgcomms[MAX_BGP_LRG_COMMS]; if (info->attr->lcommunity && info->attr->lcommunity->str) { evaluate_comm_patterns(tmp_lrgcomms, info->attr->lcommunity->str, lrg_comm_patterns_to_asn, MAX_BGP_LRG_COMMS); copy_lrgcomm_to_asn(tmp_lrgcomms, &asn, FALSE); } } } } } if (entry->key.peer_dst_as.n == asn) return (FALSE | entry->key.peer_dst_as.neg); else return (TRUE ^ entry->key.peer_dst_as.neg); } int BITR_mpls_label_bottom_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; int label_idx; u_int32_t label; switch(hdr->version) { case 10: case 9: for (label_idx = NF9_MPLS_LABEL_1; label_idx <= NF9_MPLS_LABEL_9; label_idx++) { if (tpl->tpl[label_idx].len == 3 && check_bosbit(pptrs->f_data+tpl->tpl[label_idx].off)) { label = decode_mpls_label(pptrs->f_data+tpl->tpl[label_idx].off); if (entry->key.mpls_label_bottom.n == label) return (FALSE | entry->key.mpls_label_bottom.neg); } } return (TRUE ^ entry->key.mpls_label_bottom.neg); break; default: return (TRUE ^ entry->key.mpls_label_bottom.neg); break; } } int BITR_mpls_vpn_id_handler(struct packet_ptrs *pptrs, void *unused, void *e) { struct id_entry *entry = e; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t tmp32 = 0, id = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_INGRESS_VRFID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_INGRESS_VRFID].off, MIN(tpl->tpl[NF9_INGRESS_VRFID].len, 4)); id = ntohl(tmp32); if (entry->key.mpls_vpn_id.n == id) return (FALSE | entry->key.mpls_vpn_id.neg); } if (tpl->tpl[NF9_EGRESS_VRFID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_EGRESS_VRFID].off, MIN(tpl->tpl[NF9_EGRESS_VRFID].len, 4)); id = ntohl(tmp32); if (entry->key.mpls_vpn_id.n == id) return (FALSE | entry->key.mpls_vpn_id.neg); } return (TRUE ^ entry->key.mpls_vpn_id.neg); break; default: return (TRUE ^ entry->key.mpls_vpn_id.neg); break; } } int custom_primitives_map_name_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; int idx; if (table) { lower_string(value); for (idx = 0; idx < table->num && strlen(table->primitive[idx].name); idx++) { if (!strcmp(table->primitive[idx].name, value)) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Duplicate custom aggregate primitive name specified: %s.\n", config.name, config.type, filename, value); return TRUE; } } strlcpy(table->primitive[table->num].name, value, MAX_CUSTOM_PRIMITIVE_NAMELEN); } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] custom aggregate primitives registry not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int custom_primitives_map_field_type_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; char *pen = NULL, *type = NULL, *endptr; if (table) { u_int8_t repeat_id; int idx; if ((type = strchr(value, ':'))) { pen = value; *type = '\0'; type++; } else type = value; if (pen) table->primitive[table->num].pen = strtoul(pen, &endptr, 10); table->primitive[table->num].field_type = atoi(type); if (!table->primitive[table->num].field_type) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid NetFlow v9/IPFIX field type '%s'.\n", config.name, config.type, filename, value); return TRUE; } for (idx = 0, repeat_id = 0; idx < table->num; idx++) { if (table->primitive[idx].field_type == table->primitive[table->num].field_type && table->primitive[idx].pen == table->primitive[table->num].pen) repeat_id++; } table->primitive[table->num].repeat_id = repeat_id; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] custom aggregate primitives registry not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int custom_primitives_map_packet_ptr_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; struct packet_data_ptr *pd_ptr = NULL; char *layer = NULL, *proto_ptr = NULL, *offset_ptr = NULL, *endptr; u_int16_t offset = 0, proto = 0, idx = 0; if (/* config.acct_type == ACCT_PM && */ table) { for (idx = 0; idx < MAX_CUSTOM_PRIMITIVE_PD_PTRS; idx++) { if (!table->primitive[table->num].pd_ptr[idx].ptr_idx.set) { pd_ptr = &table->primitive[table->num].pd_ptr[idx]; break; } } if (!pd_ptr) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] exceeded %u 'packet_ptr' limit per rule.\n", config.name, config.type, filename, MAX_CUSTOM_PRIMITIVE_PD_PTRS); return TRUE; } layer = value; proto_ptr = strchr(value, ':'); offset_ptr = strchr(value, '+'); if (offset_ptr) { *offset_ptr = '\0'; offset_ptr++; endptr = NULL; offset = strtoul(offset_ptr, &endptr, 10); } if (proto_ptr) { *proto_ptr = '\0'; proto_ptr++; endptr = NULL; if (strchr(proto_ptr, 'x')) proto = strtoul(proto_ptr, &endptr, 16); else proto = strtoul(proto_ptr, &endptr, 10); } if (!strncmp(layer, "packet", 6)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_PACKET_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) goto proto_err; } else if (!strncmp(layer, "mac", 3)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_MAC_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) goto proto_err; } else if (!strncmp(layer, "vlan", 4)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_VLAN_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) goto proto_err; } else if (!strncmp(layer, "mpls", 4)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_MPLS_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) goto proto_err; } else if (!strncmp(layer, "l3", 2)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_L3_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) { pd_ptr->proto.n = proto; pd_ptr->proto.set = TRUE; } } else if (!strncmp(layer, "l4", 2)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_L4_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) { pd_ptr->proto.n = proto; pd_ptr->proto.set = TRUE; } } else if (!strncmp(layer, "payload", 7)) { pd_ptr->ptr_idx.n = CUSTOM_PRIMITIVE_PAYLOAD_PTR; pd_ptr->ptr_idx.set = TRUE; if (proto) goto proto_err; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid packet pointer '%s'.\n", config.name, config.type, filename, value); return TRUE; } pd_ptr->off = offset; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] custom aggregate primitives registry not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; proto_err: Log(LOG_WARNING, "WARN ( %s/%s ): [%s] protocol type not supported for '%s'.\n", config.name, config.type, filename, layer); return TRUE; } int custom_primitives_map_len_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; if (table) { table->primitive[table->num].len = atoi(value); if (table->primitive[table->num].len) { if (table->primitive[table->num].len == PM_VARIABLE_LENGTH) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid length '%s'.\n", config.name, config.type, filename, value); return TRUE; } } else { if ((config.acct_type == ACCT_NF || config.acct_type == ACCT_PM) && !strncmp(value, "vlen", 4)) { table->primitive[table->num].len = PM_VARIABLE_LENGTH; } else { table->primitive[table->num].len = 0; /* pedantic */ Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid length '%s'.\n", config.name, config.type, filename, value); return TRUE; } } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] custom aggregate primitives registry not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int custom_primitives_map_semantics_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; if (table) { if (!strncmp(value, "u_int", 5)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_UINT; } else if (!strncmp(value, "hex", 3)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_HEX; } else if (!strncmp(value, "str", 3)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_STRING; } else if (!strncmp(value, "ip", 2)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_IP; } else if (!strncmp(value, "mac", 3)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_MAC; } else if (!strncmp(value, "raw", 3)) { table->primitive[table->num].semantics = CUSTOM_PRIMITIVE_TYPE_RAW; } } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] custom aggregate primitives registry not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } void custom_primitives_map_initialize() { custom_primitives_type = (COUNT_INDEX_CP | 0x1); } void custom_primitives_map_validate(char *filename, struct plugin_requests *req) { struct custom_primitives *table = (struct custom_primitives *) req->key_value_table; int valid = FALSE; if (table) { if (strcmp(table->primitive[table->num].name, "") && (table->primitive[table->num].field_type || table->primitive[table->num].pd_ptr[0].ptr_idx.set) && table->primitive[table->num].len && table->primitive[table->num].semantics) { valid = TRUE; if (table->primitive[table->num].semantics == CUSTOM_PRIMITIVE_TYPE_RAW) { table->primitive[table->num].alloc_len = (table->primitive[table->num].len * 3) + 1; } else { table->primitive[table->num].alloc_len = table->primitive[table->num].len; } } else valid = FALSE; if (valid && table->primitive[table->num].len == PM_VARIABLE_LENGTH) { if (table->primitive[table->num].semantics != CUSTOM_PRIMITIVE_TYPE_STRING && table->primitive[table->num].semantics != CUSTOM_PRIMITIVE_TYPE_RAW) valid = FALSE; table->primitive[table->num].alloc_len = PM_VARIABLE_LENGTH; } if (valid && (table->num + 1 < MAX_CUSTOM_PRIMITIVES)) { table->primitive[table->num].type = custom_primitives_type; custom_primitives_type = (COUNT_INDEX_CP | (custom_primitives_type << 1)); table->num++; } else { if (!valid) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Invalid entry: name=%s\n", config.name, config.type, filename, table->num + 1, table->primitive[table->num].name); } else if (table->num + 1 < MAX_CUSTOM_PRIMITIVES) { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Maximum entries (%d) reached in aggregate_primitives\n", config.name, config.type, filename, MAX_CUSTOM_PRIMITIVES); } memset(&table->primitive[table->num], 0, sizeof(struct custom_primitive_entry)); } } } int PT_map_index_entries_ip_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; if ((src_e->key.agent_mask.family == AF_INET && src_e->key.agent_mask.len == 32) || (src_e->key.agent_mask.family == AF_INET6 && src_e->key.agent_mask.len == 128)) { hash_serial_append(hash_serializer, (char *)&src_e->key.agent_ip.a, sizeof(struct host_addr), TRUE); } else { Log(LOG_WARNING, "WARN ( %s/%s ): pretag_index_fill(): unsupported 'ip' mask\n", config.name, config.type); return PRETAG_IDX_ERR_WARN; } return FALSE; } int PT_map_index_entries_input_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.input.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_output_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.output.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_bgp_nexthop_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.bgp_nexthop.a, sizeof(struct host_addr), TRUE); return FALSE; } int PT_map_index_entries_src_as_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.src_as.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_dst_as_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.dst_as.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_peer_src_as_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.peer_src_as.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_peer_dst_as_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.peer_dst_as.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_mpls_vpn_rd_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.mpls_vpn_rd.rd, sizeof(rd_t), TRUE); return FALSE; } int PT_map_index_entries_mpls_pw_id_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.mpls_pw_id.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_mpls_label_bottom_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.mpls_label_bottom.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_mpls_vpn_id_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.mpls_vpn_id.n, sizeof(u_int32_t), TRUE); return FALSE; } int PT_map_index_entries_src_mac_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.src_mac.a, ETH_ADDR_LEN, TRUE); return FALSE; } int PT_map_index_entries_dst_mac_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.dst_mac.a, ETH_ADDR_LEN, TRUE); return FALSE; } int PT_map_index_entries_vlan_id_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.vlan_id.n, sizeof(u_int16_t), TRUE); return FALSE; } int PT_map_index_entries_cvlan_id_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.cvlan_id.n, sizeof(u_int16_t), TRUE); return FALSE; } int PT_map_index_entries_src_net_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.src_net.a, sizeof(struct host_addr), TRUE); hash_serial_append(hash_serializer, (char *)&src_e->key.src_net.m.len, sizeof(src_e->key.src_net.m.len), TRUE); if (idx->netmask.hdlr_no) { if (idx->netmask.hdlr_no != (idx_hdlr_no + 1)) { Log(LOG_WARNING, "WARN ( %s/%s ): Index network masks count exceeded. Indexing disabled.\n", config.name, config.type); return TRUE; } } if (src_e->key.src_net.a.family == AF_INET) { if (!idx->netmask.v4.list) { idx->netmask.v4.list = cdada_list_create(u_int8_t); idx->netmask.hdlr_no = (idx_hdlr_no + 1); } if (idx->netmask.v4.list) { cdada_list_push_back(idx->netmask.v4.list, &src_e->key.src_net.m.len); } else { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to create Index network masks list. Indexing disabled.\n", config.name, config.type); return TRUE; } } else if (src_e->key.src_net.a.family == AF_INET6) { if (!idx->netmask.v6.list) { idx->netmask.v6.list = cdada_list_create(u_int8_t); idx->netmask.hdlr_no = (idx_hdlr_no + 1); } if (idx->netmask.v6.list) { cdada_list_push_back(idx->netmask.v6.list, &src_e->key.src_net.m.len); } else { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to create Index network masks list. Indexing disabled.\n", config.name, config.type); return TRUE; } } return FALSE; } int PT_map_index_entries_dst_net_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.dst_net.a, sizeof(struct host_addr), TRUE); hash_serial_append(hash_serializer, (char *)&src_e->key.dst_net.m.len, sizeof(src_e->key.dst_net.m.len), TRUE); if (idx->netmask.hdlr_no) { if (idx->netmask.hdlr_no != (idx_hdlr_no + 1)) { Log(LOG_WARNING, "WARN ( %s/%s ): Index network masks count exceeded. Indexing disabled.\n", config.name, config.type); return TRUE; } } if (src_e->key.dst_net.a.family == AF_INET) { if (!idx->netmask.v4.list) { idx->netmask.v4.list = cdada_list_create(u_int8_t); idx->netmask.hdlr_no = (idx_hdlr_no + 1); } if (idx->netmask.v4.list) { cdada_list_push_back(idx->netmask.v4.list, &src_e->key.dst_net.m.len); } else { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to create Index network masks list. Indexing disabled.\n", config.name, config.type); return TRUE; } } else if (src_e->key.dst_net.a.family == AF_INET6) { if (!idx->netmask.v6.list) { idx->netmask.v6.list = cdada_list_create(u_int8_t); idx->netmask.hdlr_no = (idx_hdlr_no + 1); } if (idx->netmask.v6.list) { cdada_list_push_back(idx->netmask.v6.list, &src_e->key.dst_net.m.len); } else { Log(LOG_WARNING, "WARN ( %s/%s ): Unable to create Index network masks list. Indexing disabled.\n", config.name, config.type); return TRUE; } } return FALSE; } int PT_map_index_entries_is_multicast_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.is_multicast.n, sizeof(u_int8_t), TRUE); return FALSE; } int PT_map_index_entries_fwd_status_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.fwd_status.n, sizeof(u_int8_t), TRUE); return FALSE; } int PT_map_index_entries_null_handler(struct id_table_index *idx, int idx_hdlr_no, pm_hash_serial_t *hash_serializer, void *src) { struct id_entry *src_e = (struct id_entry *) src; if (!idx || !hash_serializer || !src_e) return TRUE; hash_serial_append(hash_serializer, (char *)&src_e->key.null.n, sizeof(u_int8_t), TRUE); return FALSE; } int PT_map_index_fdata_ip_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent; SFSample *sample = (SFSample *)pptrs->f_data; u_int16_t port; if (config.acct_type == ACCT_NF) { sa_to_addr((struct sockaddr *)sa, &e->key.agent_ip.a, &port); } else if (config.acct_type == ACCT_SF) { if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V4) { e->key.agent_ip.a.family = AF_INET; e->key.agent_ip.a.address.ipv4.s_addr = sample->agent_addr.address.ip_v4.s_addr; } else if (sample->agent_addr.type == SFLADDRESSTYPE_IP_V6) { e->key.agent_ip.a.family = AF_INET6; memcpy(e->key.agent_ip.a.address.ipv6.s6_addr, sample->agent_addr.address.ip_v6.s6_addr, 16); } } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.agent_ip.a, sizeof(struct host_addr), FALSE); return FALSE; } int PT_map_index_fdata_input_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; if (config.acct_type == ACCT_NF) { u_int16_t iface16 = 0; u_int32_t iface32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_INPUT_SNMP].len == 2) { memcpy(&iface16, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, 2); e->key.input.n = ntohs(iface16); } else if (tpl->tpl[NF9_INPUT_SNMP].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_INPUT_SNMP].off, 4); e->key.input.n = ntohl(iface32); } else if (tpl->tpl[NF9_INPUT_PHYSINT].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_INPUT_PHYSINT].off, 4); e->key.input.n = ntohl(iface32); } break; case 5: iface16 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->input); e->key.input.n = iface16; break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.input.n = sample->inputPort; } else if (config.acct_type == ACCT_PM) { e->key.input.n = pptrs->ifindex_in; } hash_serial_append(hash_serializer, (char *)&e->key.input.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_output_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; if (config.acct_type == ACCT_NF) { u_int16_t iface16 = 0; u_int32_t iface32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_OUTPUT_SNMP].len == 2) { memcpy(&iface16, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, 2); e->key.output.n = ntohs(iface16); } else if (tpl->tpl[NF9_OUTPUT_SNMP].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_SNMP].off, 4); e->key.output.n = ntohl(iface32); } else if (tpl->tpl[NF9_OUTPUT_PHYSINT].len == 4) { memcpy(&iface32, pptrs->f_data+tpl->tpl[NF9_OUTPUT_PHYSINT].off, 4); e->key.output.n = ntohl(iface32); } break; case 5: iface16 = ntohs(((struct struct_export_v5 *) pptrs->f_data)->output); e->key.output.n = iface16; break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.output.n = sample->outputPort; } else if (config.acct_type == ACCT_PM) { e->key.output.n = pptrs->ifindex_out; } hash_serial_append(hash_serializer, (char *)&e->key.output.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_bgp_nexthop_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; if (evaluate_lm_method(pptrs, TRUE, config.nfacctd_net, NF_NET_BGP)) { if (dst_ret) { if (pptrs->bgp_nexthop_info) info = (struct bgp_info *) pptrs->bgp_nexthop_info; else info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { memcpy(&e->key.bgp_nexthop.a, &info->attr->mp_nexthop, HostAddrSz); } else if (info->attr->mp_nexthop.family == AF_INET6) { memcpy(&e->key.bgp_nexthop.a, &info->attr->mp_nexthop, HostAddrSz); } else { e->key.bgp_nexthop.a.address.ipv4.s_addr = info->attr->nexthop.s_addr; e->key.bgp_nexthop.a.family = AF_INET; } } } } else if (evaluate_lm_method(pptrs, TRUE, config.nfacctd_net, NF_NET_KEEP)) { if (config.acct_type == ACCT_NF) { switch(hdr->version) { case 10: case 9: if (pptrs->l3_proto == ETHERTYPE_IP) { if (tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len) { memcpy(&e->key.bgp_nexthop.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].off, MIN(tpl->tpl[NF9_BGP_IPV4_NEXT_HOP].len, 4)); e->key.bgp_nexthop.a.family = AF_INET; } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len) { memcpy(&e->key.bgp_nexthop.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].off, MIN(tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len, 4)); e->key.bgp_nexthop.a.family = AF_INET; } } else if (pptrs->l3_proto == ETHERTYPE_IPV6) { if (tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len) { memcpy(&e->key.bgp_nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].off, MIN(tpl->tpl[NF9_BGP_IPV6_NEXT_HOP].len, 16)); e->key.bgp_nexthop.a.family = AF_INET6; } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len) { memcpy(&e->key.bgp_nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].off, MIN(tpl->tpl[NF9_MPLS_TOP_LABEL_ADDR].len, 4)); e->key.bgp_nexthop.a.family = AF_INET; } else if (tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len) { memcpy(&e->key.bgp_nexthop.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].off, MIN(tpl->tpl[NF9_MPLS_TOP_LABEL_IPV6_ADDR].len, 16)); e->key.bgp_nexthop.a.family = AF_INET6; } } } } else if (config.acct_type == ACCT_SF) { if (sample->gotIPV4) { e->key.bgp_nexthop.a.family = AF_INET; e->key.bgp_nexthop.a.address.ipv4.s_addr = sample->bgp_nextHop.address.ip_v4.s_addr; } else if (sample->gotIPV6) { e->key.bgp_nexthop.a.family = AF_INET6; memcpy(&e->key.bgp_nexthop.a.address.ipv6, &sample->bgp_nextHop.address.ip_v6, IP6AddrSz); } } else return TRUE; } hash_serial_append(hash_serializer, (char *)&e->key.bgp_nexthop.a, sizeof(struct host_addr), FALSE); return FALSE; } int PT_map_index_fdata_src_as_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; if (src_ret && evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr && info->attr->aspath) { e->key.src_as.n = evaluate_last_asn(info->attr->aspath); } } else if (evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_KEEP)) { if (config.acct_type == ACCT_NF) { u_int16_t asn16 = 0; u_int32_t asn32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_SRC_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 2); e->key.src_as.n = ntohs(asn16); } else if (tpl->tpl[NF9_SRC_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_SRC_AS].off, 4); e->key.src_as.n = ntohl(asn32); } break; case 5: e->key.src_as.n = ntohs(((struct struct_export_v5 *) pptrs->f_data)->src_as); break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.src_as.n = sample->src_as; } else return TRUE; } hash_serial_append(hash_serializer, (char *)&e->key.src_as.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_dst_as_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; if (dst_ret && evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr && info->attr->aspath) { e->key.dst_as.n = evaluate_last_asn(info->attr->aspath); } } else if (evaluate_lm_method(pptrs, TRUE, config.nfacctd_as, NF_AS_KEEP)) { if (config.acct_type == ACCT_NF) { u_int16_t asn16 = 0; u_int32_t asn32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DST_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 2); e->key.dst_as.n = ntohs(asn16); } else if (tpl->tpl[NF9_DST_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_DST_AS].off, 4); e->key.dst_as.n = ntohl(asn32); } break; case 5: e->key.dst_as.n = ntohs(((struct struct_export_v5 *) pptrs->f_data)->dst_as); break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.dst_as.n = sample->dst_as; } } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.dst_as.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_peer_src_as_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; struct bgp_node *src_ret = (struct bgp_node *) pptrs->bgp_src; struct bgp_info *info; if (config.bgp_daemon_peer_as_src_type & BGP_SRC_PRIMITIVES_MAP) { e->key.peer_src_as.n = pptrs->bpas; } else { if (src_ret && evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_src_info; if (info && info->attr && info->attr->aspath) { e->key.peer_src_as.n = evaluate_first_asn(info->attr->aspath->str); } } else if (evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_KEEP)) { if (config.acct_type == ACCT_NF) { u_int16_t asn16 = 0; u_int32_t asn32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PEER_SRC_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_PEER_SRC_AS].off, 2); e->key.peer_src_as.n = ntohs(asn16); } else if (tpl->tpl[NF9_PEER_SRC_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_PEER_SRC_AS].off, 4); e->key.peer_src_as.n = ntohl(asn32); } break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.peer_src_as.n = sample->src_peer_as; } else return TRUE; } } hash_serial_append(hash_serializer, (char *)&e->key.peer_src_as.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_peer_dst_as_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; if (dst_ret && evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_BGP)) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr && info->attr->aspath) { e->key.peer_dst_as.n = evaluate_first_asn(info->attr->aspath->str); } } else if (evaluate_lm_method(pptrs, FALSE, config.nfacctd_as, NF_AS_KEEP)) { if (config.acct_type == ACCT_NF) { u_int16_t asn16 = 0; u_int32_t asn32 = 0; switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PEER_DST_AS].len == 2) { memcpy(&asn16, pptrs->f_data+tpl->tpl[NF9_PEER_DST_AS].off, 2); e->key.peer_dst_as.n = ntohs(asn16); } else if (tpl->tpl[NF9_PEER_DST_AS].len == 4) { memcpy(&asn32, pptrs->f_data+tpl->tpl[NF9_PEER_DST_AS].off, 4); e->key.peer_dst_as.n = ntohl(asn32); } break; default: break; } } else if (config.acct_type == ACCT_SF) { e->key.peer_dst_as.n = sample->dst_peer_as; } else return TRUE; } hash_serial_append(hash_serializer, (char *)&e->key.peer_dst_as.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_mpls_vpn_rd_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct bgp_node *dst_ret = (struct bgp_node *) pptrs->bgp_dst; struct bgp_info *info; /* if bitr is populate we infer non-zero config.nfacctd_flow_to_rd_map */ if (pptrs->bitr) memcpy(&e->key.mpls_vpn_rd.rd, &pptrs->bitr, sizeof(rd_t)); else { /* XXX: no src_ret lookup? */ if (dst_ret) { info = (struct bgp_info *) pptrs->bgp_dst_info; if (info && info->attr_extra) memcpy(&e->key.mpls_vpn_rd.rd, &info->attr_extra->rd, sizeof(rd_t)); } } hash_serial_append(hash_serializer, (char *)&e->key.mpls_vpn_rd.rd, sizeof(rd_t), FALSE); return FALSE; } int PT_map_index_fdata_mpls_pw_id_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; u_int32_t tmp32 = 0; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_PSEUDOWIREID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_PSEUDOWIREID].off, 4); e->key.mpls_pw_id.n = ntohl(tmp32); } } } else if (config.acct_type == ACCT_SF) { e->key.mpls_pw_id.n = sample->mpls_vll_vc_id; } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.mpls_pw_id.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_mpls_vpn_id_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t tmp32 = 0; if (config.acct_type == ACCT_NF) { switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_INGRESS_VRFID].len) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_INGRESS_VRFID].off, MIN(tpl->tpl[NF9_INGRESS_VRFID].len, 4)); e->key.mpls_vpn_id.n = ntohl(tmp32); } if (tpl->tpl[NF9_EGRESS_VRFID].len && !e->key.mpls_vpn_id.n) { memcpy(&tmp32, pptrs->f_data+tpl->tpl[NF9_EGRESS_VRFID].off, MIN(tpl->tpl[NF9_EGRESS_VRFID].len, 4)); e->key.mpls_vpn_id.n = ntohl(tmp32); } } } hash_serial_append(hash_serializer, (char *)&e->key.mpls_vpn_id.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_mpls_label_bottom_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; if (config.acct_type == ACCT_NF) { int label_idx; switch(hdr->version) { case 10: case 9: for (label_idx = NF9_MPLS_LABEL_1; label_idx <= NF9_MPLS_LABEL_9; label_idx++) { if (tpl->tpl[label_idx].len == 3 && check_bosbit(pptrs->f_data+tpl->tpl[label_idx].off)) { e->key.mpls_label_bottom.n = decode_mpls_label(pptrs->f_data+tpl->tpl[label_idx].off); break; } } break; } } hash_serial_append(hash_serializer, (char *)&e->key.mpls_label_bottom.n, sizeof(u_int32_t), FALSE); return FALSE; } int PT_map_index_fdata_src_mac_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_SRC_MAC].len) { memcpy(&e->key.src_mac.a, pptrs->f_data+tpl->tpl[NF9_IN_SRC_MAC].off, MIN(tpl->tpl[NF9_IN_SRC_MAC].len, 6)); } } } else if (config.acct_type == ACCT_SF) { memcpy(&e->key.src_mac.a, sample->eth_src, ETH_ADDR_LEN); } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.src_mac.a, ETH_ADDR_LEN, FALSE); return FALSE; } int PT_map_index_fdata_dst_mac_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_DST_MAC].len) { memcpy(&e->key.dst_mac.a, pptrs->f_data+tpl->tpl[NF9_IN_DST_MAC].off, MIN(tpl->tpl[NF9_IN_DST_MAC].len, 6)); } } } else if (config.acct_type == ACCT_SF) { memcpy(&e->key.dst_mac.a, sample->eth_dst, ETH_ADDR_LEN); } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.dst_mac.a, ETH_ADDR_LEN, FALSE); return FALSE; } int PT_map_index_fdata_vlan_id_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; u_int16_t tmp16 = 0; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_VLAN].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_IN_VLAN].off, MIN(tpl->tpl[NF9_IN_VLAN].len, 2)); } else if (tpl->tpl[NF9_DOT1QVLANID].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_DOT1QVLANID].off, MIN(tpl->tpl[NF9_DOT1QVLANID].len, 2)); } e->key.vlan_id.n = ntohs(tmp16); } } else if (config.acct_type == ACCT_SF) { if (sample->in_vlan) e->key.vlan_id.n = sample->in_vlan; else if (sample->out_vlan) e->key.vlan_id.n = sample->out_vlan; } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.vlan_id.n, sizeof(u_int16_t), FALSE); return FALSE; } int PT_map_index_fdata_cvlan_id_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int16_t tmp16 = 0; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_DOT1QCVLANID].len) { memcpy(&tmp16, pptrs->f_data+tpl->tpl[NF9_DOT1QCVLANID].off, MIN(tpl->tpl[NF9_DOT1QCVLANID].len, 2)); e->key.cvlan_id.n = ntohs(tmp16); } } } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.cvlan_id.n, sizeof(u_int16_t), FALSE); return FALSE; } int PT_map_index_fdata_src_net_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *sf_addr = &sample->ipsrc; u_int8_t netmask; int ret; if (config.acct_type == ACCT_NF) { switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IPV4_SRC_ADDR].len) { memcpy(&e->key.src_net.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV4_SRC_ADDR].len, 4)); e->key.src_net.a.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_SRC_PREFIX].len) { memcpy(&e->key.src_net.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_SRC_PREFIX].len, 4)); e->key.src_net.a.family = AF_INET; } if (tpl->tpl[NF9_IPV6_SRC_ADDR].len) { memcpy(&e->key.src_net.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_ADDR].off, MIN(tpl->tpl[NF9_IPV6_SRC_ADDR].len, 16)); e->key.src_net.a.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_SRC_PREFIX].len) { memcpy(&e->key.src_net.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_SRC_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_SRC_PREFIX].len, 16)); e->key.src_net.a.family = AF_INET6; } break; case 5: e->key.src_net.a.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->srcaddr.s_addr; e->key.src_net.a.family = AF_INET; break; } } else if (config.acct_type == ACCT_SF) { if (sample->gotIPV4) { e->key.src_net.a.address.ipv4.s_addr = sample->dcd_srcIP.s_addr; e->key.src_net.a.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&e->key.src_net.a.address.ipv6, &sf_addr->address.ip_v6, IP6AddrSz); e->key.src_net.a.family = AF_INET6; } } else return TRUE; if (idx_netmask >= 0 && idx->netmask.hdlr_no == (idx_hdlr + 1)) { if (e->key.src_net.a.family == AF_INET) { ret = cdada_list_get(idx->netmask.v4.list, idx_netmask, &netmask); } else if (e->key.src_net.a.family == AF_INET6) { ret = cdada_list_get(idx->netmask.v6.list, idx_netmask, &netmask); } if (ret == CDADA_SUCCESS) { e->key.src_net.m.family = e->key.src_net.a.family; e->key.src_net.m.len = netmask; apply_addr_mask(&e->key.src_net.a, &e->key.src_net.m); } } hash_serial_append(hash_serializer, (char *)&e->key.src_net.a, sizeof(struct host_addr), FALSE); hash_serial_append(hash_serializer, (char *)&e->key.src_net.m.len, sizeof(e->key.src_net.m.len), FALSE); return FALSE; } int PT_map_index_fdata_dst_net_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; SFLAddress *sf_addr = &sample->ipdst; u_int8_t netmask; int ret; if (config.acct_type == ACCT_NF) { switch(hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IPV4_DST_ADDR].len) { memcpy(&e->key.dst_net.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV4_DST_ADDR].len, 4)); e->key.dst_net.a.family = AF_INET; } else if (tpl->tpl[NF9_IPV4_DST_PREFIX].len) { memcpy(&e->key.dst_net.a.address.ipv4, pptrs->f_data+tpl->tpl[NF9_IPV4_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV4_DST_PREFIX].len, 4)); e->key.dst_net.a.family = AF_INET; } if (tpl->tpl[NF9_IPV6_DST_ADDR].len) { memcpy(&e->key.dst_net.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_ADDR].off, MIN(tpl->tpl[NF9_IPV6_DST_ADDR].len, 16)); e->key.dst_net.a.family = AF_INET6; } else if (tpl->tpl[NF9_IPV6_DST_PREFIX].len) { memcpy(&e->key.dst_net.a.address.ipv6, pptrs->f_data+tpl->tpl[NF9_IPV6_DST_PREFIX].off, MIN(tpl->tpl[NF9_IPV6_DST_PREFIX].len, 16)); e->key.dst_net.a.family = AF_INET6; } break; case 5: e->key.dst_net.a.address.ipv4.s_addr = ((struct struct_export_v5 *) pptrs->f_data)->dstaddr.s_addr; e->key.dst_net.a.family = AF_INET; break; } } else if (config.acct_type == ACCT_SF) { if (sample->gotIPV4) { e->key.dst_net.a.address.ipv4.s_addr = sample->dcd_dstIP.s_addr; e->key.dst_net.a.family = AF_INET; } else if (sample->gotIPV6) { memcpy(&e->key.dst_net.a.address.ipv6, &sf_addr->address.ip_v6, IP6AddrSz); e->key.dst_net.a.family = AF_INET6; } } else return TRUE; if (idx_netmask >= 0 && idx->netmask.hdlr_no == (idx_hdlr + 1)) { if (e->key.dst_net.a.family == AF_INET) { ret = cdada_list_get(idx->netmask.v4.list, idx_netmask, &netmask); } else if (e->key.dst_net.a.family == AF_INET6) { ret = cdada_list_get(idx->netmask.v6.list, idx_netmask, &netmask); } if (ret == CDADA_SUCCESS) { e->key.dst_net.m.family = e->key.dst_net.a.family; e->key.dst_net.m.len = netmask; apply_addr_mask(&e->key.dst_net.a, &e->key.dst_net.m); } } hash_serial_append(hash_serializer, (char *)&e->key.dst_net.a, sizeof(struct host_addr), FALSE); hash_serial_append(hash_serializer, (char *)&e->key.dst_net.m.len, sizeof(e->key.dst_net.m.len), FALSE); return FALSE; } int PT_map_index_fdata_is_multicast_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; SFSample *sample = (SFSample *) pptrs->f_data; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_IN_DST_MAC].len) { e->key.is_multicast.n = IS_MAC_MULTICAST(pptrs->f_data+tpl->tpl[NF9_IN_DST_MAC].off); } break; default: break; /* this field does not exist */ } } else if (config.acct_type == ACCT_SF) { e->key.is_multicast.n = IS_MAC_MULTICAST(sample->eth_dst); } hash_serial_append(hash_serializer, (char *)&e->key.is_multicast, sizeof(u_int8_t), FALSE); return FALSE; } int PT_map_index_fdata_fwd_status_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { struct packet_ptrs *pptrs = (struct packet_ptrs *) src; struct struct_header_v5 *hdr = (struct struct_header_v5 *) pptrs->f_header; struct template_cache_entry *tpl = (struct template_cache_entry *) pptrs->f_tpl; u_int32_t fwd_status = 0; if (config.acct_type == ACCT_NF) { switch (hdr->version) { case 10: case 9: if (tpl->tpl[NF9_FWD_STATUS].len == 1) { memcpy(&fwd_status, pptrs->f_data+tpl->tpl[NF9_FWD_STATUS].off, MIN(tpl->tpl[NF9_FWD_STATUS].len, 1)); e->key.fwd_status.n = fwd_status; } } } else return TRUE; hash_serial_append(hash_serializer, (char *)&e->key.fwd_status.n, sizeof(u_int8_t), FALSE); return FALSE; } int PT_map_index_fdata_null_handler(struct id_table_index *idx, int idx_hdlr, int idx_netmask, struct id_entry *e, pm_hash_serial_t *hash_serializer, void *src) { e->key.null.n = 0; hash_serial_append(hash_serializer, (char *)&e->key.null.n, sizeof(u_int8_t), FALSE); return FALSE; } void pm_pcap_interfaces_map_validate(char *filename, struct plugin_requests *req) { struct pm_pcap_interfaces *table = (struct pm_pcap_interfaces *) req->key_value_table; int valid = FALSE; if (table && table->list) { if (strlen(table->list[table->num].ifname)) { if (config.pcap_ifindex == PCAP_IFINDEX_MAP) { if (table->list[table->num].ifindex) { valid = TRUE; } } else { valid = TRUE; } } if (valid) { table->num++; } else { Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Invalid entry: ifname=%s\n", config.name, config.type, filename, table->list[table->num].ifname); memset(&table->list[table->num], 0, sizeof(struct pm_pcap_interface)); } } } int pm_pcap_interfaces_map_ifindex_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct pm_pcap_interfaces *table = (struct pm_pcap_interfaces *) req->key_value_table; char *endp; if (table && table->list) { if (table->num < PCAP_MAX_INTERFACES) { table->list[table->num].ifindex = strtoul(value, &endp, 10); if (!table->list[table->num].ifindex) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] invalid 'ifindex' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] maximum entries (%u) reached.\n", config.name, config.type, filename, PCAP_MAX_INTERFACES); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] pcap_interfaces_map not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int pm_pcap_interfaces_map_ifname_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct pm_pcap_interfaces *table = (struct pm_pcap_interfaces *) req->key_value_table; if (table && table->list) { if (table->num < PCAP_MAX_INTERFACES) { strncpy(table->list[table->num].ifname, value, IFNAMSIZ); if (!strlen(table->list[table->num].ifname)) { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] invalid 'ifname' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] maximum entries (%u) reached.\n", config.name, config.type, filename, PCAP_MAX_INTERFACES); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] pcap_interfaces_map not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } int pm_pcap_interfaces_map_direction_handler(char *filename, struct id_entry *e, char *value, struct plugin_requests *req, int acct_type) { struct pm_pcap_interfaces *table = (struct pm_pcap_interfaces *) req->key_value_table; if (table && table->list) { if (table->num < PCAP_MAX_INTERFACES) { lower_string(value); if (!strncmp(value, "in", strlen("in"))) table->list[table->num].direction = PCAP_D_IN; else if (!strncmp(value, "out", strlen("out"))) table->list[table->num].direction = PCAP_D_OUT; else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] invalid 'direction' value: '%s'.\n", config.name, config.type, filename, value); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] maximum entries (%u) reached.\n", config.name, config.type, filename, PCAP_MAX_INTERFACES); return TRUE; } } else { Log(LOG_ERR, "ERROR ( %s/%s ): [%s] pcap_interfaces_map not allocated.\n", config.name, config.type, filename); return TRUE; } return FALSE; } void pm_pcap_interfaces_map_initialize(struct pm_pcap_interfaces *map) { memset(map, 0, sizeof(struct pm_pcap_interfaces)); /* Setting up the list */ map->list = malloc((PCAP_MAX_INTERFACES) * sizeof(struct pm_pcap_interface)); if (!map->list) { Log(LOG_ERR, "ERROR ( %s/%s ): unable to allocate pcap_interfaces_map. Exiting ...\n", config.name, config.type); exit_gracefully(1); } else memset(map->list, 0, (PCAP_MAX_INTERFACES) * sizeof(struct pm_pcap_interface)); } void pm_pcap_interfaces_map_load(struct pm_pcap_interfaces *map) { struct plugin_requests req; int pm_pcap_interfaces_allocated = FALSE; memset(&req, 0, sizeof(req)); req.key_value_table = (void *) map; load_id_file(MAP_PCAP_INTERFACES, config.pcap_interfaces_map, NULL, &req, &pm_pcap_interfaces_allocated); } void pm_pcap_interfaces_map_destroy(struct pm_pcap_interfaces *map) { int idx; for (idx = 0; idx < map->num; idx++) memset(&map->list[idx], 0, sizeof(struct pm_pcap_interface)); map->num = 0; } void pm_pcap_interfaces_map_copy(struct pm_pcap_interfaces *dst, struct pm_pcap_interfaces *src) { int idx; for (idx = 0; idx < src->num; idx++) memcpy(&dst->list[idx], &src->list[idx], sizeof(struct pm_pcap_interface)); dst->num = src->num; } u_int32_t pm_pcap_interfaces_map_lookup_ifname(struct pm_pcap_interfaces *map, char *ifname) { u_int32_t ifindex = 0; int idx; for (idx = 0; idx < map->num; idx++) { if (strlen(map->list[idx].ifname) == strlen(ifname) && !strncmp(map->list[idx].ifname, ifname, strlen(ifname))) { ifindex = map->list[idx].ifindex; break; } } return ifindex; } struct pm_pcap_interface *pm_pcap_interfaces_map_getentry_by_ifname(struct pm_pcap_interfaces *map, char *ifname) { int idx; for (idx = 0; idx < map->num; idx++) { if (strlen(map->list[idx].ifname) == strlen(ifname) && !strncmp(map->list[idx].ifname, ifname, strlen(ifname))) { return &map->list[idx]; } } return NULL; } struct pm_pcap_interface *pm_pcap_interfaces_map_getentry_by_idx(struct pm_pcap_interfaces *map, int idx) { if (idx < map->num) { return &map->list[idx]; } return NULL; } char *pm_pcap_interfaces_map_getnext_ifname(struct pm_pcap_interfaces *map, int *index) { char *ifname = NULL; int loc_idx = (*index); if (loc_idx < map->num) { ifname = map->list[loc_idx].ifname; loc_idx++; (*index) = loc_idx; } return ifname; } char *pm_pcap_interfaces_map_get_ifname(struct pm_pcap_interfaces *map, int index) { char *ifname = NULL; if (index < map->num) { ifname = map->list[index].ifname; } return ifname; } int pm_pcap_interfaces_map_get_direction(struct pm_pcap_interfaces *map, int index) { int direction = 0; if (index < map->num) { direction = map->list[index].direction; } return direction; } pmacct-1.7.8/src/cfg.c0000644000175000017500000015350014354105275013510 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "plugin_hooks.h" #include "pmacct-data.h" #include "pkt_handlers.h" static const struct _dictionary_line dictionary[] = { {"debug", cfg_key_debug}, {"debug_internal_msg", cfg_key_debug_internal_msg}, {"syslog", cfg_key_syslog}, {"logfile", cfg_key_logfile}, {"pidfile", cfg_key_pidfile}, {"daemonize", cfg_key_daemonize}, {"aggregate", cfg_key_aggregate}, {"aggregate_primitives", cfg_key_aggregate_primitives}, {"cluster_name", cfg_key_cluster_name}, {"cluster_id", cfg_key_cluster_id}, {"redis_host", cfg_key_redis_host}, {"redis_db", cfg_key_redis_db}, {"snaplen", cfg_key_snaplen}, {"propagate_signals", cfg_key_propagate_signals}, {"aggregate_filter", cfg_key_aggregate_filter}, {"aggregate_unknown_etype", cfg_key_aggregate_unknown_etype}, {"dtls_path", cfg_key_dtls_path}, {"writer_id_string", cfg_key_writer_id_string}, {"promisc", cfg_key_promisc}, {"pcap_filter", cfg_key_pcap_filter}, {"pcap_protocol", cfg_key_pcap_protocol}, {"pcap_savefile", cfg_key_pcap_savefile}, {"pcap_savefile_wait", cfg_key_pcap_savefile_wait}, {"pcap_savefile_delay", cfg_key_pcap_savefile_delay}, {"pcap_savefile_replay", cfg_key_pcap_savefile_replay}, {"pcap_interface", cfg_key_pcap_interface}, {"pcap_interface_wait", cfg_key_pcap_interface_wait}, {"pcap_direction", cfg_key_pcap_direction}, {"pcap_ifindex", cfg_key_pcap_ifindex}, {"pcap_interfaces_map", cfg_key_pcap_interfaces_map}, {"pcap_arista_trailer_offset", cfg_key_pcap_arista_trailer_offset}, {"pcap_arista_trailer_flag_value", cfg_key_pcap_arista_trailer_flag_value}, {"core_proc_name", cfg_key_proc_name}, {"proc_priority", cfg_key_proc_priority}, {"pmacctd_as", cfg_key_nfacctd_as_new}, {"uacctd_as", cfg_key_nfacctd_as_new}, {"pmacctd_net", cfg_key_nfacctd_net}, {"uacctd_net", cfg_key_nfacctd_net}, {"use_ip_next_hop", cfg_key_use_ip_next_hop}, {"thread_stack", cfg_key_thread_stack}, {"plugins", NULL}, {"plugin_pipe_size", cfg_key_plugin_pipe_size}, {"plugin_buffer_size", cfg_key_plugin_buffer_size}, {"plugin_pipe_zmq", cfg_key_plugin_pipe_zmq}, {"plugin_pipe_zmq_retry", cfg_key_plugin_pipe_zmq_retry}, {"plugin_pipe_zmq_profile", cfg_key_plugin_pipe_zmq_profile}, {"plugin_pipe_zmq_hwm", cfg_key_plugin_pipe_zmq_hwm}, {"plugin_exit_any", cfg_key_plugin_exit_any}, {"files_umask", cfg_key_files_umask}, {"files_uid", cfg_key_files_uid}, {"files_gid", cfg_key_files_gid}, {"networks_mask", cfg_key_networks_mask}, {"networks_file", cfg_key_networks_file}, {"networks_file_filter", cfg_key_networks_file_filter}, {"networks_file_no_lpm", cfg_key_networks_file_no_lpm}, {"networks_no_mask_if_zero", cfg_key_networks_no_mask_if_zero}, {"networks_cache_entries", cfg_key_networks_cache_entries}, {"ports_file", cfg_key_ports_file}, {"protos_file", cfg_key_protos_file}, {"tos_file", cfg_key_tos_file}, {"timestamps_rfc3339", cfg_key_timestamps_rfc3339}, {"timestamps_utc", cfg_key_timestamps_utc}, {"timestamps_secs", cfg_key_timestamps_secs}, {"timestamps_since_epoch", cfg_key_timestamps_since_epoch}, {"tcpflags_encode_as_array", cfg_key_tcpflags_encode_as_array}, {"fwd_status_encode_as_string", cfg_key_fwd_status_encode_as_string}, {"tos_encode_as_dscp", cfg_key_tos_encode_as_dscp}, {"imt_path", cfg_key_imt_path}, {"imt_passwd", cfg_key_imt_passwd}, {"imt_buckets", cfg_key_imt_buckets}, {"imt_mem_pools_number", cfg_key_imt_mem_pools_number}, {"imt_mem_pools_size", cfg_key_imt_mem_pools_size}, {"sql_db", cfg_key_sql_db}, {"sql_table", cfg_key_sql_table}, {"sql_table_schema", cfg_key_sql_table_schema}, {"sql_table_version", cfg_key_sql_table_version}, {"sql_table_type", cfg_key_sql_table_type}, {"sql_conn_ca_file", cfg_key_sql_conn_ca_file}, {"sql_host", cfg_key_sql_host}, {"sql_port", cfg_key_sql_port}, {"sql_data", cfg_key_sql_data}, {"sql_user", cfg_key_sql_user}, {"sql_passwd", cfg_key_sql_passwd}, {"sql_refresh_time", cfg_key_sql_refresh_time}, {"sql_startup_delay", cfg_key_sql_startup_delay}, {"sql_optimize_clauses", cfg_key_sql_optimize_clauses}, {"sql_history", cfg_key_sql_history}, {"sql_history_offset", cfg_key_sql_history_offset}, {"sql_history_roundoff", cfg_key_sql_history_roundoff}, {"sql_backup_host", cfg_key_sql_recovery_backup_host}, /* Legacy feature */ {"sql_recovery_backup_host", cfg_key_sql_recovery_backup_host}, {"sql_delimiter", cfg_key_sql_delimiter}, {"sql_max_writers", cfg_key_dump_max_writers}, {"sql_trigger_exec", cfg_key_sql_trigger_exec}, {"sql_trigger_time", cfg_key_sql_trigger_time}, {"sql_cache_entries", cfg_key_sql_cache_entries}, {"sql_dont_try_update", cfg_key_sql_dont_try_update}, {"sql_preprocess", cfg_key_sql_preprocess}, {"sql_preprocess_type", cfg_key_sql_preprocess_type}, {"sql_multi_values", cfg_key_sql_multi_values}, {"sql_locking_style", cfg_key_sql_locking_style}, {"sql_use_copy", cfg_key_sql_use_copy}, {"sql_num_protos", cfg_key_num_protos}, {"sql_num_hosts", cfg_key_num_hosts}, {"print_refresh_time", cfg_key_sql_refresh_time}, {"print_cache_entries", cfg_key_print_cache_entries}, {"print_markers", cfg_key_print_markers}, {"print_output", cfg_key_print_output}, {"print_output_file", cfg_key_print_output_file}, {"print_output_file_append", cfg_key_print_output_file_append}, {"print_output_lock_file", cfg_key_print_output_lock_file}, {"print_output_separator", cfg_key_print_output_separator}, {"print_output_custom_lib", cfg_key_print_output_custom_lib}, {"print_output_custom_cfg_file", cfg_key_print_output_custom_cfg_file}, {"print_write_empty_file", cfg_key_print_write_empty_file}, {"print_latest_file", cfg_key_print_latest_file}, {"print_num_protos", cfg_key_num_protos}, {"print_trigger_exec", cfg_key_sql_trigger_exec}, {"print_history", cfg_key_sql_history}, {"print_history_offset", cfg_key_sql_history_offset}, {"print_history_roundoff", cfg_key_sql_history_roundoff}, {"print_max_writers", cfg_key_dump_max_writers}, {"print_preprocess", cfg_key_sql_preprocess}, {"print_preprocess_type", cfg_key_sql_preprocess_type}, {"print_startup_delay", cfg_key_sql_startup_delay}, {"mongo_host", cfg_key_sql_host}, {"mongo_table", cfg_key_sql_table}, {"mongo_user", cfg_key_sql_user}, {"mongo_passwd", cfg_key_sql_passwd}, {"mongo_refresh_time", cfg_key_sql_refresh_time}, {"mongo_cache_entries", cfg_key_print_cache_entries}, {"mongo_history", cfg_key_sql_history}, {"mongo_history_offset", cfg_key_sql_history_offset}, {"mongo_history_roundoff", cfg_key_sql_history_roundoff}, {"mongo_time_roundoff", cfg_key_sql_history_roundoff}, {"mongo_trigger_exec", cfg_key_sql_trigger_exec}, {"mongo_insert_batch", cfg_key_mongo_insert_batch}, {"mongo_indexes_file", cfg_key_sql_table_schema}, {"mongo_max_writers", cfg_key_dump_max_writers}, {"mongo_preprocess", cfg_key_sql_preprocess}, {"mongo_preprocess_type", cfg_key_sql_preprocess_type}, {"mongo_startup_delay", cfg_key_sql_startup_delay}, {"mongo_num_protos", cfg_key_num_protos}, {"avro_buffer_size", cfg_key_avro_buffer_size}, {"avro_schema_output_file", cfg_key_avro_schema_file}, /* to be discontinued */ {"avro_schema_file", cfg_key_avro_schema_file}, {"amqp_refresh_time", cfg_key_sql_refresh_time}, {"amqp_history", cfg_key_sql_history}, {"amqp_history_offset", cfg_key_sql_history_offset}, {"amqp_history_roundoff", cfg_key_sql_history_roundoff}, {"amqp_time_roundoff", cfg_key_sql_history_roundoff}, {"amqp_host", cfg_key_sql_host}, {"amqp_user", cfg_key_sql_user}, {"amqp_passwd", cfg_key_sql_passwd}, {"amqp_exchange", cfg_key_sql_db}, {"amqp_exchange_type", cfg_key_amqp_exchange_type}, {"amqp_routing_key", cfg_key_sql_table}, {"amqp_routing_key_rr", cfg_key_amqp_routing_key_rr}, {"amqp_persistent_msg", cfg_key_amqp_persistent_msg}, {"amqp_frame_max", cfg_key_amqp_frame_max}, {"amqp_cache_entries", cfg_key_print_cache_entries}, {"amqp_max_writers", cfg_key_dump_max_writers}, {"amqp_preprocess", cfg_key_sql_preprocess}, {"amqp_preprocess_type", cfg_key_sql_preprocess_type}, {"amqp_startup_delay", cfg_key_sql_startup_delay}, {"amqp_heartbeat_interval", cfg_key_amqp_heartbeat_interval}, {"amqp_multi_values", cfg_key_sql_multi_values}, {"amqp_num_protos", cfg_key_num_protos}, {"amqp_vhost", cfg_key_amqp_vhost}, {"amqp_markers", cfg_key_print_markers}, {"amqp_output", cfg_key_message_broker_output}, {"amqp_avro_schema_routing_key", cfg_key_amqp_avro_schema_routing_key}, /* Legacy feature */ {"amqp_avro_schema_refresh_time", cfg_key_amqp_avro_schema_refresh_time}, /* Legacy feature */ {"amqp_trigger_exec", cfg_key_sql_trigger_exec}, {"kafka_refresh_time", cfg_key_sql_refresh_time}, {"kafka_history", cfg_key_sql_history}, {"kafka_history_offset", cfg_key_sql_history_offset}, {"kafka_history_roundoff", cfg_key_sql_history_roundoff}, {"kafka_broker_host", cfg_key_sql_host}, {"kafka_broker_port", cfg_key_kafka_broker_port}, {"kafka_topic", cfg_key_sql_table}, {"kafka_topic_rr", cfg_key_amqp_routing_key_rr}, {"kafka_partition", cfg_key_kafka_partition}, {"kafka_partition_dynamic", cfg_key_kafka_partition_dynamic}, {"kafka_partition_key", cfg_key_kafka_partition_key}, {"kafka_cache_entries", cfg_key_print_cache_entries}, {"kafka_max_writers", cfg_key_dump_max_writers}, {"kafka_preprocess", cfg_key_sql_preprocess}, {"kafka_preprocess_type", cfg_key_sql_preprocess_type}, {"kafka_startup_delay", cfg_key_sql_startup_delay}, {"kafka_multi_values", cfg_key_sql_multi_values}, {"kafka_num_protos", cfg_key_num_protos}, {"kafka_markers", cfg_key_print_markers}, {"kafka_output", cfg_key_message_broker_output}, {"kafka_avro_schema_registry", cfg_key_kafka_avro_schema_registry}, {"kafka_config_file", cfg_key_kafka_config_file}, {"kafka_trigger_exec", cfg_key_sql_trigger_exec}, {"nfacctd_proc_name", cfg_key_proc_name}, {"nfacctd_port", cfg_key_nfacctd_port}, {"nfacctd_ip", cfg_key_nfacctd_ip}, {"nfacctd_interface", cfg_key_nfacctd_interface}, {"nfacctd_ipv6_only", cfg_key_nfacctd_ipv6_only}, {"nfacctd_rp_ebpf_prog", cfg_key_nfacctd_rp_ebpf_prog}, {"nfacctd_allow_file", cfg_key_nfacctd_allow_file}, {"nfacctd_nonroot", cfg_key_pmacctd_nonroot}, {"nfacctd_time_secs", cfg_key_nfacctd_time_secs}, {"nfacctd_time_new", cfg_key_nfacctd_time_new}, {"nfacctd_as_new", cfg_key_nfacctd_as_new}, {"nfacctd_as", cfg_key_nfacctd_as_new}, {"nfacctd_net", cfg_key_nfacctd_net}, {"nfacctd_mcast_groups", cfg_key_nfacctd_mcast_groups}, {"nfacctd_peer_as", cfg_key_nfprobe_peer_as}, {"nfacctd_pipe_size", cfg_key_nfacctd_pipe_size}, {"nfacctd_pro_rating", cfg_key_nfacctd_pro_rating}, {"nfacctd_templates_file", cfg_key_nfacctd_templates_file}, {"nfacctd_templates_receiver", cfg_key_nfacctd_templates_receiver}, {"nfacctd_templates_port", cfg_key_nfacctd_templates_port}, {"nfacctd_account_options", cfg_key_nfacctd_account_options}, {"nfacctd_stitching", cfg_key_nfacctd_stitching}, {"nfacctd_ext_sampling_rate", cfg_key_pmacctd_ext_sampling_rate}, {"nfacctd_renormalize", cfg_key_sfacctd_renormalize}, {"nfacctd_disable_checks", cfg_key_nfacctd_disable_checks}, {"nfacctd_disable_opt_scope_check", cfg_key_nfacctd_disable_opt_scope_check}, {"nfacctd_kafka_broker_host", cfg_key_nfacctd_kafka_broker_host}, {"nfacctd_kafka_broker_port", cfg_key_nfacctd_kafka_broker_port}, {"nfacctd_kafka_topic", cfg_key_nfacctd_kafka_topic}, {"nfacctd_kafka_config_file", cfg_key_nfacctd_kafka_config_file}, {"nfacctd_zmq_address", cfg_key_nfacctd_zmq_address}, {"nfacctd_dtls_port", cfg_key_nfacctd_dtls_port}, {"mpls_label_stack_encode_as_array", cfg_key_mpls_label_stack_encode_as_array}, {"pmacctd_proc_name", cfg_key_proc_name}, {"pmacctd_force_frag_handling", cfg_key_pmacctd_force_frag_handling}, {"pmacctd_frag_buffer_size", cfg_key_pmacctd_frag_buffer_size}, {"pmacctd_flow_buffer_size", cfg_key_pmacctd_flow_buffer_size}, {"pmacctd_flow_buffer_buckets", cfg_key_pmacctd_flow_buffer_buckets}, {"pmacctd_conntrack_buffer_size", cfg_key_pmacctd_conntrack_buffer_size}, {"pmacctd_flow_lifetime", cfg_key_pmacctd_flow_lifetime}, {"pmacctd_flow_tcp_lifetime", cfg_key_pmacctd_flow_tcp_lifetime}, {"pmacctd_ext_sampling_rate", cfg_key_pmacctd_ext_sampling_rate}, {"pmacctd_pipe_size", cfg_key_nfacctd_pipe_size}, {"pmacctd_stitching", cfg_key_nfacctd_stitching}, {"pmacctd_renormalize", cfg_key_sfacctd_renormalize}, {"pmacctd_nonroot", cfg_key_pmacctd_nonroot}, {"pmacctd_time_new", cfg_key_nfacctd_time_new}, {"uacctd_proc_name", cfg_key_proc_name}, {"uacctd_force_frag_handling", cfg_key_pmacctd_force_frag_handling}, {"uacctd_frag_buffer_size", cfg_key_pmacctd_frag_buffer_size}, {"uacctd_flow_buffer_size", cfg_key_pmacctd_flow_buffer_size}, {"uacctd_flow_buffer_buckets", cfg_key_pmacctd_flow_buffer_buckets}, {"uacctd_conntrack_buffer_size", cfg_key_pmacctd_conntrack_buffer_size}, {"uacctd_flow_lifetime", cfg_key_pmacctd_flow_lifetime}, {"uacctd_flow_tcp_lifetime", cfg_key_pmacctd_flow_tcp_lifetime}, {"uacctd_ext_sampling_rate", cfg_key_pmacctd_ext_sampling_rate}, {"uacctd_stitching", cfg_key_nfacctd_stitching}, {"uacctd_renormalize", cfg_key_sfacctd_renormalize}, {"uacctd_direction", cfg_key_pcap_direction}, {"telemetry_daemon", cfg_key_telemetry_daemon}, {"telemetry_daemon_port_tcp", cfg_key_telemetry_port_tcp}, {"telemetry_daemon_port_udp", cfg_key_telemetry_port_udp}, {"telemetry_daemon_ip", cfg_key_telemetry_ip}, {"telemetry_daemon_interface", cfg_key_telemetry_interface}, {"telemetry_daemon_ipv6_only", cfg_key_telemetry_ipv6_only}, {"telemetry_daemon_udp_notif_port", cfg_key_telemetry_udp_notif_port}, {"telemetry_daemon_udp_notif_ip", cfg_key_telemetry_udp_notif_ip}, {"telemetry_daemon_udp_notif_interface", cfg_key_telemetry_udp_notif_interface}, {"telemetry_daemon_udp_notif_ipv6_only", cfg_key_telemetry_udp_notif_ipv6_only}, {"telemetry_daemon_udp_notif_nmsgs", cfg_key_telemetry_udp_notif_nmsgs}, {"telemetry_daemon_udp_notif_rp_ebpf_prog", cfg_key_telemetry_udp_notif_rp_ebpf_prog}, {"telemetry_daemon_zmq_address", cfg_key_telemetry_zmq_address}, {"telemetry_daemon_kafka_broker_host", cfg_key_telemetry_kafka_broker_host}, {"telemetry_daemon_kafka_broker_port", cfg_key_telemetry_kafka_broker_port}, {"telemetry_daemon_kafka_topic", cfg_key_telemetry_kafka_topic}, {"telemetry_daemon_kafka_config_file", cfg_key_telemetry_kafka_config_file}, {"telemetry_daemon_decoder", cfg_key_telemetry_decoder}, {"telemetry_daemon_max_peers", cfg_key_telemetry_max_peers}, {"telemetry_daemon_peer_timeout", cfg_key_telemetry_peer_timeout}, {"telemetry_daemon_tag_map", cfg_key_telemetry_tag_map}, {"telemetry_daemon_allow_file", cfg_key_telemetry_allow_file}, {"telemetry_daemon_pipe_size", cfg_key_telemetry_pipe_size}, {"telemetry_daemon_ipprec", cfg_key_telemetry_ip_precedence}, {"telemetry_daemon_msglog_output", cfg_key_telemetry_msglog_output}, {"telemetry_daemon_msglog_file", cfg_key_telemetry_msglog_file}, {"telemetry_daemon_msglog_amqp_host", cfg_key_telemetry_msglog_amqp_host}, {"telemetry_daemon_msglog_amqp_vhost", cfg_key_telemetry_msglog_amqp_vhost}, {"telemetry_daemon_msglog_amqp_user", cfg_key_telemetry_msglog_amqp_user}, {"telemetry_daemon_msglog_amqp_passwd", cfg_key_telemetry_msglog_amqp_passwd}, {"telemetry_daemon_msglog_amqp_exchange", cfg_key_telemetry_msglog_amqp_exchange}, {"telemetry_daemon_msglog_amqp_exchange_type", cfg_key_telemetry_msglog_amqp_exchange_type}, {"telemetry_daemon_msglog_amqp_routing_key", cfg_key_telemetry_msglog_amqp_routing_key}, {"telemetry_daemon_msglog_amqp_routing_key_rr", cfg_key_telemetry_msglog_amqp_routing_key_rr}, {"telemetry_daemon_msglog_amqp_persistent_msg", cfg_key_telemetry_msglog_amqp_persistent_msg}, {"telemetry_daemon_msglog_amqp_frame_max", cfg_key_telemetry_msglog_amqp_frame_max}, {"telemetry_daemon_msglog_amqp_heartbeat_interval", cfg_key_telemetry_msglog_amqp_heartbeat_interval}, {"telemetry_daemon_msglog_amqp_retry", cfg_key_telemetry_msglog_amqp_retry}, {"telemetry_daemon_msglog_kafka_broker_host", cfg_key_telemetry_msglog_kafka_broker_host}, {"telemetry_daemon_msglog_kafka_broker_port", cfg_key_telemetry_msglog_kafka_broker_port}, {"telemetry_daemon_msglog_kafka_topic", cfg_key_telemetry_msglog_kafka_topic}, {"telemetry_daemon_msglog_kafka_topic_rr", cfg_key_telemetry_msglog_kafka_topic_rr}, {"telemetry_daemon_msglog_kafka_partition", cfg_key_telemetry_msglog_kafka_partition}, {"telemetry_daemon_msglog_kafka_partition_key", cfg_key_telemetry_msglog_kafka_partition_key}, {"telemetry_daemon_msglog_kafka_retry", cfg_key_telemetry_msglog_kafka_retry}, {"telemetry_daemon_msglog_kafka_config_file", cfg_key_telemetry_msglog_kafka_config_file}, {"telemetry_dump_output", cfg_key_telemetry_dump_output}, {"telemetry_dump_file", cfg_key_telemetry_dump_file}, {"telemetry_dump_latest_file", cfg_key_telemetry_dump_latest_file}, {"telemetry_dump_refresh_time", cfg_key_telemetry_dump_refresh_time}, {"telemetry_dump_time_slots", cfg_key_telemetry_dump_time_slots}, {"telemetry_dump_amqp_host", cfg_key_telemetry_dump_amqp_host}, {"telemetry_dump_amqp_vhost", cfg_key_telemetry_dump_amqp_vhost}, {"telemetry_dump_amqp_user", cfg_key_telemetry_dump_amqp_user}, {"telemetry_dump_amqp_passwd", cfg_key_telemetry_dump_amqp_passwd}, {"telemetry_dump_amqp_exchange", cfg_key_telemetry_dump_amqp_exchange}, {"telemetry_dump_amqp_exchange_type", cfg_key_telemetry_dump_amqp_exchange_type}, {"telemetry_dump_amqp_routing_key", cfg_key_telemetry_dump_amqp_routing_key}, {"telemetry_dump_amqp_routing_key_rr", cfg_key_telemetry_dump_amqp_routing_key_rr}, {"telemetry_dump_amqp_persistent_msg", cfg_key_telemetry_dump_amqp_persistent_msg}, {"telemetry_dump_amqp_frame_max", cfg_key_telemetry_dump_amqp_frame_max}, {"telemetry_dump_amqp_heartbeat_interval", cfg_key_telemetry_dump_amqp_heartbeat_interval}, {"telemetry_dump_kafka_broker_host", cfg_key_telemetry_dump_kafka_broker_host}, {"telemetry_dump_kafka_broker_port", cfg_key_telemetry_dump_kafka_broker_port}, {"telemetry_dump_kafka_topic", cfg_key_telemetry_dump_kafka_topic}, {"telemetry_dump_kafka_topic_rr", cfg_key_telemetry_dump_kafka_topic_rr}, {"telemetry_dump_kafka_partition", cfg_key_telemetry_dump_kafka_partition}, {"telemetry_dump_kafka_partition_key", cfg_key_telemetry_dump_kafka_partition_key}, {"telemetry_dump_kafka_config_file", cfg_key_telemetry_dump_kafka_config_file}, {"telemetry_dump_workers", cfg_key_telemetry_dump_workers}, {"maps_refresh", cfg_key_maps_refresh}, {"maps_index", cfg_key_maps_index}, {"maps_entries", cfg_key_maps_entries}, {"maps_row_len", cfg_key_maps_row_len}, {"pre_tag_map", cfg_key_pre_tag_map}, {"pre_tag_filter", cfg_key_pre_tag_filter}, {"pre_tag2_filter", cfg_key_pre_tag2_filter}, {"pre_tag_label_filter", cfg_key_pre_tag_label_filter}, {"pre_tag_label_encode_as_map", cfg_key_pre_tag_label_encode_as_map}, {"post_tag", cfg_key_post_tag}, {"post_tag2", cfg_key_post_tag2}, {"sampling_rate", cfg_key_sampling_rate}, {"sampling_map", cfg_key_sampling_map}, {"sfacctd_proc_name", cfg_key_proc_name}, {"sfacctd_port", cfg_key_nfacctd_port}, {"sfacctd_ip", cfg_key_nfacctd_ip}, {"sfacctd_interface", cfg_key_nfacctd_interface}, {"sfacctd_rp_ebpf_prog", cfg_key_nfacctd_rp_ebpf_prog}, {"sfacctd_allow_file", cfg_key_nfacctd_allow_file}, {"sfacctd_as_new", cfg_key_nfacctd_as_new}, {"sfacctd_as", cfg_key_nfacctd_as_new}, {"sfacctd_net", cfg_key_nfacctd_net}, {"sfacctd_peer_as", cfg_key_nfprobe_peer_as}, {"sfacctd_nonroot", cfg_key_pmacctd_nonroot}, {"sfacctd_time_new", cfg_key_nfacctd_time_new}, {"sfacctd_pipe_size", cfg_key_nfacctd_pipe_size}, {"sfacctd_renormalize", cfg_key_sfacctd_renormalize}, {"sfacctd_disable_checks", cfg_key_nfacctd_disable_checks}, {"sfacctd_mcast_groups", cfg_key_nfacctd_mcast_groups}, {"sfacctd_stitching", cfg_key_nfacctd_stitching}, {"sfacctd_ext_sampling_rate", cfg_key_pmacctd_ext_sampling_rate}, {"sfacctd_counter_output", cfg_key_sfacctd_counter_output}, {"sfacctd_counter_file", cfg_key_sfacctd_counter_file}, {"sfacctd_counter_amqp_host", cfg_key_sfacctd_counter_amqp_host}, {"sfacctd_counter_amqp_vhost", cfg_key_sfacctd_counter_amqp_vhost}, {"sfacctd_counter_amqp_user", cfg_key_sfacctd_counter_amqp_user}, {"sfacctd_counter_amqp_passwd", cfg_key_sfacctd_counter_amqp_passwd}, {"sfacctd_counter_amqp_exchange", cfg_key_sfacctd_counter_amqp_exchange}, {"sfacctd_counter_amqp_exchange_type", cfg_key_sfacctd_counter_amqp_exchange_type}, {"sfacctd_counter_amqp_routing_key", cfg_key_sfacctd_counter_amqp_routing_key}, {"sfacctd_counter_amqp_persistent_msg", cfg_key_sfacctd_counter_amqp_persistent_msg}, {"sfacctd_counter_amqp_frame_max", cfg_key_sfacctd_counter_amqp_frame_max}, {"sfacctd_counter_amqp_heartbeat_interval", cfg_key_sfacctd_counter_amqp_heartbeat_interval}, {"sfacctd_counter_amqp_retry", cfg_key_sfacctd_counter_amqp_retry}, {"sfacctd_counter_kafka_broker_host", cfg_key_sfacctd_counter_kafka_broker_host}, {"sfacctd_counter_kafka_broker_port", cfg_key_sfacctd_counter_kafka_broker_port}, {"sfacctd_counter_kafka_topic", cfg_key_sfacctd_counter_kafka_topic}, {"sfacctd_counter_kafka_partition", cfg_key_sfacctd_counter_kafka_partition}, {"sfacctd_counter_kafka_partition_key", cfg_key_sfacctd_counter_kafka_partition_key}, {"sfacctd_counter_kafka_retry", cfg_key_sfacctd_counter_kafka_retry}, {"sfacctd_counter_kafka_config_file", cfg_key_sfacctd_counter_kafka_config_file}, {"sfacctd_kafka_broker_host", cfg_key_nfacctd_kafka_broker_host}, {"sfacctd_kafka_broker_port", cfg_key_nfacctd_kafka_broker_port}, {"sfacctd_kafka_topic", cfg_key_nfacctd_kafka_topic}, {"sfacctd_kafka_config_file", cfg_key_nfacctd_kafka_config_file}, {"sfacctd_zmq_address", cfg_key_nfacctd_zmq_address}, #if defined (WITH_NDPI) {"classifier_num_roots", cfg_key_classifier_ndpi_num_roots}, {"classifier_max_flows", cfg_key_classifier_ndpi_max_flows}, {"classifier_proto_guess", cfg_key_classifier_ndpi_proto_guess}, {"classifier_idle_scan_period", cfg_key_classifier_ndpi_idle_scan_period}, {"classifier_idle_max_time", cfg_key_classifier_ndpi_idle_max_time}, {"classifier_idle_scan_budget", cfg_key_classifier_ndpi_idle_scan_budget}, {"classifier_giveup_proto_tcp", cfg_key_classifier_ndpi_giveup_proto_tcp}, {"classifier_giveup_proto_udp", cfg_key_classifier_ndpi_giveup_proto_udp}, {"classifier_giveup_proto_other", cfg_key_classifier_ndpi_giveup_proto_other}, #endif {"nfprobe_timeouts", cfg_key_nfprobe_timeouts}, {"nfprobe_hoplimit", cfg_key_nfprobe_hoplimit}, {"nfprobe_maxflows", cfg_key_nfprobe_maxflows}, {"nfprobe_receiver", cfg_key_nfprobe_receiver}, {"nfprobe_dtls", cfg_key_nfprobe_dtls}, {"nfprobe_dtls_verify_cert", cfg_key_nfprobe_dtls_verify_cert}, {"nfprobe_engine", cfg_key_nfprobe_engine}, {"nfprobe_version", cfg_key_nfprobe_version}, {"nfprobe_peer_as", cfg_key_nfprobe_peer_as}, {"nfprobe_source_ip", cfg_key_nfprobe_source_ip}, {"nfprobe_ipprec", cfg_key_nfprobe_ip_precedence}, {"nfprobe_direction", cfg_key_nfprobe_direction}, {"nfprobe_ifindex", cfg_key_nfprobe_ifindex}, {"nfprobe_dont_cache", cfg_key_nfprobe_dont_cache}, {"nfprobe_ifindex_override", cfg_key_nfprobe_ifindex_override}, {"nfprobe_tstamp_usec", cfg_key_nfprobe_tstamp_usec}, {"sfprobe_receiver", cfg_key_sfprobe_receiver}, {"sfprobe_agentip", cfg_key_sfprobe_agentip}, {"sfprobe_agentsubid", cfg_key_sfprobe_agentsubid}, {"sfprobe_peer_as", cfg_key_nfprobe_peer_as}, {"sfprobe_source_ip", cfg_key_nfprobe_source_ip}, {"sfprobe_ipprec", cfg_key_nfprobe_ip_precedence}, {"sfprobe_direction", cfg_key_nfprobe_direction}, {"sfprobe_ifindex", cfg_key_nfprobe_ifindex}, {"sfprobe_ifspeed", cfg_key_sfprobe_ifspeed}, {"sfprobe_ifindex_override", cfg_key_nfprobe_ifindex_override}, {"tee_receivers", cfg_key_tee_receivers}, {"tee_source_ip", cfg_key_nfprobe_source_ip}, {"tee_transparent", cfg_key_tee_transparent}, {"tee_max_receivers", cfg_key_tee_max_receivers}, {"tee_max_receiver_pools", cfg_key_tee_max_receiver_pools}, {"tee_ipprec", cfg_key_nfprobe_ip_precedence}, {"tee_pipe_size", cfg_key_tee_pipe_size}, {"tee_kafka_config_file", cfg_key_tee_kafka_config_file}, {"bgp_daemon", cfg_key_bgp_daemon}, {"bgp_daemon_ip", cfg_key_bgp_daemon_ip}, {"bgp_daemon_interface", cfg_key_bgp_daemon_interface}, {"bgp_daemon_ipv6_only", cfg_key_bgp_daemon_ipv6_only}, {"bgp_daemon_id", cfg_key_bgp_daemon_id}, {"bgp_daemon_as", cfg_key_bgp_daemon_as}, {"bgp_daemon_port", cfg_key_bgp_daemon_port}, {"bgp_daemon_rp_ebpf_prog", cfg_key_bgp_daemon_rp_ebpf_prog}, {"bgp_daemon_add_path_ignore", cfg_key_bgp_daemon_add_path_ignore}, {"bgp_daemon_tag_map", cfg_key_bgp_daemon_tag_map}, {"bgp_daemon_pipe_size", cfg_key_bgp_daemon_pipe_size}, {"bgp_daemon_max_peers", cfg_key_bgp_daemon_max_peers}, {"bgp_daemon_msglog_output", cfg_key_bgp_daemon_msglog_output}, {"bgp_daemon_msglog_file", cfg_key_bgp_daemon_msglog_file}, {"bgp_daemon_msglog_avro_schema_file", cfg_key_bgp_daemon_msglog_avro_schema_file}, {"bgp_daemon_msglog_amqp_host", cfg_key_bgp_daemon_msglog_amqp_host}, {"bgp_daemon_msglog_amqp_vhost", cfg_key_bgp_daemon_msglog_amqp_vhost}, {"bgp_daemon_msglog_amqp_user", cfg_key_bgp_daemon_msglog_amqp_user}, {"bgp_daemon_msglog_amqp_passwd", cfg_key_bgp_daemon_msglog_amqp_passwd}, {"bgp_daemon_msglog_amqp_exchange", cfg_key_bgp_daemon_msglog_amqp_exchange}, {"bgp_daemon_msglog_amqp_exchange_type", cfg_key_bgp_daemon_msglog_amqp_exchange_type}, {"bgp_daemon_msglog_amqp_routing_key", cfg_key_bgp_daemon_msglog_amqp_routing_key}, {"bgp_daemon_msglog_amqp_routing_key_rr", cfg_key_bgp_daemon_msglog_amqp_routing_key_rr}, {"bgp_daemon_msglog_amqp_persistent_msg", cfg_key_bgp_daemon_msglog_amqp_persistent_msg}, {"bgp_daemon_msglog_amqp_frame_max", cfg_key_bgp_daemon_msglog_amqp_frame_max}, {"bgp_daemon_msglog_amqp_heartbeat_interval", cfg_key_bgp_daemon_msglog_amqp_heartbeat_interval}, {"bgp_daemon_msglog_amqp_retry", cfg_key_bgp_daemon_msglog_amqp_retry}, {"bgp_daemon_msglog_kafka_broker_host", cfg_key_bgp_daemon_msglog_kafka_broker_host}, {"bgp_daemon_msglog_kafka_broker_port", cfg_key_bgp_daemon_msglog_kafka_broker_port}, {"bgp_daemon_msglog_kafka_topic", cfg_key_bgp_daemon_msglog_kafka_topic}, {"bgp_daemon_msglog_kafka_topic_rr", cfg_key_bgp_daemon_msglog_kafka_topic_rr}, {"bgp_daemon_msglog_kafka_partition", cfg_key_bgp_daemon_msglog_kafka_partition}, {"bgp_daemon_msglog_kafka_partition_key", cfg_key_bgp_daemon_msglog_kafka_partition_key}, {"bgp_daemon_msglog_kafka_retry", cfg_key_bgp_daemon_msglog_kafka_retry}, {"bgp_daemon_msglog_kafka_config_file", cfg_key_bgp_daemon_msglog_kafka_config_file}, {"bgp_daemon_msglog_kafka_avro_schema_registry", cfg_key_bgp_daemon_msglog_kafka_avro_schema_registry}, {"bgp_daemon_allow_file", cfg_key_bgp_daemon_allow_file}, {"bgp_daemon_ipprec", cfg_key_bgp_daemon_ip_precedence}, {"bgp_daemon_md5_file", cfg_key_bgp_daemon_md5_file}, {"bgp_daemon_batch", cfg_key_bgp_daemon_batch}, {"bgp_daemon_batch_interval", cfg_key_bgp_daemon_batch_interval}, {"bgp_aspath_radius", cfg_key_bgp_daemon_aspath_radius}, {"bgp_stdcomm_pattern", cfg_key_bgp_daemon_stdcomm_pattern}, {"bgp_extcomm_pattern", cfg_key_bgp_daemon_extcomm_pattern}, {"bgp_lrgcomm_pattern", cfg_key_bgp_daemon_lrgcomm_pattern}, {"bgp_stdcomm_pattern_to_asn", cfg_key_bgp_daemon_stdcomm_pattern_to_asn}, {"bgp_lrgcomm_pattern_to_asn", cfg_key_bgp_daemon_lrgcomm_pattern_to_asn}, {"bgp_blackhole_stdcomm_list", cfg_key_bgp_blackhole_stdcomm_list}, {"bgp_peer_as_skip_subas", cfg_key_bgp_daemon_peer_as_skip_subas}, {"bgp_peer_src_as_map", cfg_key_bgp_daemon_peer_src_as_map}, {"bgp_src_local_pref_map", cfg_key_bgp_daemon_src_local_pref_map}, {"bgp_src_med_map", cfg_key_bgp_daemon_src_med_map}, {"bgp_peer_src_as_type", cfg_key_bgp_daemon_peer_src_as_type}, {"bgp_src_std_comm_type", cfg_key_bgp_daemon_src_std_comm_type}, {"bgp_src_ext_comm_type", cfg_key_bgp_daemon_src_ext_comm_type}, {"bgp_src_lrg_comm_type", cfg_key_bgp_daemon_src_lrg_comm_type}, {"bgp_src_as_path_type", cfg_key_bgp_daemon_src_as_path_type}, {"bgp_src_local_pref_type", cfg_key_bgp_daemon_src_local_pref_type}, {"bgp_src_med_type", cfg_key_bgp_daemon_src_med_type}, {"bgp_src_roa_type", cfg_key_bgp_daemon_src_roa_type}, {"bgp_agent_map", cfg_key_bgp_daemon_to_xflow_agent_map}, {"bgp_follow_default", cfg_key_bgp_daemon_follow_default}, {"bgp_follow_nexthop", cfg_key_bgp_daemon_follow_nexthop}, {"bgp_follow_nexthop_external", cfg_key_bgp_daemon_follow_nexthop_external}, {"bgp_disable_router_id_check", cfg_key_bgp_daemon_disable_router_id_check}, {"bgp_neighbors_file", cfg_key_bgp_daemon_neighbors_file}, {"bgp_table_peer_buckets", cfg_key_bgp_daemon_table_peer_buckets}, {"bgp_table_per_peer_buckets", cfg_key_bgp_daemon_table_per_peer_buckets}, {"bgp_table_attr_hash_buckets", cfg_key_bgp_daemon_table_attr_hash_buckets}, {"bgp_table_per_peer_hash", cfg_key_bgp_daemon_table_per_peer_hash}, {"bgp_table_dump_output", cfg_key_bgp_daemon_table_dump_output}, {"bgp_table_dump_file", cfg_key_bgp_daemon_table_dump_file}, {"bgp_table_dump_latest_file", cfg_key_bgp_daemon_table_dump_latest_file}, {"bgp_table_dump_avro_schema_file", cfg_key_bgp_daemon_table_dump_avro_schema_file}, {"bgp_table_dump_refresh_time", cfg_key_bgp_daemon_table_dump_refresh_time}, {"bgp_table_dump_time_slots", cfg_key_bgp_daemon_table_dump_time_slots}, {"bgp_table_dump_amqp_host", cfg_key_bgp_daemon_table_dump_amqp_host}, {"bgp_table_dump_amqp_vhost", cfg_key_bgp_daemon_table_dump_amqp_vhost}, {"bgp_table_dump_amqp_user", cfg_key_bgp_daemon_table_dump_amqp_user}, {"bgp_table_dump_amqp_passwd", cfg_key_bgp_daemon_table_dump_amqp_passwd}, {"bgp_table_dump_amqp_exchange", cfg_key_bgp_daemon_table_dump_amqp_exchange}, {"bgp_table_dump_amqp_exchange_type", cfg_key_bgp_daemon_table_dump_amqp_exchange_type}, {"bgp_table_dump_amqp_routing_key", cfg_key_bgp_daemon_table_dump_amqp_routing_key}, {"bgp_table_dump_amqp_routing_key_rr", cfg_key_bgp_daemon_table_dump_amqp_routing_key_rr}, {"bgp_table_dump_amqp_persistent_msg", cfg_key_bgp_daemon_table_dump_amqp_persistent_msg}, {"bgp_table_dump_amqp_frame_max", cfg_key_bgp_daemon_table_dump_amqp_frame_max}, {"bgp_table_dump_amqp_heartbeat_interval", cfg_key_bgp_daemon_table_dump_amqp_heartbeat_interval}, {"bgp_table_dump_kafka_broker_host", cfg_key_bgp_daemon_table_dump_kafka_broker_host}, {"bgp_table_dump_kafka_broker_port", cfg_key_bgp_daemon_table_dump_kafka_broker_port}, {"bgp_table_dump_kafka_topic", cfg_key_bgp_daemon_table_dump_kafka_topic}, {"bgp_table_dump_kafka_topic_rr", cfg_key_bgp_daemon_table_dump_kafka_topic_rr}, {"bgp_table_dump_kafka_partition", cfg_key_bgp_daemon_table_dump_kafka_partition}, {"bgp_table_dump_kafka_partition_key", cfg_key_bgp_daemon_table_dump_kafka_partition_key}, {"bgp_table_dump_kafka_config_file", cfg_key_bgp_daemon_table_dump_kafka_config_file}, {"bgp_table_dump_kafka_avro_schema_registry", cfg_key_bgp_daemon_table_dump_kafka_avro_schema_registry}, {"bgp_table_dump_workers", cfg_key_bgp_daemon_table_dump_workers}, {"bgp_daemon_lg", cfg_key_bgp_lg}, {"bgp_daemon_lg_ip", cfg_key_bgp_lg_ip}, {"bgp_daemon_lg_port", cfg_key_bgp_lg_port}, {"bgp_daemon_lg_threads", cfg_key_bgp_lg_threads}, {"bgp_daemon_lg_user", cfg_key_bgp_lg_user}, {"bgp_daemon_lg_passwd", cfg_key_bgp_lg_passwd}, {"bgp_daemon_xconnect_map", cfg_key_bgp_xconnect_map}, {"bmp_daemon", cfg_key_bmp_daemon}, {"bmp_daemon_ip", cfg_key_bmp_daemon_ip}, {"bmp_daemon_interface", cfg_key_bmp_daemon_interface}, {"bmp_daemon_ipv6_only", cfg_key_bmp_daemon_ipv6_only}, {"bmp_daemon_port", cfg_key_bmp_daemon_port}, {"bmp_daemon_rp_ebpf_prog", cfg_key_bmp_daemon_rp_ebpf_prog}, {"bmp_daemon_tag_map", cfg_key_bmp_daemon_tag_map}, {"bmp_daemon_pipe_size", cfg_key_bmp_daemon_pipe_size}, {"bmp_daemon_max_peers", cfg_key_bmp_daemon_max_peers}, {"bmp_daemon_allow_file", cfg_key_bmp_daemon_allow_file}, {"bmp_daemon_ipprec", cfg_key_bmp_daemon_ip_precedence}, {"bmp_daemon_batch", cfg_key_bmp_daemon_batch}, {"bmp_daemon_batch_interval", cfg_key_bmp_daemon_batch_interval}, {"bmp_agent_map", cfg_key_bgp_daemon_to_xflow_agent_map}, {"bmp_daemon_msglog_output", cfg_key_bmp_daemon_msglog_output}, {"bmp_daemon_msglog_file", cfg_key_bmp_daemon_msglog_file}, {"bmp_daemon_msglog_avro_schema_file", cfg_key_bmp_daemon_msglog_avro_schema_file}, {"bmp_daemon_msglog_amqp_host", cfg_key_bmp_daemon_msglog_amqp_host}, {"bmp_daemon_msglog_amqp_vhost", cfg_key_bmp_daemon_msglog_amqp_vhost}, {"bmp_daemon_msglog_amqp_user", cfg_key_bmp_daemon_msglog_amqp_user}, {"bmp_daemon_msglog_amqp_passwd", cfg_key_bmp_daemon_msglog_amqp_passwd}, {"bmp_daemon_msglog_amqp_exchange", cfg_key_bmp_daemon_msglog_amqp_exchange}, {"bmp_daemon_msglog_amqp_exchange_type", cfg_key_bmp_daemon_msglog_amqp_exchange_type}, {"bmp_daemon_msglog_amqp_routing_key", cfg_key_bmp_daemon_msglog_amqp_routing_key}, {"bmp_daemon_msglog_amqp_routing_key_rr", cfg_key_bmp_daemon_msglog_amqp_routing_key_rr}, {"bmp_daemon_msglog_amqp_persistent_msg", cfg_key_bmp_daemon_msglog_amqp_persistent_msg}, {"bmp_daemon_msglog_amqp_frame_max", cfg_key_bmp_daemon_msglog_amqp_frame_max}, {"bmp_daemon_msglog_amqp_heartbeat_interval", cfg_key_bmp_daemon_msglog_amqp_heartbeat_interval}, {"bmp_daemon_msglog_amqp_retry", cfg_key_bmp_daemon_msglog_amqp_retry}, {"bmp_daemon_msglog_kafka_broker_host", cfg_key_bmp_daemon_msglog_kafka_broker_host}, {"bmp_daemon_msglog_kafka_broker_port", cfg_key_bmp_daemon_msglog_kafka_broker_port}, {"bmp_daemon_msglog_kafka_topic", cfg_key_bmp_daemon_msglog_kafka_topic}, {"bmp_daemon_msglog_kafka_topic_rr", cfg_key_bmp_daemon_msglog_kafka_topic_rr}, {"bmp_daemon_msglog_kafka_partition", cfg_key_bmp_daemon_msglog_kafka_partition}, {"bmp_daemon_msglog_kafka_partition_key", cfg_key_bmp_daemon_msglog_kafka_partition_key}, {"bmp_daemon_msglog_kafka_retry", cfg_key_bmp_daemon_msglog_kafka_retry}, {"bmp_daemon_msglog_kafka_config_file", cfg_key_bmp_daemon_msglog_kafka_config_file}, {"bmp_daemon_msglog_kafka_avro_schema_registry", cfg_key_bmp_daemon_msglog_kafka_avro_schema_registry}, {"bmp_table_peer_buckets", cfg_key_bmp_daemon_table_peer_buckets}, {"bmp_table_per_peer_buckets", cfg_key_bmp_daemon_table_per_peer_buckets}, {"bmp_table_attr_hash_buckets", cfg_key_bmp_daemon_table_attr_hash_buckets}, {"bmp_table_per_peer_hash", cfg_key_bmp_daemon_table_per_peer_hash}, {"bmp_dump_output", cfg_key_bmp_daemon_dump_output}, {"bmp_dump_file", cfg_key_bmp_daemon_dump_file}, {"bmp_dump_latest_file", cfg_key_bmp_daemon_dump_latest_file}, {"bmp_dump_workers", cfg_key_bmp_daemon_dump_workers}, {"bmp_dump_avro_schema_file", cfg_key_bmp_daemon_dump_avro_schema_file}, {"bmp_dump_refresh_time", cfg_key_bmp_daemon_dump_refresh_time}, {"bmp_dump_time_slots", cfg_key_bmp_daemon_dump_time_slots}, {"bmp_dump_amqp_host", cfg_key_bmp_daemon_dump_amqp_host}, {"bmp_dump_amqp_vhost", cfg_key_bmp_daemon_dump_amqp_vhost}, {"bmp_dump_amqp_user", cfg_key_bmp_daemon_dump_amqp_user}, {"bmp_dump_amqp_passwd", cfg_key_bmp_daemon_dump_amqp_passwd}, {"bmp_dump_amqp_exchange", cfg_key_bmp_daemon_dump_amqp_exchange}, {"bmp_dump_amqp_exchange_type", cfg_key_bmp_daemon_dump_amqp_exchange_type}, {"bmp_dump_amqp_routing_key", cfg_key_bmp_daemon_dump_amqp_routing_key}, {"bmp_dump_amqp_routing_key_rr", cfg_key_bmp_daemon_dump_amqp_routing_key_rr}, {"bmp_dump_amqp_persistent_msg", cfg_key_bmp_daemon_dump_amqp_persistent_msg}, {"bmp_dump_amqp_frame_max", cfg_key_bmp_daemon_dump_amqp_frame_max}, {"bmp_dump_amqp_heartbeat_interval", cfg_key_bmp_daemon_dump_amqp_heartbeat_interval}, {"bmp_dump_kafka_broker_host", cfg_key_bmp_daemon_dump_kafka_broker_host}, {"bmp_dump_kafka_broker_port", cfg_key_bmp_daemon_dump_kafka_broker_port}, {"bmp_dump_kafka_topic", cfg_key_bmp_daemon_dump_kafka_topic}, {"bmp_dump_kafka_topic_rr", cfg_key_bmp_daemon_dump_kafka_topic_rr}, {"bmp_dump_kafka_partition", cfg_key_bmp_daemon_dump_kafka_partition}, {"bmp_dump_kafka_partition_key", cfg_key_bmp_daemon_dump_kafka_partition_key}, {"bmp_dump_kafka_config_file", cfg_key_bmp_daemon_dump_kafka_config_file}, {"bmp_dump_kafka_avro_schema_registry", cfg_key_bmp_daemon_dump_kafka_avro_schema_registry}, {"bmp_daemon_parse_proxy_header", cfg_key_nfacctd_bmp_daemon_parse_proxy_header}, {"rpki_roas_file", cfg_key_rpki_roas_file}, {"rpki_rtr_cache", cfg_key_rpki_rtr_cache}, {"rpki_rtr_cache_version", cfg_key_rpki_rtr_cache_version}, {"rpki_rtr_cache_pipe_size", cfg_key_rpki_rtr_cache_pipe_size}, {"rpki_rtr_cache_ipprec", cfg_key_rpki_rtr_cache_ip_precedence}, {"flow_to_rd_map", cfg_key_nfacctd_flow_to_rd_map}, {"isis_daemon", cfg_key_nfacctd_isis}, {"isis_daemon_ip", cfg_key_nfacctd_isis_ip}, {"isis_daemon_net", cfg_key_nfacctd_isis_net}, {"isis_daemon_iface", cfg_key_nfacctd_isis_iface}, {"isis_daemon_mtu", cfg_key_nfacctd_isis_mtu}, {"isis_daemon_msglog", cfg_key_nfacctd_isis_msglog}, {"igp_daemon", cfg_key_nfacctd_isis}, {"igp_daemon_map", cfg_key_igp_daemon_map}, {"igp_daemon_map_msglog", cfg_key_igp_daemon_map_msglog}, #if defined WITH_GEOIP {"geoip_ipv4_file", cfg_key_geoip_ipv4_file}, {"geoip_ipv6_file", cfg_key_geoip_ipv6_file}, #endif #if defined WITH_GEOIPV2 {"geoipv2_file", cfg_key_geoipv2_file}, #endif {"uacctd_group", cfg_key_uacctd_group}, {"uacctd_nl_size", cfg_key_uacctd_nl_size}, {"uacctd_threshold", cfg_key_uacctd_threshold}, {"tunnel_0", cfg_key_tunnel_0}, {"tmp_asa_bi_flow", cfg_key_tmp_asa_bi_flow}, {"tmp_bgp_lookup_compare_ports", cfg_key_tmp_bgp_lookup_compare_ports}, {"tmp_bgp_daemon_route_refresh", cfg_key_tmp_bgp_daemon_route_refresh}, {"tmp_bgp_daemon_origin_type_int", cfg_key_tmp_bgp_daemon_origin_type_int}, {"tmp_telemetry_daemon_udp_notif_legacy", cfg_key_tmp_telemetry_daemon_udp_notif_legacy}, {"tmp_telemetry_decode_cisco_v1_json_string", cfg_key_tmp_telemetry_decode_cisco_v1_json_string}, {"", NULL} }; static struct plugin_type_entry plugin_types_list[] = { {PLUGIN_ID_CORE, "core", NULL}, {PLUGIN_ID_MEMORY, "memory", imt_plugin}, {PLUGIN_ID_PRINT, "print", print_plugin}, {PLUGIN_ID_NFPROBE, "nfprobe", nfprobe_plugin}, {PLUGIN_ID_SFPROBE, "sfprobe", sfprobe_plugin}, #ifdef WITH_MYSQL {PLUGIN_ID_MYSQL, "mysql", mysql_plugin}, #endif #ifdef WITH_PGSQL {PLUGIN_ID_PGSQL, "pgsql", pgsql_plugin}, #endif #ifdef WITH_SQLITE3 {PLUGIN_ID_SQLITE3, "sqlite3", sqlite3_plugin}, #endif #ifdef WITH_MONGODB {PLUGIN_ID_UNKNOWN, "mongodb", mongodb_legacy_warning}, /* Legacy plugin */ {PLUGIN_ID_MONGODB, "mongodb_legacy", mongodb_plugin}, /* Legacy plugin */ #endif #ifdef WITH_RABBITMQ {PLUGIN_ID_AMQP, "amqp", amqp_plugin}, #endif #ifdef WITH_KAFKA {PLUGIN_ID_KAFKA, "kafka", kafka_plugin}, #endif {PLUGIN_ID_TEE, "tee", tee_plugin}, {PLUGIN_ID_UNKNOWN, "", NULL}, }; //Global variables char *cfg[LARGEBUFLEN], *cfg_cmdline[SRVBUFLEN]; struct custom_primitives custom_primitives_registry; pm_cfgreg_t custom_primitives_type; int rows; char default_proc_name[] = "default"; /* evaluate_configuration() handles all supported configuration keys and inserts them in configuration structure of plugins */ void evaluate_configuration(char *filename, int rows) { char *key, *value, *name, *delim; int index = 0, dindex, valid_line, key_found = 0, res; while (index < rows) { if (*cfg[index] == '\0') valid_line = FALSE; else valid_line = TRUE; if (valid_line) { /* debugging the line if required */ if (debug) Log(LOG_DEBUG, "DEBUG: [%s] %s\n", filename, cfg[index]); /* splitting key, value and name */ delim = strchr(cfg[index], ':'); *delim = '\0'; key = cfg[index]; value = delim+1; delim = strchr(key, '['); if (delim) { *delim = '\0'; name = delim+1; delim = strchr(name, ']'); *delim = '\0'; } else name = NULL; /* parsing keys */ for (dindex = 0; strcmp(dictionary[dindex].key, ""); dindex++) { if (!strcmp(dictionary[dindex].key, key)) { res = FALSE; if ((*dictionary[dindex].func)) { res = (*dictionary[dindex].func)(filename, name, value); if (res < 0) Log(LOG_WARNING, "WARN: [%s:%u] Invalid value. Ignored.\n", filename, index+1); else if (!res) Log(LOG_WARNING, "WARN: [%s:%u] Unknown symbol '%s'. Ignored.\n", filename, index+1, name); } else Log(LOG_WARNING, "WARN: [%s:%u] Unable to handle key: %s. Ignored.\n", filename, index+1, key); key_found = TRUE; break; } else key_found = FALSE; } if (!key_found) Log(LOG_WARNING, "WARN: [%s:%u] Unknown key: %s. Ignored.\n", filename, index+1, key); } index++; } } /* parse_configuration_file() reads configuration file and stores its content in an array; then creates plugin structures and parses supported config keys */ int parse_configuration_file(char *filename) { struct stat st; char localbuf[10240]; char cmdline [] = "cmdline"; FILE *file; int num = 0, cmdlineflag = FALSE, rows_cmdline = rows, idx, ret; rows = 0; /* NULL filename means we don't have a configuration file; 1st stage: read from file and store lines into a first char* array; merge commandline options, if required, placing them at the tail - in order to override directives placed in the configuration file */ if (filename) { ret = stat(filename, &st); if (ret < 0) { Log(LOG_ERR, "ERROR: [%s] file not found.\n", filename); return ERR; } else { if (!S_ISREG(st.st_mode)) { Log(LOG_ERR, "ERROR: [%s] path is not a regular file.\n", filename); return ERR; } } if ((file = fopen(filename, "r"))) { while (!feof(file)) { if (rows == LARGEBUFLEN) { Log(LOG_ERR, "ERROR: [%s] maximum number of %d lines reached.\n", filename, LARGEBUFLEN); break; } memset(localbuf, 0, sizeof(localbuf)); if (fgets(localbuf, sizeof(localbuf), file) == NULL) break; else { localbuf[sizeof(localbuf)-1] = '\0'; cfg[rows] = malloc(strlen(localbuf)+2); if (!cfg[rows]) { Log(LOG_ERR, "ERROR: [%s] malloc() failed (parse_configuration_file). Exiting.\n", filename); exit(1); } strcpy(cfg[rows], localbuf); cfg[rows][strlen(localbuf)+1] = '\0'; rows++; } } } fclose(file); } else { filename = cmdline; cmdlineflag = TRUE; } if (rows_cmdline) { for (idx = 0; idx < rows_cmdline && (rows+idx) < LARGEBUFLEN; idx++) { cfg[rows+idx] = cfg_cmdline[idx]; } rows += idx; } /* 2nd stage: sanitize lines */ sanitize_cfg(rows, filename); /* 3rd stage: plugin structures creation; we discard plugin names if 'pmacctd' has been invoked commandline; if any plugin has been activated we default to a single 'imt' plugin */ if (!cmdlineflag) parse_core_process_name(filename, rows, FALSE); else parse_core_process_name(filename, rows, TRUE); if (!cmdlineflag) num = parse_plugin_names(filename, rows, FALSE); else num = parse_plugin_names(filename, rows, TRUE); if (!num && config.acct_type < ACCT_FWDPLANE_MAX) { Log(LOG_WARNING, "WARN: [%s] No plugin has been activated; defaulting to in-memory table.\n", filename); num = create_plugin(filename, "default_memory", "memory"); } if (debug) { struct plugins_list_entry *list = plugins_list; while (list) { Log(LOG_DEBUG, "DEBUG: [%s] plugin name/type: '%s'/'%s'.\n", filename, list->name, list->type.string); list = list->next; } } /* 4th stage: setting some default value */ set_default_values(); /* 5th stage: parsing keys and building configurations */ evaluate_configuration(filename, rows); return SUCCESS; } void sanitize_cfg(int rows, char *filename) { int rindex = 0, len; char localbuf[10240]; while (rindex < rows) { memset(localbuf, 0, 10240); /* checking the whole line: if it's a comment starting with '!', it will be removed */ if (iscomment(cfg[rindex])) memset(cfg[rindex], 0, strlen(cfg[rindex])); /* checking the whole line: if it's void, it will be removed */ if (isblankline(cfg[rindex])) memset(cfg[rindex], 0, strlen(cfg[rindex])); /* a pair of syntax checks on the whole line: - does the line contain at least a ':' verb ? - are the square brackets weighted both in key and value ? */ len = strlen(cfg[rindex]); if (len) { int symbol = FALSE, cindex = 0, got_first = 0, got_first_colon = 0; if (!strchr(cfg[rindex], ':')) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: missing ':'. Exiting.\n", filename, rindex+1); exit(1); } while(cindex <= len) { if (cfg[rindex][cindex] == '[') symbol++; else if (cfg[rindex][cindex] == ']') { symbol--; got_first++; } if (cfg[rindex][cindex] == ':' && !got_first_colon) { got_first_colon = TRUE; if (symbol) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: illegal brackets. Exiting.\n", filename, rindex+1); exit(1); } } if (cfg[rindex][cindex] == '\0') { if (symbol && !got_first) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: not weighted brackets (1). Exiting.\n", filename, rindex+1); exit(1); } } if (symbol < 0 && !got_first) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: not weighted brackets (2). Exiting.\n", filename, rindex+1); exit(1); } if (symbol > 1 && !got_first) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: nested symbols not allowed. Exiting.\n", filename, rindex+1); exit(1); } cindex++; } } /* checking the whole line: erasing unwanted spaces from key; trimming start/end spaces from value; symbols will be left untouched */ len = strlen(cfg[rindex]); if (len) { int symbol = FALSE, value = FALSE, cindex = 0, lbindex = 0; char *valueptr = NULL; while(cindex <= len) { if (!value) { if (cfg[rindex][cindex] == '[') symbol++; else if (cfg[rindex][cindex] == ']') symbol--; else if (cfg[rindex][cindex] == ':') { value++; valueptr = &localbuf[lbindex+1]; } } if ((!symbol) && (!value)) { if (!isspace(cfg[rindex][cindex])) { localbuf[lbindex] = cfg[rindex][cindex]; lbindex++; } } else { localbuf[lbindex] = cfg[rindex][cindex]; lbindex++; } cindex++; } localbuf[lbindex] = '\0'; trim_spaces(valueptr); strcpy(cfg[rindex], localbuf); } /* checking key field: each symbol must refer to a key */ len = strlen(cfg[rindex]); if (len) { int symbol = FALSE, key = FALSE, cindex = 0; while (cindex < rows) { if (cfg[rindex][cindex] == '[') symbol++; else if (cfg[rindex][cindex] == ']') { symbol--; key--; } if (cfg[rindex][cindex] == ':') break; if (!symbol) { if (isalpha(cfg[rindex][cindex])) key = TRUE; } else { if (!key) { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: symbol not referring to any key. Exiting.\n", filename, rindex+1); exit(1); } } cindex++; } } /* checking key field: does a key still exist ? */ len = strlen(cfg[rindex]); if (len) { if (cfg[rindex][0] == ':') { Log(LOG_ERR, "ERROR: [%s:%u] Syntax error: missing key. Exiting.\n", filename, rindex+1); exit(1); } } /* checking key field: converting key to lower chars */ len = strlen(cfg[rindex]); if (len) { int symbol = FALSE, cindex = 0; while(cindex <= len) { if (cfg[rindex][cindex] == '[') symbol++; else if (cfg[rindex][cindex] == ']') symbol--; if (cfg[rindex][cindex] == ':') break; if (!symbol) { if (isalpha(cfg[rindex][cindex])) cfg[rindex][cindex] = tolower(cfg[rindex][cindex]); } cindex++; } } rindex++; } } void parse_core_process_name(char *filename, int rows, int ignore_names) { int index = 0, found = 0; char key[SRVBUFLEN], name[SRVBUFLEN], *start, *end; /* searching for 'core_proc_name' key */ while (index < rows) { memset(key, 0, SRVBUFLEN); start = NULL; end = NULL; start = cfg[index]; end = strchr(cfg[index], ':'); if (end > start) { strlcpy(key, cfg[index], (end-start)+1); if (!strncmp(key, "core_proc_name", sizeof("core_proc_name"))) { start = end+1; strlcpy(name, start, SRVBUFLEN); found = TRUE; break; } } index++; } if (!found || ignore_names) create_plugin(filename, "default", "core"); else create_plugin(filename, name, "core"); } /* parse_plugin_names() leaves cfg array untouched: parses the key 'plugins' if it exists and creates the plugins linked list */ int parse_plugin_names(char *filename, int rows, int ignore_names) { int index = 0, num = 0, found = 0, default_name = FALSE; char *start, *end, *start_name, *end_name; char key[SRVBUFLEN], value[10240], token[SRVBUFLEN], name[SRVBUFLEN]; /* searching for 'plugins' key */ while (index < rows) { memset(key, 0, SRVBUFLEN); start = NULL; end = NULL; start = cfg[index]; end = strchr(cfg[index], ':'); if (end > start) { strlcpy(key, cfg[index], (end-start)+1); if (!strncmp(key, "plugins", sizeof("plugins"))) { start = end+1; strcpy(value, start); found = TRUE; break; } } index++; } if (!found) return 0; /* parsing declared plugins */ start = value; while (*end != '\0') { memset(token, 0, SRVBUFLEN); if (!(end = strchr(start, ','))) end = strchr(start, '\0'); if (end > start) { strlcpy(token, start, (end-start)+1); if ((start_name = strchr(token, '[')) && (end_name = strchr(token, ']'))) { if (end_name > (start_name+1)) { strlcpy(name, (start_name+1), (end_name-start_name)); trim_spaces(name); *start_name = '\0'; } } else default_name = TRUE; /* Having already plugins name and type, we'll filter out reserved symbols */ trim_spaces(token); lower_string(token); if (!strcmp(token, "core")) { Log(LOG_ERR, "ERROR: [%s] plugins of type 'core' are not allowed. Exiting.\n", filename); exit(1); } if (!ignore_names) { if (default_name) compose_default_plugin_name(name, SRVBUFLEN, token); if (create_plugin(filename, name, token)) num++; } else { compose_default_plugin_name(name, SRVBUFLEN, token); if (create_plugin(filename, name, token)) num++; } } start = end+1; } /* having already processed it, we erase 'plugins' line */ memset(cfg[index], 0, strlen(cfg[index])); return num; } /* rough and dirty function to assign default values to configuration file of each plugin */ void set_default_values() { struct plugins_list_entry *list = plugins_list; while (list) { list->cfg.promisc = TRUE; list->cfg.maps_refresh = TRUE; list = list->next; } } void compose_default_plugin_name(char *out, int outlen, char *type) { strcpy(out, "default"); strcat(out, "_"); strncat(out, type, (outlen - 10)); } int create_plugin(char *filename, char *name, char *type) { struct plugins_list_entry *plugin, *ptr; struct plugin_type_entry *ptype = NULL; int index = 0, id = 0; /* searching for a valid known plugin type */ while(strcmp(plugin_types_list[index].string, "")) { if (!strcmp(type, plugin_types_list[index].string)) ptype = &plugin_types_list[index]; index++; } if (!ptype) { Log(LOG_ERR, "ERROR: [%s] Unknown plugin type: %s. Ignoring.\n", filename, type); return FALSE; } /* checks */ if (plugins_list) { id = 0; ptr = plugins_list; while (ptr) { /* plugin id */ if (ptr->id > id) id = ptr->id; /* dupes */ if (!strcmp(name, ptr->name)) { Log(LOG_WARNING, "WARN: [%s] another plugin with the same name '%s' already exists. Preserving first.\n", filename, name); return FALSE; } ptr = ptr->next; } id++; } /* creating a new plugin structure */ plugin = (struct plugins_list_entry *) malloc(sizeof(struct plugins_list_entry)); if (!plugin) { Log(LOG_ERR, "ERROR: [%s] malloc() failed (create_plugin). Exiting.\n", filename); exit(1); } memset(plugin, 0, sizeof(struct plugins_list_entry)); strcpy(plugin->name, name); plugin->id = id; memcpy(&plugin->type, ptype, sizeof(struct plugin_type_entry)); plugin->next = NULL; /* inserting our object in plugin's linked list */ if (plugins_list) { ptr = plugins_list; while(ptr->next) ptr = ptr->next; ptr->next = plugin; } else plugins_list = plugin; return TRUE; } int delete_plugin_by_id(int id) { struct plugins_list_entry *list = plugins_list; struct plugins_list_entry *aux = plugins_list; int highest_id = 0; if (id == 0) return ERR; while (list) { if (list->id == id) { aux->next = list->next; free(list); list = aux; } else { if (list->id > highest_id) highest_id = list->id; } aux = list; list = list->next; } return highest_id; } struct plugins_list_entry *search_plugin_by_pipe(int pipe) { struct plugins_list_entry *list = plugins_list; if (pipe < 0) return NULL; while (list) { if (list->pipe[1] == pipe) return list; else list = list->next; } return NULL; } struct plugins_list_entry *search_plugin_by_pid(pid_t pid) { struct plugins_list_entry *list = plugins_list; if (pid <= 0) return NULL; while (list) { if (list->pid == pid) return list; else list = list->next; } return NULL; } pmacct-1.7.8/src/cfg_handlers.c0000644000175000017500000105017614354105275015376 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "nfacctd.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "cfg_handlers.h" #include "bgp/bgp.h" int parse_truefalse(char *value_ptr) { int value; lower_string(value_ptr); if (!strcmp("true", value_ptr)) value = TRUE; else if (!strcmp("false", value_ptr)) value = FALSE; else value = ERR; return value; } int parse_truefalse_nonzero(char *value_ptr) { int value; lower_string(value_ptr); if (!strcmp("true", value_ptr)) value = TRUE; else if (!strcmp("false", value_ptr)) value = FALSE_NONZERO; else value = ERR; return value; } int validate_truefalse(int value) { if (value == TRUE || value == FALSE) return SUCCESS; else return ERR; } void cfg_key_legacy_warning(char *filename, char *cfg_key) { Log(LOG_WARNING, "WARN: [%s] Configuration key '%s' is legacy and will be discontinued in the next major release.\n", filename, cfg_key); } int cfg_key_debug(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.debug = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.debug = value; changes++; break; } } } return changes; } int cfg_key_debug_internal_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.debug_internal_msg = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.debug_internal_msg = value; changes++; break; } } } return changes; } int cfg_key_syslog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.syslog = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.syslog = value_ptr; changes++; break; } } } return changes; } int cfg_key_logfile(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.logfile = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'logfile'. Globalized.\n", filename); return changes; } int cfg_key_pidfile(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.pidfile = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pidfile'. Globalized.\n", filename); return changes; } int cfg_key_daemonize(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.daemon = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'daemonize'. Globalized.\n", filename); return changes; } int cfg_key_propagate_signals(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.propagate_signals = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'propagate_signals'. Globalized.\n", filename); return changes; } int cfg_key_pcap_arista_trailer_offset(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 8) { Log(LOG_ERR, "WARN: [%s] 'pcap_arista_trailer_offset' has to be >= 8.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.pcap_arista_trailer_offset = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_arista_trailer_offset'. Globalized.\n", filename); return changes; } int cfg_key_pcap_arista_trailer_flag_value(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value > 128) { Log(LOG_ERR, "WARN: [%s] 'pcap_arista_trailer_flag_value' has to be < 128.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.pcap_arista_trailer_flag_value = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_arista_trailer_flag_value'. Globalized.\n", filename); return changes; } int cfg_key_use_ip_next_hop(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.use_ip_next_hop = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'use_ip_next_hop'. Globalized.\n", filename); return changes; } int cfg_key_aggregate(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; struct custom_primitives_ptrs cpptrs; char *count_token; u_int32_t changes = 0; u_int64_t value[3]; trim_all_spaces(value_ptr); lower_string(value_ptr); memset(&value, 0, sizeof(value)); memset(&cpptrs, 0, sizeof(cpptrs)); while ((count_token = extract_token(&value_ptr, ','))) { if (!strcmp(count_token, "src_host")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_HOST, count_token); else if (!strcmp(count_token, "dst_host")) cfg_set_aggregate(filename, value, COUNT_INT_DST_HOST, count_token); else if (!strcmp(count_token, "src_net")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_NET, count_token); else if (!strcmp(count_token, "dst_net")) cfg_set_aggregate(filename, value, COUNT_INT_DST_NET, count_token); else if (!strcmp(count_token, "sum")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_HOST, count_token); else if (!strcmp(count_token, "src_port")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_PORT, count_token); else if (!strcmp(count_token, "dst_port")) cfg_set_aggregate(filename, value, COUNT_INT_DST_PORT, count_token); else if (!strcmp(count_token, "proto")) cfg_set_aggregate(filename, value, COUNT_INT_IP_PROTO, count_token); #if defined (HAVE_L2) else if (!strcmp(count_token, "src_mac")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_MAC, count_token); else if (!strcmp(count_token, "dst_mac")) cfg_set_aggregate(filename, value, COUNT_INT_DST_MAC, count_token); else if (!strcmp(count_token, "out_vlan")) cfg_set_aggregate(filename, value, COUNT_INT_OUT_VLAN, count_token); else if (!strcmp(count_token, "in_vlan")) cfg_set_aggregate(filename, value, COUNT_INT_VLAN, count_token); else if (!strcmp(count_token, "vlan")) { cfg_set_aggregate(filename, value, COUNT_INT_VLAN, count_token); config.tmp_vlan_legacy = TRUE; } else if (!strcmp(count_token, "sum_mac")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_MAC, count_token); #else else if (!strcmp(count_token, "src_mac") || !strcmp(count_token, "dst_mac") || !strcmp(count_token, "vlan") || !strcmp(count_token, "in_vlan") || !strcmp(count_token, "out_vlan") || !strcmp(count_token, "sum_mac")) { Log(LOG_WARNING, "WARN: [%s] pmacct was compiled with --disable-l2 but 'aggregate' contains a L2 primitive. Ignored.\n", filename); } #endif else if (!strcmp(count_token, "tos")) cfg_set_aggregate(filename, value, COUNT_INT_IP_TOS, count_token); else if (!strcmp(count_token, "none")) cfg_set_aggregate(filename, value, COUNT_INT_NONE, count_token); else if (!strcmp(count_token, "src_as")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_AS, count_token); else if (!strcmp(count_token, "dst_as")) cfg_set_aggregate(filename, value, COUNT_INT_DST_AS, count_token); else if (!strcmp(count_token, "sum_host")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_HOST, count_token); else if (!strcmp(count_token, "sum_net")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_NET, count_token); else if (!strcmp(count_token, "sum_as")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_AS, count_token); else if (!strcmp(count_token, "sum_port")) cfg_set_aggregate(filename, value, COUNT_INT_SUM_PORT, count_token); else if (!strcmp(count_token, "tag")) cfg_set_aggregate(filename, value, COUNT_INT_TAG, count_token); else if (!strcmp(count_token, "tag2")) cfg_set_aggregate(filename, value, COUNT_INT_TAG2, count_token); else if (!strcmp(count_token, "flows")) cfg_set_aggregate(filename, value, COUNT_INT_FLOWS, count_token); else if (!strcmp(count_token, "class_frame")) { // XXX: to deprecate if (config.acct_type == ACCT_NF) { #if defined (WITH_NDPI) cfg_set_aggregate(filename, value, COUNT_INT_NDPI_CLASS, count_token); #else Log(LOG_WARNING, "WARN: [%s] Class aggregation not possible due to missing --enable-ndpi\n", filename); #endif } } else if (!strcmp(count_token, "class")) { // XXX: to conciliate and merge with 'class_frame' if (config.acct_type == ACCT_NF) { cfg_set_aggregate(filename, value, COUNT_INT_CLASS, count_token); } else if (config.acct_type == ACCT_PM || config.acct_type == ACCT_SF) { #if defined (WITH_NDPI) cfg_set_aggregate(filename, value, COUNT_INT_NDPI_CLASS, count_token); #else Log(LOG_WARNING, "WARN: [%s] Class aggregation not possible due to missing --enable-ndpi\n", filename); #endif } } else if (!strcmp(count_token, "tcpflags")) cfg_set_aggregate(filename, value, COUNT_INT_TCPFLAGS, count_token); else if (!strcmp(count_token, "fwd_status")) cfg_set_aggregate(filename, value, COUNT_INT_FWD_STATUS, count_token); else if (!strcmp(count_token, "std_comm")) cfg_set_aggregate(filename, value, COUNT_INT_STD_COMM, count_token); else if (!strcmp(count_token, "ext_comm")) cfg_set_aggregate(filename, value, COUNT_INT_EXT_COMM, count_token); else if (!strcmp(count_token, "lrg_comm")) cfg_set_aggregate(filename, value, COUNT_INT_LRG_COMM, count_token); else if (!strcmp(count_token, "as_path")) cfg_set_aggregate(filename, value, COUNT_INT_AS_PATH, count_token); else if (!strcmp(count_token, "local_pref")) cfg_set_aggregate(filename, value, COUNT_INT_LOCAL_PREF, count_token); else if (!strcmp(count_token, "med")) cfg_set_aggregate(filename, value, COUNT_INT_MED, count_token); else if (!strcmp(count_token, "peer_src_as")) cfg_set_aggregate(filename, value, COUNT_INT_PEER_SRC_AS, count_token); else if (!strcmp(count_token, "peer_dst_as")) cfg_set_aggregate(filename, value, COUNT_INT_PEER_DST_AS, count_token); else if (!strcmp(count_token, "peer_src_ip")) cfg_set_aggregate(filename, value, COUNT_INT_PEER_SRC_IP, count_token); else if (!strcmp(count_token, "peer_dst_ip")) cfg_set_aggregate(filename, value, COUNT_INT_PEER_DST_IP, count_token); else if (!strcmp(count_token, "src_as_path")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_AS_PATH, count_token); else if (!strcmp(count_token, "src_std_comm")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_STD_COMM, count_token); else if (!strcmp(count_token, "src_ext_comm")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_EXT_COMM, count_token); else if (!strcmp(count_token, "src_lrg_comm")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_LRG_COMM, count_token); else if (!strcmp(count_token, "src_local_pref")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_LOCAL_PREF, count_token); else if (!strcmp(count_token, "src_med")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_MED, count_token); else if (!strcmp(count_token, "in_iface")) cfg_set_aggregate(filename, value, COUNT_INT_IN_IFACE, count_token); else if (!strcmp(count_token, "out_iface")) cfg_set_aggregate(filename, value, COUNT_INT_OUT_IFACE, count_token); else if (!strcmp(count_token, "src_mask")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_NMASK, count_token); else if (!strcmp(count_token, "dst_mask")) cfg_set_aggregate(filename, value, COUNT_INT_DST_NMASK, count_token); else if (!strcmp(count_token, "cos")) cfg_set_aggregate(filename, value, COUNT_INT_COS, count_token); else if (!strcmp(count_token, "etype")) cfg_set_aggregate(filename, value, COUNT_INT_ETHERTYPE, count_token); else if (!strcmp(count_token, "mpls_vpn_rd")) cfg_set_aggregate(filename, value, COUNT_INT_MPLS_VPN_RD, count_token); else if (!strcmp(count_token, "mpls_pw_id")) cfg_set_aggregate(filename, value, COUNT_INT_MPLS_PW_ID, count_token); else if (!strcmp(count_token, "sampling_rate")) cfg_set_aggregate(filename, value, COUNT_INT_SAMPLING_RATE, count_token); else if (!strcmp(count_token, "sampling_direction")) cfg_set_aggregate(filename, value, COUNT_INT_SAMPLING_DIRECTION, count_token); else if (!strcmp(count_token, "src_host_country")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_HOST_COUNTRY, count_token); else if (!strcmp(count_token, "dst_host_country")) cfg_set_aggregate(filename, value, COUNT_INT_DST_HOST_COUNTRY, count_token); else if (!strcmp(count_token, "post_nat_src_host")) cfg_set_aggregate(filename, value, COUNT_INT_POST_NAT_SRC_HOST, count_token); else if (!strcmp(count_token, "post_nat_dst_host")) cfg_set_aggregate(filename, value, COUNT_INT_POST_NAT_DST_HOST, count_token); else if (!strcmp(count_token, "post_nat_src_port")) cfg_set_aggregate(filename, value, COUNT_INT_POST_NAT_SRC_PORT, count_token); else if (!strcmp(count_token, "post_nat_dst_port")) cfg_set_aggregate(filename, value, COUNT_INT_POST_NAT_DST_PORT, count_token); else if (!strcmp(count_token, "nat_event")) cfg_set_aggregate(filename, value, COUNT_INT_NAT_EVENT, count_token); else if (!strcmp(count_token, "fw_event")) cfg_set_aggregate(filename, value, COUNT_INT_FW_EVENT, count_token); else if (!strcmp(count_token, "timestamp_start")) cfg_set_aggregate(filename, value, COUNT_INT_TIMESTAMP_START, count_token); else if (!strcmp(count_token, "timestamp_end")) cfg_set_aggregate(filename, value, COUNT_INT_TIMESTAMP_END, count_token); else if (!strcmp(count_token, "timestamp_arrival")) cfg_set_aggregate(filename, value, COUNT_INT_TIMESTAMP_ARRIVAL, count_token); else if (!strcmp(count_token, "timestamp_export")) cfg_set_aggregate(filename, value, COUNT_INT_EXPORT_PROTO_TIME, count_token); else if (!strcmp(count_token, "mpls_label_stack")) cfg_set_aggregate(filename, value, COUNT_INT_MPLS_LABEL_STACK, count_token); else if (!strcmp(count_token, "mpls_label_top")) cfg_set_aggregate(filename, value, COUNT_INT_MPLS_LABEL_TOP, count_token); else if (!strcmp(count_token, "mpls_label_bottom")) cfg_set_aggregate(filename, value, COUNT_INT_MPLS_LABEL_BOTTOM, count_token); else if (!strcmp(count_token, "label")) cfg_set_aggregate(filename, value, COUNT_INT_LABEL, count_token); else if (!strcmp(count_token, "export_proto_seqno")) cfg_set_aggregate(filename, value, COUNT_INT_EXPORT_PROTO_SEQNO, count_token); else if (!strcmp(count_token, "export_proto_version")) cfg_set_aggregate(filename, value, COUNT_INT_EXPORT_PROTO_VERSION, count_token); else if (!strcmp(count_token, "export_proto_sysid")) cfg_set_aggregate(filename, value, COUNT_INT_EXPORT_PROTO_SYSID, count_token); else if (!strcmp(count_token, "src_host_pocode")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_HOST_POCODE, count_token); else if (!strcmp(count_token, "dst_host_pocode")) cfg_set_aggregate(filename, value, COUNT_INT_DST_HOST_POCODE, count_token); else if (!strcmp(count_token, "src_host_coords")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_HOST_COORDS, count_token); else if (!strcmp(count_token, "dst_host_coords")) cfg_set_aggregate(filename, value, COUNT_INT_DST_HOST_COORDS, count_token); else if (!strcmp(count_token, "tunnel_src_mac")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_SRC_MAC, count_token); else if (!strcmp(count_token, "tunnel_dst_mac")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_DST_MAC, count_token); else if (!strcmp(count_token, "tunnel_src_host")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_SRC_HOST, count_token); else if (!strcmp(count_token, "tunnel_dst_host")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_DST_HOST, count_token); else if (!strcmp(count_token, "tunnel_proto")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_IP_PROTO, count_token); else if (!strcmp(count_token, "tunnel_tos")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_IP_TOS, count_token); else if (!strcmp(count_token, "tunnel_src_port")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_SRC_PORT, count_token); else if (!strcmp(count_token, "tunnel_dst_port")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_DST_PORT, count_token); else if (!strcmp(count_token, "tunnel_tcpflags")) cfg_set_aggregate(filename, value, COUNT_INT_TUNNEL_TCPFLAGS, count_token); else if (!strcmp(count_token, "src_roa")) cfg_set_aggregate(filename, value, COUNT_INT_SRC_ROA, count_token); else if (!strcmp(count_token, "dst_roa")) cfg_set_aggregate(filename, value, COUNT_INT_DST_ROA, count_token); else if (!strcmp(count_token, "vxlan")) cfg_set_aggregate(filename, value, COUNT_INT_VXLAN, count_token); else { cpptrs.primitive[cpptrs.num].name = count_token; cpptrs.num++; } } if (!name) for (; list; list = list->next, changes++) { list->cfg.what_to_count = value[1]; list->cfg.what_to_count_2 = value[2]; memcpy(&list->cfg.cpptrs, &cpptrs, sizeof(cpptrs)); } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.what_to_count = value[1]; list->cfg.what_to_count_2 = value[2]; memcpy(&list->cfg.cpptrs, &cpptrs, sizeof(cpptrs)); changes++; break; } } } return changes; } int cfg_key_aggregate_primitives(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.aggregate_primitives = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'aggregate_primitives'. Globalized.\n", filename); return changes; } int cfg_key_proc_name(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.proc_name = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key '%s_proc_name'. Globalized.\n", filename, config.progname); return changes; } int cfg_key_proc_priority(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (!name) for (; list; list = list->next, changes++) list->cfg.proc_priority = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.proc_priority = value; changes++; break; } } } return changes; } int cfg_key_cluster_name(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.cluster_name = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'cluster_name'. Globalized.\n", filename); return changes; } int cfg_key_cluster_id(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.cluster_id = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'cluster_id'. Globalized.\n", filename); return changes; } int cfg_key_redis_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.redis_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'redis_host'. Globalized.\n", filename); return changes; } int cfg_key_redis_db(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.redis_db = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'redis_db'. Globalized.\n", filename); return changes; } int cfg_key_snaplen(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < DEFAULT_SNAPLEN) { Log(LOG_WARNING, "WARN: [%s] 'snaplen' has to be >= %d.\n", filename, DEFAULT_SNAPLEN); return ERR; } for (; list; list = list->next, changes++) list->cfg.snaplen = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'snaplen'. Globalized.\n", filename); return changes; } int cfg_key_aggregate_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) { Log(LOG_ERR, "ERROR: [%s] aggregation filter cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.a_filter = value_ptr; changes++; break; } } } return changes; } int cfg_key_aggregate_unknown_etype(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.aggregate_unknown_etype = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'aggregate_unknown_etype'. Globalized.\n", filename); return changes; } int cfg_key_pre_tag_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) { Log(LOG_ERR, "ERROR: [%s] TAG filter cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { changes = load_tags(filename, &list->cfg.ptf, value_ptr); break; } } } return changes; } int cfg_key_pre_tag2_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) { Log(LOG_ERR, "ERROR: [%s] TAG2 filter cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { changes = load_tags(filename, &list->cfg.pt2f, value_ptr); break; } } } return changes; } int cfg_key_pre_tag_label_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) { Log(LOG_ERR, "ERROR: [%s] LABEL filter cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { changes = load_labels(filename, &list->cfg.ptlf, value_ptr); break; } } } return changes; } int cfg_key_pre_tag_label_encode_as_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.pretag_label_encode_as_map = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pretag_label_encode_as_map = value; changes++; break; } } } return changes; } int cfg_key_tcpflags_encode_as_array(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.tcpflags_encode_as_array = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tcpflags_encode_as_array = value; changes++; break; } } } return changes; } int cfg_key_fwd_status_encode_as_string(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.fwd_status_encode_as_string = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.fwd_status_encode_as_string = value; changes++; break; } } } return changes; } int cfg_key_tos_encode_as_dscp(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.tos_encode_as_dscp = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tos_encode_as_dscp = value; changes++; break; } } } return changes; } int cfg_key_mpls_label_stack_encode_as_array(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.mpls_label_stack_encode_as_array = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.mpls_label_stack_encode_as_array = value; changes++; break; } } } return changes; } int cfg_key_pcap_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.clbuf = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_filter'. Globalized.\n", filename); return changes; } int cfg_key_pcap_protocol(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = strtol(value_ptr, NULL, 0); for (; list; list = list->next, changes++) list->cfg.pcap_protocol = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_protocol'. Globalized.\n", filename); return changes; } int cfg_key_pcap_direction(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "in", strlen("in"))) value = PCAP_D_IN; else if (!strncmp(value_ptr, "out", strlen("out"))) value = PCAP_D_OUT; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'pcap_direction' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.pcap_direction = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_direction'. Globalized.\n", filename); return changes; } int cfg_key_pcap_ifindex(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "sys", strlen("sys"))) value = PCAP_IFINDEX_SYS; else if (!strncmp(value_ptr, "hash", strlen("hash"))) value = PCAP_IFINDEX_HASH; else if (!strncmp(value_ptr, "map", strlen("map"))) value = PCAP_IFINDEX_MAP; else if (!strncmp(value_ptr, "none", strlen("none"))) value = PCAP_IFINDEX_NONE; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'pcap_ifindex' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.pcap_ifindex = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_ifindex'. Globalized.\n", filename); return changes; } int cfg_key_pcap_interfaces_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.pcap_interfaces_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_interfaces_map'. Globalized.\n", filename); return changes; } int cfg_key_pcap_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.pcap_if = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_interface'. Globalized.\n", filename); return changes; } int cfg_key_files_umask(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; char *endp; value = strtoul(value_ptr, &endp, 8); if (value < 2) { Log(LOG_WARNING, "WARN: [%s] 'files_umask' has to be >= '002'.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.files_umask = value & 0666; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.files_umask = value & 0666; changes++; break; } } } return changes; } int cfg_key_files_uid(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; struct passwd *user = NULL; int value, changes = 0; user = getpwnam(value_ptr); if (!user) { value = atoi(value_ptr); if (value_ptr && !value && value_ptr[0] != '0'); else user = getpwuid(value); } if (user) value = user->pw_uid; else { Log(LOG_ERR, "WARN: [%s] Invalid 'files_uid'.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.files_uid = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.files_uid = value; changes++; break; } } } return changes; } int cfg_key_files_gid(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; struct group *group = NULL; u_int32_t value, changes = 0; group = getgrnam(value_ptr); if (!group) { value = atoi(value_ptr); if (value_ptr && !value && value_ptr[0] != '0'); else group = getgrgid(value); } if (group) value = group->gr_gid; else { Log(LOG_ERR, "WARN: [%s] Invalid 'files_gid'.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.files_gid = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.files_gid = value; changes++; break; } } } return changes; } int cfg_key_pcap_interface_wait(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.pcap_if_wait = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_interface_wait'. Globalized.\n", filename); return changes; } int cfg_key_pcap_savefile_wait(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.pcap_sf_wait = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_savefile_wait'. Globalized.\n", filename); return changes; } int cfg_key_pcap_savefile_delay(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'pcap_savefile_delay' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.pcap_sf_delay = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_savefile_delay'. Globalized.\n", filename); return changes; } int cfg_key_pcap_savefile_replay(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'pcap_savefile_replay' has to be >= 0.\n", filename); return ERR; } else if (value == 0) value = -1; for (; list; list = list->next, changes++) list->cfg.pcap_sf_replay = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_savefile_replay'. Globalized.\n", filename); return changes; } int cfg_key_promisc(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.promisc = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'promisc'. Globalized.\n", filename); return changes; } int cfg_key_imt_path(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.imt_plugin_path = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.imt_plugin_path = value_ptr; changes++; break; } } } return changes; } int cfg_key_imt_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.imt_plugin_passwd = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.imt_plugin_passwd = value_ptr; changes++; break; } } } return changes; } int cfg_key_imt_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'imt_buckets' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.buckets = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.buckets = value; changes++; break; } } } return changes; } int cfg_key_imt_mem_pools_number(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'imt_mem_pools_number' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.num_memory_pools = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.num_memory_pools = value; changes++; break; } } } return changes; } int cfg_key_imt_mem_pools_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; /* legal values should be >= sizeof(struct acc), though we are unable to check this condition here. Thus, this function will just cut clearly wrong values ie. < = 0. Strict checks will be accomplished later, by the memory plugin */ value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'imt_mem_pools_size' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.memory_pool_size = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.memory_pool_size = value; changes++; break; } } } return changes; } int cfg_key_sql_db(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_db = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_db = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_table(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; /* validations: we allow only a) certain variable names, b) a maximum of 32 variables and c) a maximum table name length of 64 chars */ { int num = 0; char *c, *ptr = value_ptr; while ((c = strchr(ptr, '%'))) { c++; ptr = c; switch (*c) { case 'd': num++; break; case 'H': num++; break; case 'm': num++; break; case 'M': num++; break; case 'w': num++; break; case 'W': num++; break; case 'Y': num++; break; case 's': num++; break; case 'S': num++; break; case 'z': num++; break; default: Log(LOG_ERR, "ERROR: [%s] sql_table, %%%c not supported.\n", filename, *c); exit(1); break; } } if (num > 32) { Log(LOG_ERR, "ERROR: [%s] sql_table, exceeded the maximum allowed variables (32) into the table name.\n", filename); exit(1); } } if (strlen(value_ptr) > 64) { Log(LOG_ERR, "ERROR: [%s] sql_table, exceeded the maximum SQL table name length (64).\n", filename); exit(1); } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_table = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_table = value_ptr; changes++; break; } } } return changes; } int cfg_key_print_output_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; /* validations: we allow only a) certain variable names, b) a maximum of 32 variables */ { int num = 0; char *c, *ptr = value_ptr; while ((c = strchr(ptr, '%'))) { c++; ptr = c; switch (*c) { case 'd': num++; break; case 'H': num++; break; case 'm': num++; break; case 'M': num++; break; case 'w': num++; break; case 'W': num++; break; case 'Y': num++; break; case 's': num++; break; case 'S': num++; break; case 'z': num++; break; default: Log(LOG_ERR, "ERROR: [%s] print_output_file, %%%c not supported.\n", filename, *c); exit(1); break; } } if (num > 32) { Log(LOG_ERR, "ERROR: [%s] print_output_file, exceeded the maximum allowed variables (32) into the filename.\n", filename); exit(1); } } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_table = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_table = value_ptr; changes++; break; } } } return changes; } int cfg_key_print_latest_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (strchr(value_ptr, '%')) { Log(LOG_ERR, "ERROR: [%s] invalid 'print_latest_file' value: time-based '%%' variables not allowed.\n", filename); return TRUE; } if (!name) for (; list; list = list->next, changes++) list->cfg.print_latest_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_latest_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_print_output_file_append(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.print_output_file_append = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output_file_append = value; changes++; break; } } } return changes; } int cfg_key_print_write_empty_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.print_write_empty_file = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_write_empty_file = value; changes++; break; } } } return changes; } int cfg_key_print_output_lock_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.print_output_lock_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output_lock_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_table_schema(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_table_schema = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_table_schema = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_table_version(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "ERROR: [%s] invalid 'sql_table_version' value.\n", filename); exit(1); } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_table_version = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_table_version = value; changes++; break; } } } return changes; } int cfg_key_sql_table_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "bgp")); else if (!strcmp(value_ptr, "original")); else { Log(LOG_WARNING, "WARN: [%s] Invalid sql_table_type value '%s'\n", filename, value_ptr); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_table_type = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_table_type = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_data(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; lower_string(value_ptr); if (!name) for (; list; list = list->next, changes++) list->cfg.sql_data = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_data = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_conn_ca_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_conn_ca_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_conn_ca_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_host = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_host = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'sql_port' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_port = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_port = value; changes++; break; } } } return changes; } int cfg_key_sql_recovery_backup_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; cfg_key_legacy_warning(filename, "sql_backup_host"); if (!name) for (; list; list = list->next, changes++) list->cfg.sql_backup_host = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_backup_host = value_ptr; changes++; break; } } } return changes; } int cfg_key_dump_max_writers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1 || value >= 100) { Log(LOG_WARNING, "WARN: [%s] invalid 'dump_max_writers' value). Allowed values are: 1 <= dump_max_writers < 100.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.dump_max_writers = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.dump_max_writers = value; changes++; break; } } } return changes; } int cfg_key_sql_trigger_exec(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_trigger_exec = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_trigger_exec = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_trigger_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, t, t_howmany; parse_time(filename, value_ptr, &t, &t_howmany); if (!name) { for (; list; list = list->next, changes++) { list->cfg.sql_trigger_time = t; list->cfg.sql_trigger_time_howmany = t_howmany; } } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_trigger_time = t; list->cfg.sql_trigger_time_howmany = t_howmany; changes++; break; } } } return changes; } int cfg_key_sql_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_user = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_user = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_passwd = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_passwd = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'sql_refresh_time' is expected in secs but contains non-digit chars: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'sql_refresh_time' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_refresh_time = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_refresh_time = value; changes++; break; } } } return changes; } int cfg_key_sql_startup_delay(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'sql_startup_delay' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_startup_delay = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_startup_delay = value; changes++; break; } } } return changes; } int cfg_key_sql_optimize_clauses(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_optimize_clauses = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_optimize_clauses = value; changes++; break; } } } return changes; } int cfg_key_sql_history_roundoff(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; int i, check, len; len = strlen(value_ptr); for (i = 0, check = 0; i < len; i++) { if (value_ptr[i] == 'd') check |= COUNT_DAILY; if (value_ptr[i] == 'w') check |= COUNT_WEEKLY; if (value_ptr[i] == 'M') check |= COUNT_MONTHLY; } if (((check & COUNT_DAILY) || (check & COUNT_MONTHLY)) && (check & COUNT_WEEKLY)) { Log(LOG_ERR, "WARN: [%s] 'sql_history_roundoff' 'w' is not compatible with either 'd' or 'M'.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_history_roundoff = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_history_roundoff = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_history(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, sql_history, sql_history_howmany; parse_time(filename, value_ptr, &sql_history, &sql_history_howmany); if (!name) { for (; list; list = list->next, changes++) { list->cfg.sql_history = sql_history; list->cfg.sql_history_howmany = sql_history_howmany; } } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_history = sql_history; list->cfg.sql_history_howmany = sql_history_howmany; changes++; break; } } } return changes; } int cfg_key_sql_history_offset(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'sql_history_offset' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_history_offset = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_history_offset = value; changes++; break; } } } return changes; } int cfg_key_timestamps_since_epoch(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.timestamps_since_epoch = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.timestamps_since_epoch = value; changes++; break; } } } return changes; } int cfg_key_sql_cache_entries(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'sql_cache_entries' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_cache_entries = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_cache_entries = value; changes++; break; } } } return changes; } int cfg_key_sql_dont_try_update(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_dont_try_update = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_dont_try_update = value; changes++; break; } } } return changes; } int cfg_key_sql_preprocess(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_preprocess = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_preprocess = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_preprocess_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "any", 3)) value = FALSE; if (!strncmp(value_ptr, "all", 3)) value = TRUE; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_preprocess_type = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_preprocess_type = value; changes++; break; } } } return changes; } int cfg_key_sql_multi_values(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'sql_multi_values' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_multi_values = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_multi_values = value; changes++; break; } } } return changes; } int cfg_key_mongo_insert_batch(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'mongo_insert_batch' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.mongo_insert_batch = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.mongo_insert_batch = value; changes++; break; } } } return changes; } int cfg_key_message_broker_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] '[amqp|kafka]_output' set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] '[amqp|kafka]_output' set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] '[amqp|kafka]_output' set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "custom")) { value = PRINT_OUTPUT_CUSTOM; } else { Log(LOG_WARNING, "WARN: [%s] Invalid '[amqp|kafka]_output' value '%s'\n", filename, value_ptr); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.message_broker_output = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.message_broker_output = value; changes++; break; } } } return changes; } int cfg_key_avro_buffer_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'avro_buffer_size' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.avro_buffer_size = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.avro_buffer_size = value; changes++; break; } } } return changes; } int cfg_key_avro_schema_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.avro_schema_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.avro_schema_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_exchange_type = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_exchange_type = value_ptr; changes++; break; } } } return changes; } int cfg_key_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_persistent_msg = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_persistent_msg = value; changes++; break; } } } return changes; } int cfg_key_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'amqp_frame_max' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_frame_max = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_frame_max = value; changes++; break; } } } return changes; } int cfg_key_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_heartbeat_interval = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_heartbeat_interval = value; changes++; break; } } } return changes; } int cfg_key_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_vhost = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_vhost = value_ptr; changes++; break; } } } return changes; } int cfg_key_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_routing_key_rr = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_routing_key_rr = value; changes++; break; } } } return changes; } int cfg_key_amqp_avro_schema_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_avro_schema_routing_key = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_avro_schema_routing_key = value_ptr; changes++; break; } } } return changes; } int cfg_key_amqp_avro_schema_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'amqp_avro_schema_refresh_time' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.amqp_avro_schema_refresh_time = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.amqp_avro_schema_refresh_time = value; changes++; break; } } } return changes; } int cfg_key_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_broker_port = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_broker_port = value; changes++; break; } } } return changes; } int cfg_key_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_partition = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_partition = value; changes++; break; } } } return changes; } int cfg_key_kafka_partition_dynamic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_partition_dynamic = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_partition_dynamic = value; changes++; break; } } } return changes; } int cfg_key_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); lower_string(value_ptr); if (!name) for (; list; list = list->next, changes++) { list->cfg.kafka_partition_key = value_ptr; list->cfg.kafka_partition_keylen = value_len; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_partition_key = value_ptr; list->cfg.kafka_partition_keylen = value_len; changes++; break; } } } return changes; } int cfg_key_kafka_avro_schema_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; cfg_key_legacy_warning(filename, "kafka_avro_schema_topic"); if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_avro_schema_topic = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_avro_schema_topic = value_ptr; changes++; break; } } } return changes; } int cfg_key_kafka_avro_schema_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; cfg_key_legacy_warning(filename, "kafka_avro_schema_refresh_time"); value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'kakfa_avro_schema_refresh_time' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_avro_schema_refresh_time = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_avro_schema_refresh_time = value; changes++; break; } } } return changes; } int cfg_key_kafka_avro_schema_registry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_avro_schema_registry = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_avro_schema_registry = value_ptr; changes++; break; } } } return changes; } int cfg_key_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.kafka_config_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.kafka_config_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_locking_style(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; lower_string(value_ptr); if (!name) for (; list; list = list->next, changes++) list->cfg.sql_locking_style = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_locking_style = value_ptr; changes++; break; } } } return changes; } int cfg_key_sql_use_copy(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.sql_use_copy = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_use_copy = value; changes++; break; } } } return changes; } int cfg_key_sql_delimiter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; /* delimiter is only one character */ if (strlen(value_ptr) != 1) { Log(LOG_WARNING, "WARN: [%s] 'sql_delimiter' length has to be 1.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sql_delimiter = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sql_delimiter = value_ptr; changes++; break; } } } return changes; } int cfg_key_timestamps_rfc3339(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.timestamps_rfc3339 = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.timestamps_rfc3339 = value; changes++; break; } } } return changes; } int cfg_key_timestamps_utc(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.timestamps_utc = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.timestamps_utc = value; changes++; break; } } } return changes; } int cfg_key_timestamps_secs(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.timestamps_secs = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.timestamps_secs = value; changes++; break; } } } return changes; } int cfg_key_plugin_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; /* legal values should be >= sizeof(struct pkt_data)+sizeof(struct ch_buf_hdr) though we are unable to check this condition here. Thus, this function will just cut clearly wrong values ie. < = 0. Strict checks will be accomplished later, by the load_plugins() */ value = strtoull(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'plugin_pipe_size' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.pipe_size = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pipe_size = value; changes++; break; } } } return changes; } int cfg_key_plugin_pipe_zmq(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.pipe_zmq = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pipe_zmq = value; changes++; break; } } } return changes; } int cfg_key_plugin_pipe_zmq_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'plugin_pipe_zmq_retry' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.pipe_zmq_retry = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pipe_zmq_retry = value; changes++; break; } } } return changes; } int cfg_key_plugin_pipe_zmq_profile(char *filename, char *name, char *value_ptr) { int changes = 0; lower_string(value_ptr); #ifdef WITH_ZMQ struct plugins_list_entry *list = plugins_list; int value; if (!name) for (; list; list = list->next, changes++) { value = p_zmq_plugin_pipe_set_profile(&list->cfg, value_ptr); if (value < 0) return ERR; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { value = p_zmq_plugin_pipe_set_profile(&list->cfg, value_ptr); if (value < 0) return ERR; changes++; break; } } } #endif return changes; } int cfg_key_plugin_pipe_zmq_hwm(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'plugin_pipe_zmq_hwm' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.pipe_zmq_hwm = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pipe_zmq_hwm = value; changes++; break; } } } return changes; } int cfg_key_plugin_exit_any(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.plugin_exit_any = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'plugin_exit_any'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] '%s_pipe_size' has to be > 0 and <= INT_MAX.\n", filename, config.progname); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_pipe_size = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key '%s_pipe_size'. Globalized.\n", filename, config.progname); return changes; } int cfg_key_nfacctd_pro_rating(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfacctd_pro_rating = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfacctd_pro_rating = value; changes++; break; } } } return changes; } int cfg_key_nfacctd_templates_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_templates_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_templates_file'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_templates_receiver(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_templates_receiver = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_templates_receiver'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_templates_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'nfacctd_templates_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_templates_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_templates_port'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_stitching(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfacctd_stitching = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfacctd_stitching = value; changes++; break; } } } return changes; } int cfg_key_nfacctd_account_options(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_account_options = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_account_options'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] 'bgp_daemon_pipe_size' has to be > 0 and <= INT_MAX.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_pipe_size = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_pipe_size'. Globalized.\n", filename); return changes; } int cfg_key_plugin_buffer_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; /* legal values should be >= sizeof(struct pkt_data) and < plugin_pipe_size value, if any though we are unable to check this condition here. Thus, this function will just cut clearly wrong values ie. < = 0. Strict checks will be accomplished later, by the load_plugins() */ value = strtoull(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'plugin_buffer_size' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.buffer_size = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.buffer_size = value; changes++; break; } } } return changes; } int cfg_key_networks_mask(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'networks_mask' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.networks_mask = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_mask = value; changes++; break; } } } return changes; } int cfg_key_networks_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.networks_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_networks_file_filter(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.networks_file_filter = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_file_filter = value; changes++; break; } } } return changes; } int cfg_key_networks_file_no_lpm(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.networks_file_no_lpm = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_file_no_lpm = value; changes++; break; } } } return changes; } int cfg_key_networks_no_mask_if_zero(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.networks_no_mask_if_zero = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_no_mask_if_zero = value; changes++; break; } } } return changes; } int cfg_key_networks_cache_entries(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'networks_cache_entries' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.networks_cache_entries = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.networks_cache_entries = value; changes++; break; } } } return changes; } int cfg_key_ports_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.ports_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.ports_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_protos_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.protos_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.protos_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_tos_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.tos_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tos_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_maps_refresh(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.maps_refresh = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'maps_refresh'. Globalized.\n", filename); return changes; } int cfg_key_print_cache_entries(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'print_cache_entries' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.print_cache_entries = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_cache_entries = value; changes++; break; } } } return changes; } int cfg_key_print_markers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.print_markers = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_markers = value; changes++; break; } } } return changes; } int cfg_key_print_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "formatted")) value = PRINT_OUTPUT_FORMATTED; else if (!strcmp(value_ptr, "csv")) value = PRINT_OUTPUT_CSV; else if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] print_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "event_formatted")) { value = PRINT_OUTPUT_FORMATTED; value |= PRINT_OUTPUT_EVENT; } else if (!strcmp(value_ptr, "event_csv")) { value = PRINT_OUTPUT_CSV; value |= PRINT_OUTPUT_EVENT; } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] print_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] print_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "custom")) { value = PRINT_OUTPUT_CUSTOM; } else { Log(LOG_WARNING, "WARN: [%s] Invalid print output value '%s'\n", filename, value_ptr); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.print_output = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output = value; changes++; break; } } } return changes; } int cfg_key_print_output_separator(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (strlen(value_ptr) != 1) { if (!strcmp(value_ptr, "\\t") || !strcmp(value_ptr, "\\s")); else { Log(LOG_WARNING, "WARN: [%s] Invalid print_output_separator value '%s'. Only one char allowed.\n", filename, value_ptr); return ERR; } } if (!name) for (; list; list = list->next, changes++) list->cfg.print_output_separator = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output_separator = value_ptr; changes++; break; } } } return changes; } int cfg_key_num_protos(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.num_protos = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.num_protos = value; changes++; break; } } } return changes; } int cfg_key_num_hosts(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.num_hosts = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.num_hosts = value; changes++; break; } } } return changes; } int cfg_key_post_tag(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; pm_id_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'post_tag' cannot be zero.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.post_tag = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.post_tag = value; changes++; break; } } } return changes; } int cfg_key_post_tag2(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; pm_id_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'post_tag2' cannot be zero.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.post_tag2 = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.post_tag2 = value; changes++; break; } } } return changes; } int cfg_key_sampling_rate(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'sampling_rate' has to be >= 1.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sampling_rate = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sampling_rate = value; changes++; break; } } } return changes; } int cfg_key_sampling_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sampling_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sampling_map'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'nfacctd_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_port'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_ip'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_interface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_interface'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_ipv6_only(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_ipv6_only = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key '%s_ipv6_only'. Globalized.\n", filename, config.progname); return changes; } int cfg_key_nfacctd_rp_ebpf_prog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_rp_ebpf_prog = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_rp_ebpf_prog'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'nfacctd_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_zmq_address(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_zmq_address = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_zmq_address'. Globalized.\n", filename); return changes; } int cfg_key_dtls_path(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.dtls_path = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'dtls_path'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_dtls_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'nfacctd_dtls_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_dtls_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_dtls_port'. Globalized.\n", filename); return changes; } int cfg_key_writer_id_string(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.writer_id_string = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.writer_id_string = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfacctd_allow_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_allow_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_allow_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_allow_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_allow_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_allow_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_md5_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_md5_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_md5_file'. Globalized.\n", filename); return changes; } int cfg_key_pre_tag_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.pre_tag_map = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.pre_tag_map = value_ptr; changes++; break; } } } return changes; } int cfg_key_maps_entries(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'maps_entries' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.maps_entries = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.maps_entries = value; changes++; break; } } } return changes; } int cfg_key_maps_row_len(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'maps_row_len' has to be > 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.maps_row_len = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.maps_row_len = value; changes++; break; } } } return changes; } int cfg_key_maps_index(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.maps_index = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'maps_index'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_time_secs(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) { if (!list->cfg.nfacctd_time) { if (value) list->cfg.nfacctd_time = NF_TIME_SECS; } else Log(LOG_WARNING, "WARN: [%s] Possibly 'nfacctd_time_new: true' set. 'nfacctd_time_secs' ignored.\n", filename); } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_time_secs'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_time_new(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) { if (!list->cfg.nfacctd_time) { if (value) { list->cfg.nfacctd_time = NF_TIME_NEW; list->cfg.nfacctd_time_new = TRUE; } } else Log(LOG_WARNING, "WARN: [%s] Possibly 'nfacctd_time_secs: true' set. 'nfacctd_time_new' ignored.\n", filename); } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_time_new'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_mcast_groups(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; struct host_addr tmp_addr; char *count_token; u_int32_t changes = 0; u_int8_t idx = 0, more = 0; trim_all_spaces(value_ptr); memset(mcast_groups, 0, sizeof(mcast_groups)); while ((count_token = extract_token(&value_ptr, ','))) { memset(&tmp_addr, 0, sizeof(tmp_addr)); str_to_addr(count_token, &tmp_addr); if (is_multicast(&tmp_addr)) { if (idx < MAX_MCAST_GROUPS) { memcpy(&mcast_groups[idx], &tmp_addr, sizeof(tmp_addr)); idx++; } else more++; } } for (; list; list = list->next, changes++); /* Nothing to do because of the global array, just rolling changes counters */ if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for keys '%s_mcast_groups'. Globalized.\n", filename, config.progname); if (more) Log(LOG_WARNING, "WARN: [%s] Only the first %u (on a total of %u) multicast groups will be joined.\n", filename, MAX_MCAST_GROUPS, MAX_MCAST_GROUPS+more); return changes; } int cfg_key_bgp_daemon(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "false")) value = BGP_DAEMON_NONE; else if (!strcmp(value_ptr, "true")) value = BGP_DAEMON_ONLINE; else { Log(LOG_ERR, "WARN: [%s] Invalid 'bgp_daemon' value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_add_path_ignore(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_add_path_ignore = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_add_path_ignore'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_tag_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_tag_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_tag_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_aspath_radius(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'bgp_aspath_radius' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_aspath_radius = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_aspath_radius'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_stdcomm_pattern(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_stdcomm_pattern = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_stdcomm_pattern'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_extcomm_pattern(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_extcomm_pattern = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_extcomm_pattern'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_lrgcomm_pattern(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_lrgcomm_pattern = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_lrgcomm_pattern'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_stdcomm_pattern_to_asn(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_stdcomm_pattern_to_asn = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_stdcomm_pattern_to_asn'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_lrgcomm_pattern_to_asn(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_lrgcomm_pattern_to_asn = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_lrgcomm_pattern_to_asn'. Globalized.\n", filename); return changes; } int cfg_key_bgp_blackhole_stdcomm_list(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_blackhole_stdcomm_list = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_blackhole_stdcomm_list'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_peer_src_as_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "netflow", strlen("netflow"))) value = BGP_SRC_PRIMITIVES_KEEP; else if (!strncmp(value_ptr, "sflow", strlen("sflow"))) value = BGP_SRC_PRIMITIVES_KEEP; else if (!strncmp(value_ptr, "map", strlen("map"))) value = BGP_SRC_PRIMITIVES_MAP; else if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else if (!strncmp(value_ptr, "fallback", strlen("fallback")) || !strncmp(value_ptr, "longest", strlen("longest"))) { value = BGP_SRC_PRIMITIVES_KEEP; value |= BGP_SRC_PRIMITIVES_BGP; } else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_peer_src_as_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_peer_as_src_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_peer_src_as_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_std_comm_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_std_comm_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_std_comm_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_std_comm_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_ext_comm_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_ext_comm_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_ext_comm_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_ext_comm_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_lrg_comm_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_lrg_comm_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_lrg_comm_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_lrg_comm_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_as_path_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_as_path_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_as_path_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_as_path_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_local_pref_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "map", strlen("map"))) value = BGP_SRC_PRIMITIVES_MAP; else if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_local_pref_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_local_pref_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_local_pref_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_med_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "map", strlen("map"))) value = BGP_SRC_PRIMITIVES_MAP; else if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_med_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_med_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_med_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_roa_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_SRC_PRIMITIVES_UNK, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "bgp", strlen("bgp"))) value = BGP_SRC_PRIMITIVES_BGP; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_src_roa_type' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_roa_type = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_roa_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_peer_as_skip_subas(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_peer_as_skip_subas = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_peer_as_skip_subas'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_local_pref_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_local_pref_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_local_pref_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_peer_src_as_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_peer_as_src_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_peer_src_as_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_src_med_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_src_med_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_src_med_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_to_xflow_agent_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_to_xflow_agent_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_to_agent_map'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_flow_to_rd_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_flow_to_rd_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'flow_to_rd_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_follow_default(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_follow_default = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_follow_default'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_follow_nexthop(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; char *count_token; int changes = 0, idx = 0, valid = 0; trim_all_spaces(value_ptr); while ((count_token = extract_token(&value_ptr, ',')) && idx < FOLLOW_BGP_NH_ENTRIES) { for (list = plugins_list; list; list = list->next) { valid = str2prefix(count_token, &list->cfg.bgp_daemon_follow_nexthop[idx]); if (!valid) { Log(LOG_WARNING, "WARN: [%s] bgp_follow_nexthop: invalid IP prefix '%s'.\n", filename, count_token); break; } } if (valid) idx++; } changes = idx; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_follow_nexthop'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_follow_nexthop_external(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_follow_nexthop_external = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_follow_nexthop_external'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_disable_router_id_check(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_disable_router_id_check = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_disable_router_id_check'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_neighbors_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_neighbors_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_neighbors_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_max_peers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_max_peers' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_max_peers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_max_peers'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_ip'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_interface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_interface'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_ipv6_only(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_ipv6_only = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_ipv6_only'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_id(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_id = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_id'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_as(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; char *endptr; as_t value; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_as = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_as'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_port'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_rp_ebpf_prog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_rp_ebpf_prog = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_rp_ebpf_prog'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_workers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_workers' value has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_workers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_workers'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_lg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_lg_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg_ip'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_lg_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_lg_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg_port'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg_threads(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_lg_threads' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_lg_threads = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg_threads'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_lg_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg_user'. Globalized.\n", filename); return changes; } int cfg_key_bgp_lg_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_lg_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_lg_passwd'. Globalized.\n", filename); return changes; } int cfg_key_bgp_xconnect_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_xconnect_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_xconnect_map'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_ip_precedence(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 0) || (value > 7)) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_ipprec' has to be in the range 0-7.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_ipprec = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_ipprec'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_peer_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 1000)) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_peer_buckets' has to be in the range 1-1000.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_peer_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_peer_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_per_peer_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 128)) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_per_peer_buckets' has to be in the range 1-128.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_per_peer_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_per_peer_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_attr_hash_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 1000000)) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_attr_hash_buckets' has to be in the range 1-1000000.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_attr_hash_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_attr_hash_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_per_peer_hash(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_ASPATH_HASH_PATHID, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "path_id", strlen("path_id"))) value = BGP_ASPATH_HASH_PATHID; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bgp_table_per_peer_hash' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bgp_table_per_peer_hash = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_per_peer_hash'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_batch_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_batch_interval' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_batch_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_batch_interval'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_batch(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_batch' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_batch = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_batch'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bmp_daemon = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_ip'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_interface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_interface'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_ipv6_only(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_ipv6_only = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_ipv6_only'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_port'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_rp_ebpf_prog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_rp_ebpf_prog = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_rp_ebpf_prog'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_tag_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_tag_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_tag_map'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_pipe_size' has to be > 0 and <= INT_MAX.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_pipe_size = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_pipe_size'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_max_peers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_max_peers' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_max_peers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_max_peers'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_allow_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_allow_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_allow_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_ip_precedence(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 0) || (value > 7)) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_ipprec' has to be in the range 0-7.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_ipprec = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_ipprec'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_batch_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_batch_interval' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_batch_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_batch_interval'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_batch(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_batch' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_batch = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_batch'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_table_peer_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 1000)) { Log(LOG_ERR, "WARN: [%s] 'bmp_table_peer_buckets' has to be in the range 1-1000.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_table_peer_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_table_peer_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_table_per_peer_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 128)) { Log(LOG_ERR, "WARN: [%s] 'bmp_table_per_peer_buckets' has to be in the range 1-128.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_table_per_peer_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_table_per_peer_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_table_attr_hash_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 1000000)) { Log(LOG_ERR, "WARN: [%s] 'bmp_table_attr_hash_buckets' has to be in the range 1-1000000.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_table_attr_hash_buckets = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_table_attr_hash_buckets'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_table_per_peer_hash(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value = BGP_ASPATH_HASH_PATHID, changes = 0; lower_string(value_ptr); if (!strncmp(value_ptr, "path_id", strlen("path_id"))) value = BGP_ASPATH_HASH_PATHID; else Log(LOG_WARNING, "WARN: [%s] Ignoring unknown 'bmp_table_per_peer_hash' value.\n", filename); for (; list; list = list->next, changes++) list->cfg.bmp_table_per_peer_hash = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_table_per_peer_hash'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_avro_schema_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_avro_schema_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_avro_schema_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] bmp_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_msglog_output' set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_msglog_output' set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid bmp_daemon_msglog_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_output'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_msglog_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_msglog_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_amqp_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_msglog_amqp_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_amqp_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_amqp_retry'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_latest_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_latest_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_latest_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_avro_schema_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_avro_schema_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_avro_schema_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] bmp_dump_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] bmp_dump_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] bmp_dump_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid bmp_dump_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_output'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_workers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_workers' value has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_workers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_workers'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_refresh_time' is expected in secs but contains non-digit chars: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < MIN_REFRESH_TIME || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_refresh_time' value has to be >= %d and <= %d secs.\n", filename, MIN_REFRESH_TIME, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_refresh_time = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_refresh_time'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_time_slots(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_time_slots' is expected to be an integer value: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < 1 || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_time_slots' value has to be >= 1 and <= %d.\n", filename, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_time_slots = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_time_slots'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_dump_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_dump_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.bmp_dump_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_isis = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_isis_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon_ip'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis_net(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_isis_net = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon_net'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis_iface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.nfacctd_isis_iface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon_iface'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis_mtu(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < SNAPLEN_ISIS_MIN) { Log(LOG_WARNING, "WARN: [%s] 'isis_daemon_mtu' has to be >= %d.\n", filename, SNAPLEN_ISIS_MIN); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_isis_mtu = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon_mtu'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_isis_msglog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_isis_msglog = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'isis_daemon_msglog'. Globalized.\n", filename); return changes; } int cfg_key_igp_daemon_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.igp_daemon_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'igp_daemon_map'. Globalized.\n", filename); return changes; } int cfg_key_igp_daemon_map_msglog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.igp_daemon_map_msglog = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'igp_daemon_map_msglog'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_force_frag_handling(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.handle_fragments = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_force_frag_handling'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_frag_buffer_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_frag_buffer_size' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.frag_bufsz = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_frag_buffer_size'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_flow_buffer_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_flow_buffer_size' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.flow_bufsz = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_flow_buffer_size'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_flow_buffer_buckets(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'flow_buffer_buckets' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.flow_hashsz = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_flow_buffer_buckets'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_conntrack_buffer_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_conntrack_buffer_size' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.conntrack_bufsz = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_conntrack_buffer_size'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_flow_lifetime(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_flow_lifetime' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.flow_lifetime = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_flow_lifetime'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_flow_tcp_lifetime(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_flow_tcp_lifetime' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.flow_tcp_lifetime = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_flow_tcp_lifetime'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_ext_sampling_rate(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'pmacctd_ext_sampling_rate' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.ext_sampling_rate = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_ext_sampling_rate'. Globalized.\n", filename); return changes; } int cfg_key_pmacctd_nonroot(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.pmacctd_nonroot = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pmacctd_nonroot'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_renormalize(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.sfacctd_renormalize = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_renormalize'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_file'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] sfacctd_counter_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid sfacctd_counter_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_output'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'sfacctd_counter_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_amqp_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'sfacctd_counter_amqp_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_amqp_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_amqp_retry'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'sfacctd_counter_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'sfacctd_counter_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.sfacctd_counter_kafka_partition_key = value_ptr; list->cfg.sfacctd_counter_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'sfacctd_counter_kafka_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_retry'. Globalized.\n", filename); return changes; } int cfg_key_sfacctd_counter_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.sfacctd_counter_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'sfacctd_counter_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_pcap_savefile(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.pcap_savefile = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'pcap_savefile'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_as_new(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "false") /* legacy */ || !strcmp(value_ptr, "netflow") || !strcmp(value_ptr, "sflow")) { if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) value = NF_AS_KEEP; else { Log(LOG_ERR, "WARN: [%s] Invalid AS aggregation value '%s'\n", filename, value_ptr); return ERR; } } else if (!strcmp(value_ptr, "true") /* legacy */ || !strcmp(value_ptr, "file")) value = NF_AS_NEW; else if (!strcmp(value_ptr, "bgp") || !strcmp(value_ptr, "bmp")) value = NF_AS_BGP; else if (!strcmp(value_ptr, "fallback") || !strcmp(value_ptr, "longest")) { value = NF_AS_FALLBACK; if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { value |= NF_AS_KEEP; value |= NF_AS_BGP; } else value |= NF_AS_BGP; /* NF_AS_KEEP does not apply to ACCT_PM and ACCT_UL; we set value to NF_AS_BGP since we can't fallback to any alternative method as of yet */ } else { Log(LOG_ERR, "WARN: [%s] Invalid AS aggregation value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.nfacctd_as = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key '%s_as_new'. Globalized.\n", filename, config.progname); return changes; } int cfg_key_nfacctd_net(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "sflow") || !strcmp(value_ptr, "netflow")) { if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) value = NF_NET_KEEP; else { Log(LOG_ERR, "WARN: [%s] Invalid network aggregation value '%s'\n", filename, value_ptr); return ERR; } } else if (!strcmp(value_ptr, "file")) value = NF_NET_NEW; else if (!strcmp(value_ptr, "mask")) value = NF_NET_STATIC; else if (!strcmp(value_ptr, "bgp") || !strcmp(value_ptr, "bmp")) value = NF_NET_BGP; else if (!strcmp(value_ptr, "igp")) value = NF_NET_IGP; else if (!strcmp(value_ptr, "fallback") || !strcmp(value_ptr, "longest")) { value = NF_NET_FALLBACK; if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) { value |= NF_NET_KEEP; value |= NF_NET_BGP; value |= NF_NET_IGP; } else { value |= NF_NET_BGP; value |= NF_NET_IGP; } } else { Log(LOG_ERR, "WARN: [%s] Invalid network aggregation value '%s'\n", filename, value_ptr); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.nfacctd_net = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfacctd_net = value; changes++; break; } } } return changes; } int cfg_key_nfacctd_disable_checks(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse_nonzero(value_ptr); if (value == ERR) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_disable_checks = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key '[ns]facctd_disable_checks'. Globalized.\n", filename); return changes; } int cfg_key_nfacctd_disable_opt_scope_check(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse_nonzero(value_ptr); if (value == ERR) return ERR; for (; list; list = list->next, changes++) list->cfg.nfacctd_disable_opt_scope_check = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'nfacctd_disable_opt_scope_check'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_num_roots(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.ndpi_num_roots = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_num_roots'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_max_flows(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.ndpi_max_flows = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_max_flows'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_proto_guess(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.ndpi_proto_guess = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_proto_guess'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_idle_scan_period(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.ndpi_idle_scan_period = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_idle_scan_period'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_idle_max_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.ndpi_idle_max_time= value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_idle_max_time'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_idle_scan_budget(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.ndpi_idle_scan_budget = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_idle_scan_budget'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_giveup_proto_tcp(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_INFO, "INFO: [%s] 'classifier_giveup_proto_tcp' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.ndpi_giveup_proto_tcp = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_giveup_proto_tcp'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_giveup_proto_udp(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_INFO, "INFO: [%s] 'classifier_giveup_proto_udp' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.ndpi_giveup_proto_udp = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_giveup_proto_udp'. Globalized.\n", filename); return changes; } int cfg_key_classifier_ndpi_giveup_proto_other(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_INFO, "INFO: [%s] 'classifier_giveup_proto_other' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.ndpi_giveup_proto_other = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'classifier_giveup_proto_other'. Globalized.\n", filename); return changes; } int cfg_key_nfprobe_timeouts(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_timeouts = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_timeouts = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfprobe_hoplimit(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 1) || (value > 255)) { Log(LOG_ERR, "WARN: [%s] 'nfprobe_hoplimit' has to be in the range 1-255.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_hoplimit = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_hoplimit = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_maxflows(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'nfprobe_maxflows' has to be >= 1.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_maxflows = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_maxflows = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_receiver(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_receiver = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_receiver = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfprobe_dtls(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_dtls = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_dtls = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_dtls_verify_cert(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_dtls_verify_cert = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_dtls_verify_cert = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfprobe_source_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_source_ip = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_source_ip = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfprobe_version(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value != 5 && value != 9 && value != 10) { Log(LOG_ERR, "WARN: [%s] 'nfprobe_version' has to be one of 5, 9 or 10.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_version = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_version = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_engine(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_engine = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_engine = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfprobe_peer_as(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_peer_as = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_peer_as = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_ip_precedence(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 0) || (value > 7)) { Log(LOG_ERR, "WARN: [%s] 'nfprobe_ipprec' and 'sfprobe_ipprec' have to be in the range 0-7.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_ipprec = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_ipprec = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_direction(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "tag")) value = DIRECTION_TAG; else if (!strcmp(value_ptr, "tag2")) value = DIRECTION_TAG2; else if (!strcmp(value_ptr, "in")) value = DIRECTION_IN; else if (!strcmp(value_ptr, "out")) value = DIRECTION_OUT; else { Log(LOG_ERR, "WARN: [%s] Invalid nfprobe_direction or sfprobe_direction value '%s'\n", filename, value_ptr); return ERR; } if (!name) { Log(LOG_ERR, "ERROR: [%s] nfprobe_direction and sfprobe_direction cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_direction = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_ifindex(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value2 = 0; u_int32_t value = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "tag")) value2 = IFINDEX_TAG; else if (!strcmp(value_ptr, "tag2")) value2 = IFINDEX_TAG2; else if ((value = strtol(value_ptr, NULL, 0))) value2 = IFINDEX_STATIC; else { Log(LOG_ERR, "WARN: [%s] Invalid nfprobe_ifindex or sfprobe_ifindex value '%s'\n", filename, value_ptr); return ERR; } if (!name) { Log(LOG_ERR, "ERROR: [%s] nfprobe_ifindex and sfprobe_ifindex cannot be global. Not loaded.\n", filename); changes++; } else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_ifindex = value; list->cfg.nfprobe_ifindex_type = value2; changes++; break; } } } return changes; } int cfg_key_nfprobe_ifindex_override(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_ifindex_override = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_ifindex_override = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_tstamp_usec(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_tstamp_usec = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_tstamp_usec = value; changes++; break; } } } return changes; } int cfg_key_nfprobe_dont_cache(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.nfprobe_dont_cache = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.nfprobe_dont_cache = value; changes++; break; } } } return changes; } int cfg_key_sfprobe_receiver(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sfprobe_receiver = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sfprobe_receiver = value_ptr; changes++; break; } } } return changes; } int cfg_key_sfprobe_agentip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.sfprobe_agentip = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sfprobe_agentip = value_ptr; changes++; break; } } } return changes; } int cfg_key_sfprobe_agentsubid(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_ERR, "WARN: [%s] 'sfprobe_agentsubid' has to be >= 0.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.sfprobe_agentsubid = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sfprobe_agentsubid = value; changes++; break; } } } return changes; } int cfg_key_sfprobe_ifspeed(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; u_int64_t value; value = strtoll(value_ptr, NULL, 0); if (!name) for (; list; list = list->next, changes++) list->cfg.sfprobe_ifspeed = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.sfprobe_ifspeed = value; changes++; break; } } } return changes; } int cfg_key_tee_transparent(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.tee_transparent = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_transparent = value; changes++; break; } } } return changes; } int cfg_key_tee_max_receivers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_WARNING, "WARN: [%s] invalid 'tee_max_receivers' value). Allowed values are >= 1.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.tee_max_receivers = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_max_receivers = value; changes++; break; } } } return changes; } int cfg_key_tee_max_receiver_pools(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_WARNING, "WARN: [%s] invalid 'tee_max_receiver_pools' value). Allowed values are >= 1.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.tee_max_receiver_pools = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_max_receiver_pools = value; changes++; break; } } } return changes; } int cfg_key_tee_receivers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.tee_receivers = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_receivers = value_ptr; changes++; break; } } } return changes; } int cfg_key_tee_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] 'tee_pipe_size' has to be > 0 and <= INT_MAX.\n", filename); return ERR; } if (!name) for (; list; list = list->next, changes++) list->cfg.tee_pipe_size = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_pipe_size = value; changes++; break; } } } return changes; } int cfg_key_tee_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.tee_kafka_config_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tee_kafka_config_file = value_ptr; changes++; break; } } } return changes; } void parse_time(char *filename, char *value, int *mu, int *howmany) { int k, j, len; *mu = 0; *howmany = 0; len = strlen(value); for (j = 0; j < len; j++) { if (!isdigit(value[j])) { if (value[j] == 's') *mu = COUNT_SECONDLY; else if (value[j] == 'm') *mu = COUNT_MINUTELY; else if (value[j] == 'h') *mu = COUNT_HOURLY; else if (value[j] == 'd') *mu = COUNT_DAILY; else if (value[j] == 'w') *mu = COUNT_WEEKLY; else if (value[j] == 'M') *mu = COUNT_MONTHLY; else { Log(LOG_WARNING, "WARN: [%s] Ignoring unknown time measuring unit: '%c'.\n", filename, value[j]); *mu = 0; *howmany = 0; return; } if (*mu) { value[j] = '\0'; break; } } } /* if no measurement unit given, assume it's seconds */ if (!(*mu)) *mu = COUNT_SECONDLY; k = atoi(value); if (k > 0) { if (*mu == COUNT_SECONDLY) { if (k % 60) { Log(LOG_WARNING, "WARN: [%s] Ignoring invalid time value: %d (residual secs afters conversion in mins)\n", filename, k); goto exit_lane; } else { k = k / 60; *mu = COUNT_MINUTELY; } } *howmany = k; } else { Log(LOG_WARNING, "WARN: [%s] Ignoring invalid time value: %d (not greater than zero)\n", filename, k); goto exit_lane; } return; exit_lane: *mu = 0; *howmany = 0; } int cfg_key_uacctd_group(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 0 || value > 65535) return ERR; for (; list; list = list->next, changes++) list->cfg.uacctd_group = value; return changes; } int cfg_key_uacctd_nl_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.uacctd_nl_size = value; return changes; } int cfg_key_uacctd_threshold(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.uacctd_threshold = value; return changes; } int cfg_key_tunnel_0(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; trim_all_spaces(value_ptr); for (; list; list = list->next, changes++) list->cfg.tunnel0 = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tunnel_0'. Globalized.\n", filename); return changes; } #if defined WITH_GEOIP int cfg_key_geoip_ipv4_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.geoip_ipv4_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'geoip_ipv4_file'. Globalized.\n", filename); return changes; } int cfg_key_geoip_ipv6_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.geoip_ipv6_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'geoip_ipv6_file'. Globalized.\n", filename); return changes; } #endif #if defined WITH_GEOIPV2 int cfg_key_geoipv2_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.geoipv2_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'geoipv2_file'. Globalized.\n", filename); return changes; } #endif void cfg_get_primitive_index_value(u_int64_t input, u_int64_t *index, u_int64_t *value) { if (index && value) { (*index) = (input >> COUNT_REGISTRY_BITS) & COUNT_INDEX_MASK; (*value) = (input & COUNT_REGISTRY_MASK); } } void cfg_set_primitive_index_value(u_int64_t index, u_int64_t value, u_int64_t *output) { if (output) { (*output) = ((index << COUNT_REGISTRY_BITS) | (value & COUNT_REGISTRY_MASK)); } } void cfg_set_aggregate(char *filename, u_int64_t registry[], u_int64_t input, char *token) { u_int64_t index, value; cfg_get_primitive_index_value(input, &index, &value); if (registry[index] & value) { Log(LOG_ERR, "ERROR: [%s] '%s' repeated in 'aggregate' or invalid 0x%llx bit code.\n", filename, token, (unsigned long long)input); exit(1); } else registry[index] |= value; } int cfg_key_bgp_daemon_msglog_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_avro_schema_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_avro_schema_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_avro_schema_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] bgp_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] bgp_daemon_msglog_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] bgp_daemon_msglog_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid bgp_daemon_msglog_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_output'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_daemon_msglog_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_daemon_msglog_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_amqp_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_msglog_amqp_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_amqp_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_amqp_retry'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_latest_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_latest_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_latest_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_avro_schema_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_avro_schema_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_avro_schema_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] bgp_table_dump_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else if (!strcmp(value_ptr, "avro") || !strcmp(value_ptr, "avro_bin")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_BIN; #else value = PRINT_OUTPUT_AVRO_BIN; Log(LOG_WARNING, "WARN: [%s] bgp_table_dump_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else if (!strcmp(value_ptr, "avro_json")) { #ifdef WITH_AVRO value = PRINT_OUTPUT_AVRO_JSON; #else value = PRINT_OUTPUT_AVRO_JSON; Log(LOG_WARNING, "WARN: [%s] bgp_table_dump_output set to avro but will produce no output (missing --enable-avro).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid bgp_table_dump_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_output'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_refresh_time' is expected in secs but contains non-digit chars: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < MIN_REFRESH_TIME || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_refresh_time' value has to be >= %d and <= %d secs.\n", filename, MIN_REFRESH_TIME, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_refresh_time = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_refresh_time'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_time_slots(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_time_slots' is expected to be an integer value: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < 1 || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_time_slots' value has to be >= 1 and <= %d.\n", filename, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_time_slots = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_time_slots'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_table_dump_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_table_dump_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_daemon_msglog_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_msglog_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.bgp_daemon_msglog_kafka_partition_key = value_ptr; list->cfg.bgp_daemon_msglog_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_msglog_kafka_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_retry'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_msglog_kafka_avro_schema_registry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_daemon_msglog_kafka_avro_schema_registry = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_daemon_msglog_kafka_avro_schema_registry'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bgp_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bgp_table_dump_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'bgp_table_dump_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.bgp_table_dump_kafka_partition_key = value_ptr; list->cfg.bgp_table_dump_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_bgp_daemon_table_dump_kafka_avro_schema_registry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bgp_table_dump_kafka_avro_schema_registry = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bgp_table_dump_kafka_avro_schema_registry'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_daemon_msglog_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_msglog_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.bmp_daemon_msglog_kafka_partition_key = value_ptr; list->cfg.bmp_daemon_msglog_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_msglog_kafka_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_retry'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_msglog_kafka_avro_schema_registry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_msglog_kafka_avro_schema_registry = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_msglog_kafka_avro_schema_registry'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'bmp_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'bmp_dump_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'bmp_dump_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.bmp_dump_kafka_partition_key = value_ptr; list->cfg.bmp_dump_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_bmp_daemon_dump_kafka_avro_schema_registry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.bmp_dump_kafka_avro_schema_registry = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_dump_kafka_avro_schema_registry'. Globalized.\n", filename); return changes; } int cfg_key_tmp_asa_bi_flow(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; if (!name) for (; list; list = list->next, changes++) list->cfg.tmp_asa_bi_flow = value; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.tmp_asa_bi_flow = value; changes++; break; } } } return changes; } int cfg_key_tmp_bgp_lookup_compare_ports(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.tmp_bgp_lookup_compare_ports = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tmp_bgp_lookup_compare_ports'. Globalized.\n", filename); return changes; } int cfg_key_tmp_bgp_daemon_route_refresh(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.tmp_bgp_daemon_route_refresh = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tmp_bgp_daemon_route_refresh'. Globalized.\n", filename); return changes; } int cfg_key_tmp_bgp_daemon_origin_type_int(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.tmp_bgp_daemon_origin_type_int = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tmp_bgp_daemon_origin_type_int'. Globalized.\n", filename); return changes; } int cfg_key_tmp_telemetry_daemon_udp_notif_legacy(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.tmp_telemetry_udp_notif_legacy = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tmp_telemetry_udp_notif_legacy'. Globalized.\n", filename); return changes; } int cfg_key_tmp_telemetry_decode_cisco_v1_json_string(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.tmp_telemetry_decode_cisco_v1_json_string = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'tmp_telemetry_decode_cisco_v1_json_string'. Globalized.\n", filename); return changes; } int cfg_key_thread_stack(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'thread_stack' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.thread_stack = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'thread_stack'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_daemon(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.telemetry_daemon = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_port_tcp(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_port_tcp' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_port_tcp = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_port_tcp'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_port_udp(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_port_udp' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_port_udp = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_port_udp'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_ip'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_interface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_interface'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_udp_notif_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_port'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_ip(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_ip = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_ip'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_interface(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_interface = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_interface'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_ipv6_only(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_ipv6_only = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_ipv6_only'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_nmsgs(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_nmsgs = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_nmsgs'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_udp_notif_rp_ebpf_prog(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_udp_notif_rp_ebpf_prog = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_udp_notif_rp_ebpf_prog'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_ipv6_only(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.telemetry_ipv6_only = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_ipv6_only'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_zmq_address(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_zmq_address = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_zmq_address'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_decoder(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_decoder = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_decoder'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_allow_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_allow_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_allow_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_daemon_pipe_size' has to be > 0 and <= INT_MAX.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_pipe_size = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_pipe_size'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_ip_precedence(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 0) || (value > 7)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_ipprec' has to be in the range 0-7.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_ipprec = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_ipprec'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_max_peers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_max_peers' has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_max_peers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_max_peers'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_peer_timeout(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 60) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_peer_timeout' has to be >= 60.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_peer_timeout = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_peer_timeout'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_tag_map(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_tag_map = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_tag_map'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] telemetry_daemon_msglog_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid telemetry_daemon_msglog_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_output'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_daemon_msglog_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_daemon_msglog_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_amqp_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_msglog_amqp_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_amqp_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_amqp_retry'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_latest_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_latest_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_latest_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_output(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; lower_string(value_ptr); if (!strcmp(value_ptr, "json")) { #ifdef WITH_JANSSON value = PRINT_OUTPUT_JSON; #else value = PRINT_OUTPUT_JSON; Log(LOG_WARNING, "WARN: [%s] telemetry_dump_output set to json but will produce no output (missing --enable-jansson).\n", filename); #endif } else { Log(LOG_WARNING, "WARN: [%s] Invalid telemetry_dump_output value '%s'\n", filename, value_ptr); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_output = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_output'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_refresh_time(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_refresh_time' is expected in secs but contains non-digit chars: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < MIN_REFRESH_TIME || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_refresh_time' value has to be >= %d and <= %d secs.\n", filename, MIN_REFRESH_TIME, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_refresh_time = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_refresh_time'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_time_slots(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0, i, len = strlen(value_ptr); for (i = 0; i < len; i++) { if (!isdigit(value_ptr[i]) && !isspace(value_ptr[i])) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_time_slots' is expected to be an integer value: '%c'\n", filename, value_ptr[i]); return ERR; } } value = atoi(value_ptr); if (value < 1 || value > MAX_REFRESH_TIME) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_time_slots' value has to be >= 1 and <= %d.\n", filename, MAX_REFRESH_TIME); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_time_slots = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_time_slots'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_host'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_vhost(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_vhost = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_vhost'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_user(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_user = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_user'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_passwd(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_passwd = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_passwd'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_exchange(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_exchange = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_exchange'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_exchange_type(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_exchange_type = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_exchange_type'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_routing_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_routing_key = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_routing_key'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_routing_key_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_dump_amqp_routing_key_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_routing_key_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_routing_key_rr'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_persistent_msg(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_persistent_msg = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_persistent_msg'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_frame_max(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); if (value <= 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_dump_amqp_frame_max' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_frame_max = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_frame_max'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_amqp_heartbeat_interval(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int32_t value, changes = 0; char *endptr; value = strtoul(value_ptr, &endptr, 10); for (; list; list = list->next, changes++) list->cfg.telemetry_dump_amqp_heartbeat_interval = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_amqp_heartbeat_interval'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_workers(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < 1) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_workers' value has to be >= 1.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_workers = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_workers'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_daemon_msglog_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_msglog_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.telemetry_msglog_kafka_partition_key = value_ptr; list->cfg.telemetry_msglog_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_retry(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value <= 0) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_msglog_kafka_retry' has to be > 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_retry = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_retry'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_msglog_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_msglog_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_daemon_msglog_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_broker_host(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_broker_host = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_broker_host'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_broker_port(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value <= 0) || (value > 65535)) { Log(LOG_ERR, "WARN: [%s] 'telemetry_daemon_msglog_kafka_broker_port' has to be in the range 1-65535.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_broker_port = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_broker_port'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_topic(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_topic = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_topic'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_topic_rr(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0, value = 0; value = atoi(value_ptr); if (value < 0) { Log(LOG_WARNING, "WARN: [%s] 'telemetry_dump_kafka_topic_rr' has to be >= 0.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_topic_rr = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_topic_rr'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_partition(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if (value < -1) { Log(LOG_ERR, "WARN: [%s] 'telemetry_dump_kafka_partition' has to be >= -1.\n", filename); return ERR; } if (!value) value = FALSE_NONZERO; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_partition = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_partition'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_partition_key(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value_len, changes = 0; value_len = strlen(value_ptr); for (; list; list = list->next, changes++) { list->cfg.telemetry_dump_kafka_partition_key = value_ptr; list->cfg.telemetry_dump_kafka_partition_keylen = value_len; } if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_partition_key'. Globalized.\n", filename); return changes; } int cfg_key_telemetry_dump_kafka_config_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.telemetry_dump_kafka_config_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'telemetry_dump_kafka_config_file'. Globalized.\n", filename); return changes; } int cfg_key_rpki_roas_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.rpki_roas_file = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'rpki_roas_file'. Globalized.\n", filename); return changes; } int cfg_key_rpki_rtr_cache(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; for (; list; list = list->next, changes++) list->cfg.rpki_rtr_cache = value_ptr; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'rpki_rtr_cache'. Globalized.\n", filename); return changes; } int cfg_key_rpki_rtr_cache_version(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); for (; list; list = list->next, changes++) list->cfg.rpki_rtr_cache_version = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'rpki_rtr_cache_version'. Globalized.\n", filename); return changes; } int cfg_key_rpki_rtr_cache_pipe_size(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; u_int64_t value, changes = 0; char *endptr; value = strtoull(value_ptr, &endptr, 10); if (!value || value > INT_MAX) { Log(LOG_WARNING, "WARN: [%s] 'rpki_rtr_cache_pipe_size' has to be > 0 and <= INT_MAX.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.rpki_rtr_cache_pipe_size = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'rpki_rtr_cache_pipe_size'. Globalized.\n", filename); return changes; } int cfg_key_rpki_rtr_cache_ip_precedence(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = atoi(value_ptr); if ((value < 0) || (value > 7)) { Log(LOG_ERR, "WARN: [%s] 'rpki_rtr_cache_ipprec' has to be in the range 0-7.\n", filename); return ERR; } for (; list; list = list->next, changes++) list->cfg.rpki_rtr_cache_ipprec = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'rpki_rtr_cache_ipprec'. Globalized.\n", filename); return changes; } int cfg_key_print_output_custom_lib(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.print_output_custom_lib = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output_custom_lib = value_ptr; changes++; break; } } } return changes; } int cfg_key_print_output_custom_cfg_file(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int changes = 0; if (!name) for (; list; list = list->next, changes++) list->cfg.print_output_custom_cfg_file = value_ptr; else { for (; list; list = list->next) { if (!strcmp(name, list->name)) { list->cfg.print_output_custom_cfg_file = value_ptr; changes++; break; } } } return changes; } int cfg_key_nfacctd_bmp_daemon_parse_proxy_header(char *filename, char *name, char *value_ptr) { struct plugins_list_entry *list = plugins_list; int value, changes = 0; value = parse_truefalse(value_ptr); if (value < 0) return ERR; for (; list; list = list->next, changes++) list->cfg.bmp_daemon_parse_proxy_header = value; if (name) Log(LOG_WARNING, "WARN: [%s] plugin name not supported for key 'bmp_daemon_parse_proxy_header'. Globalized.\n", filename); return changes; } pmacct-1.7.8/src/Makefile.am0000644000175000017500000001324014354105275014635 0ustar paolopaoloSUBDIRS = if WITH_EXTERNAL_DEPS SUBDIRS += external_libs endif SUBDIRS += nfprobe_plugin sfprobe_plugin bgp tee_plugin isis bmp telemetry rpki filters ebpf sbin_PROGRAMS = bin_PROGRAMS = EXTRA_PROGRAMS = AM_LDFLAGS = @GEOIP_LIBS@ @GEOIPV2_LIBS@ if WITH_JANSSON AM_LDFLAGS += @JANSSON_LIBS@ endif if WITH_AVRO AM_LDFLAGS += @AVRO_LIBS@ endif AM_CFLAGS = $(PMACCT_CFLAGS) #Build string autogen BUILT_SOURCES = pmacct-build.h_h .PHONY = pmacct-build.h pmacct-build.h_h: @if [ ! -f ".pmacct-build.h" ] || [ "`cat .pmacct-build.h`" != "`git rev-parse HEAD 2> /dev/null`" ]; then \ echo "#ifndef PMACCT_BUILD_STR" > pmacct-build.h; \ echo "#define PMACCT_BUILD_STR" >> pmacct-build.h; \ if [ "x`git rev-parse --is-inside-work-tree 2> /dev/null`" == "xtrue" ]; then \ echo "`git rev-parse HEAD`" > .pmacct-build.h; \ BUILD_DATE="`git log -1 --date=short --pretty=format:%ad | tr -d "-"`"; \ BUILD_AUX="`git log -1 --date=short --pretty=format:%ad`";\ BUILD_COMMITS="`git log --date=short --pretty=format:%ad | sort | uniq -c | grep $$BUILD_AUX | awk '{print $$1}'`"; \ BUILD_COMMITS="$$(($$BUILD_COMMITS - 1))"; \ BUILD_HASH_SHORT="`git rev-parse --short HEAD`"; \ echo "#define PMACCT_BUILD \"$$BUILD_DATE-$$BUILD_COMMITS ($$BUILD_HASH_SHORT)\"" >> pmacct-build.h; \ else \ echo "#define PMACCT_BUILD \"RELEASE\"" >> pmacct-build.h; \ fi;\ echo "#endif" >> pmacct-build.h; \ fi noinst_LTLIBRARIES = libdaemons.la libcommon.la libcommon_la_SOURCES = strlcpy.c addr.c libdaemons_la_SOURCES = signals.c util.c plugin_hooks.c \ server.c acct.c memory.c cfg.c \ imt_plugin.c log.c pkt_handlers.c \ cfg_handlers.c net_aggr.c \ print_plugin.c pretag.c ip_frag.c \ pretag_handlers.c ip_flow.c setproctitle.c \ classifier.c conntrack.c xflow_status.c \ plugin_common.c preprocess.c \ ll.c nl.c \ base64.c pmsearch.c linklist.c \ thread_pool.c \ plugin_cmn_custom.c network.c pmacct-globals.c libcommon_la_LIBADD = libcommon_la_CFLAGS = $(AM_CFLAGS) # Builtin plugins libdaemons_la_LIBADD = nfprobe_plugin/libnfprobe_plugin.la libdaemons_la_LIBADD += sfprobe_plugin/libsfprobe_plugin.la libdaemons_la_LIBADD += bmp/libpmbmp.la libdaemons_la_LIBADD += bgp/libpmbgp.la libdaemons_la_LIBADD += rpki/libpmrpki.la libdaemons_la_LIBADD += filters/libpmfilters.la libdaemons_la_LIBADD += tee_plugin/libtee_plugin.la libdaemons_la_LIBADD += isis/libpmisis.la libdaemons_la_LIBADD += telemetry/libpmtelemetry.la libdaemons_la_LIBADD += ebpf/libpmebpf.la libdaemons_la_LIBADD += libcommon.la libdaemons_la_CFLAGS = $(AM_CFLAGS) if WITH_MYSQL libdaemons_la_SOURCES += mysql_plugin.c libdaemons_la_LIBADD += @MYSQL_LIBS@ libdaemons_la_CFLAGS += @MYSQL_CFLAGS@ endif if WITH_PGSQL libdaemons_la_SOURCES += pgsql_plugin.c libdaemons_la_LIBADD += @PGSQL_LIBS@ libdaemons_la_CFLAGS += @PGSQL_CFLAGS@ endif if WITH_MONGODB libdaemons_la_SOURCES += mongodb_plugin.c libdaemons_la_LIBADD += @MONGODB_LIBS@ libdaemons_la_CFLAGS += @MONGODB_CFLAGS@ endif if WITH_SQLITE3 libdaemons_la_SOURCES += sqlite3_plugin.c libdaemons_la_LIBADD += @SQLITE3_LIBS@ libdaemons_la_CFLAGS += @SQLITE3_CFLAGS@ endif if WITH_JANSSON libdaemons_la_SOURCES += plugin_cmn_json.c libdaemons_la_LIBADD += @JANSSON_LIBS@ libdaemons_la_CFLAGS += @JANSSON_CFLAGS@ endif if WITH_AVRO libdaemons_la_SOURCES += plugin_cmn_avro.c libdaemons_la_LIBADD += @AVRO_LIBS@ libdaemons_la_CFLAGS += @AVRO_CFLAGS@ if WITH_SERDES libdaemons_la_LIBADD += @SERDES_LIBS@ libdaemons_la_CFLAGS += @SERDES_CFLAGS@ endif endif if WITH_NDPI SUBDIRS += ndpi libdaemons_la_LIBADD += ndpi/libndpi_support.la libdaemons_la_LIBADD += @NDPI_LIBS@ libdaemons_la_CFLAGS += @NDPI_CFLAGS@ endif if WITH_RABBITMQ libdaemons_la_SOURCES += amqp_common.c amqp_plugin.c libdaemons_la_LIBADD += @RABBITMQ_LIBS@ libdaemons_la_CFLAGS += @RABBITMQ_CFLAGS@ endif if WITH_ZMQ libdaemons_la_SOURCES += zmq_common.c libdaemons_la_LIBADD += @ZMQ_LIBS@ libdaemons_la_CFLAGS += @ZMQ_CFLAGS@ endif if WITH_KAFKA libdaemons_la_SOURCES += kafka_common.c kafka_plugin.c libdaemons_la_LIBADD += @KAFKA_LIBS@ libdaemons_la_CFLAGS += @KAFKA_CFLAGS@ endif if USING_SQL libdaemons_la_SOURCES += sql_common.c sql_handlers.c sql_common_m.c libdaemons_la_CFLAGS += -Wno-error=pointer-sign libdaemons_la_LIBADD += -lm -lz endif if WITH_REDIS libdaemons_la_SOURCES += redis_common.c libdaemons_la_LIBADD += @REDIS_LIBS@ libdaemons_la_CFLAGS += @REDIS_CFLAGS@ endif if WITH_GNUTLS libdaemons_la_LIBADD += @GNUTLS_LIBS@ libdaemons_la_CFLAGS += @GNUTLS_CFLAGS@ endif if WITH_UNYTE_UDP_NOTIF libdaemons_la_LIBADD += @UNYTE_UDP_NOTIF_LIBS@ libdaemons_la_CFLAGS += @UNYTE_UDP_NOTIF_CFLAGS@ endif if WITH_EBPF libdaemons_la_LIBADD += @EBPF_LIBS@ libdaemons_la_CFLAGS += @EBPF_CFLAGS@ endif if USING_TRAFFIC_BINS sbin_PROGRAMS += pmacctd nfacctd sfacctd bin_PROGRAMS += pmacct pmacctd_SOURCES = pmacctd.c pmacctd_LDADD = libdaemons.la nfacctd_SOURCES = nfacctd.c nfv9_template.c nfacctd_LDADD = libdaemons.la sfacctd_SOURCES = sfacctd.c sflow.c sfv5_module.c sfacctd_LDADD = libdaemons.la if WITH_NFLOG sbin_PROGRAMS += uacctd uacctd_SOURCES = uacctd.c uacctd_CFLAGS = $(AM_CFLAGS) @NFLOG_CFLAGS@ -Wno-error=pointer-sign uacctd_LDADD = libdaemons.la @NFLOG_LIBS@ endif pmacct_SOURCES = pmacct.c pmacct_LDADD = libcommon.la libdaemons.la endif if USING_ST_BINS sbin_PROGRAMS += pmtelemetryd pmtelemetryd_SOURCES = pmtelemetryd.c pmtelemetryd_LDFLAGS = $(DEFS) pmtelemetryd_LDADD = libdaemons.la endif if USING_BGP_BINS sbin_PROGRAMS += pmbgpd pmbgpd_SOURCES = pmbgpd.c pmbgpd_LDFLAGS = $(DEFS) pmbgpd_LDADD = libdaemons.la endif if USING_BMP_BINS sbin_PROGRAMS += pmbmpd pmbmpd_SOURCES = pmbmpd.c pmbmpd_LDFLAGS = $(DEFS) pmbmpd_LDADD = libdaemons.la endif pmacct-1.7.8/src/util.h0000644000175000017500000002551614354105275013740 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UTIL_H #define UTIL_H /* defines */ #define ADD 0 #define SUB 1 #define DYNNAME_TOKENS_MAX 32 #define DYNNAME_DEFAULT_WRITER_ID "$proc_name/$writer_pid" /* typedefs */ typedef int (*dynname_token_handler) (char *, int, char *, void *); typedef int (*dynname_token_dict_registry_handler) (void *, char *, int); /* structs */ struct p_broker_timers { time_t last_fail; int retry_interval; }; struct dynname_token_dict_registry_line { int id; char *desc; dynname_token_dict_registry_handler func; }; struct dynname_type_dictionary_line { char key[SRVBUFLEN]; dynname_token_handler func; }; struct dynname_tokens { const struct dynname_token_dict_registry_line *type; dynname_token_handler func[DYNNAME_TOKENS_MAX]; void *static_arg[DYNNAME_TOKENS_MAX]; }; /* prototypes */ extern void setnonblocking(int); extern void setblocking(int); extern int daemonize(); extern char *copy_argv(register char **); extern char *extract_token(char **, int); extern char *extract_plugin_name(char **); extern void trim_spaces(char *); extern void trim_all_spaces(char *); extern void strip_quotes(char *); extern void string_add_newline(char *); extern int isblankline(char *); extern int iscomment(char *); extern int check_not_valid_char(char *, char *, int); extern time_t roundoff_time(time_t, char *); extern time_t calc_monthly_timeslot(time_t, int, int); extern void write_pid_file(char *); extern void write_pid_file_plugin(char *, char *, char *); extern void remove_pid_file(char *); extern int sanitize_buf_net(char *, char *, int); extern int sanitize_buf(char *); extern void mark_columns(char *); extern int Setsocksize(int, int, int, void *, socklen_t); extern void *map_shared(void *, size_t, int, int, int, off_t); extern void lower_string(char *); extern void evaluate_sums(u_int64_t *, u_int64_t *, char *, char *); extern void stop_all_childs(); extern int file_lock(int); extern int file_unlock(int); extern void pm_strftime(char *, int, char *, const time_t *, int); extern void pm_strftime_same(char *, int, char *, const time_t *, int); extern void insert_rfc3339_timezone(char *, int, const struct tm *); extern void append_rfc3339_timezone(char *, int, const struct tm *); extern int read_SQLquery_from_file(char *, char *, int); extern void stick_bosbit(u_char *); extern int check_bosbit(u_char *); extern u_int32_t decode_mpls_label(u_char *); extern void encode_mpls_label(char *, u_int32_t); extern int timeval_cmp(struct timeval *, struct timeval *); extern void signal_kittens(int, int); extern void exit_all(int); extern void exit_plugin(int); extern void exit_gracefully(int); extern void reset_tag_label_status(struct packet_ptrs_vector *); extern void reset_net_status(struct packet_ptrs *); extern void reset_net_status_v(struct packet_ptrs_vector *); extern void reset_shadow_status(struct packet_ptrs_vector *); extern void reset_fallback_status(struct packet_ptrs *); extern void set_sampling_table(struct packet_ptrs_vector *, u_char *); extern void set_shadow_status(struct packet_ptrs *); extern void set_default_preferences(struct configuration *); extern FILE *open_output_file(char *, char *, int); extern void open_pcap_savefile(struct pm_pcap_device *, char *); extern void pm_pcap_device_initialize(struct pm_pcap_devices *); extern void link_latest_output_file(char *, char *); extern void close_output_file(FILE *); extern int handle_dynname_internal_strings(char *, int, char *, struct primitives_ptrs *, int); extern int handle_dynname_internal_strings_same(char *, int, char *, struct primitives_ptrs *, int); extern int have_dynname_nontime(char *); extern void escape_ip_uscores(char *); extern int sql_history_to_secs(int, int); extern void *pm_malloc(size_t); extern void load_allow_file(char *, struct hosts_table *); extern int check_allow(struct hosts_table *, struct sockaddr *); extern int BTA_find_id(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); extern void calc_refresh_timeout(time_t, time_t, int *); extern void calc_refresh_timeout_sec(time_t, time_t, int *); extern int load_tags(char *, struct pretag_filter *, char *); extern int load_labels(char *, struct pretag_label_filter *, char *); extern int evaluate_tags(struct pretag_filter *, pm_id_t); extern int evaluate_labels(struct pretag_label_filter *, pt_label_t *); extern char *write_sep(char *, int *); extern void version_daemon(int, char *); extern void set_truefalse_nonzero(int *); extern char *ip_proto_print(u_int8_t, char *, int); extern void parse_hostport(const char *, struct sockaddr *, socklen_t *); extern bool is_prime(u_int32_t); extern u_int32_t next_prime(u_int32_t); extern char *null_terminate(char *, int); extern char *uint_print(void *, int, int); extern void reload_logs(char *); extern int is_empty_256b(void *, int); extern ssize_t pm_recv(int, void *, size_t, int, unsigned int); extern int ft2af(u_int8_t); extern char *compose_json_str(void *); extern void write_and_free_json(FILE *, void *); extern void add_writer_name_and_pid_json(void *, struct dynname_tokens *); extern void write_file_binary(FILE *, void *, size_t); extern void compose_timestamp(char *, int, struct timeval *, int, int, int, int); extern void print_primitives(int, char *); extern int mkdir_multilevel(const char *, int, uid_t, gid_t); extern char bin_to_hex(int); extern int hex_to_bin(int); extern int serialize_hex(const u_char *, u_char *, int); extern int serialize_bin(const u_char *, u_char *, int); extern void set_primptrs_funcs(struct extra_primitives *); extern void primptrs_set_bgp(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_lbgp(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_nat(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_mpls(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_tun(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_custom(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_extras(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern void primptrs_set_vlen_hdr(u_char *, struct extra_primitives *, struct primitives_ptrs *); extern int custom_primitives_vlen(struct custom_primitives_ptrs *); extern void custom_primitives_reconcile(struct custom_primitives_ptrs *, struct custom_primitives *); extern void custom_primitive_header_print(char *, int, struct custom_primitive_ptrs *, int); extern void custom_primitive_value_print(char *, int, u_char *, struct custom_primitive_ptrs *, int); extern void custom_primitives_debug(void *, void *); extern unsigned char *vlen_prims_copy(struct pkt_vlen_hdr_primitives *); extern void vlen_prims_init(struct pkt_vlen_hdr_primitives *, int); extern void vlen_prims_free(struct pkt_vlen_hdr_primitives *); extern int vlen_prims_cmp(struct pkt_vlen_hdr_primitives *, struct pkt_vlen_hdr_primitives *); extern int vlen_prims_get(struct pkt_vlen_hdr_primitives *, pm_cfgreg_t, char **); extern void vlen_prims_debug(struct pkt_vlen_hdr_primitives *); extern void vlen_prims_insert(struct pkt_vlen_hdr_primitives *, pm_cfgreg_t, int, u_char *, int); extern int vlen_prims_delete(struct pkt_vlen_hdr_primitives *, pm_cfgreg_t); extern void hash_init_key(pm_hash_key_t *); extern int hash_init_serial(pm_hash_serial_t *, u_int16_t); extern int hash_alloc_key(pm_hash_key_t *, u_int16_t); extern int hash_dup_key(pm_hash_key_t *, pm_hash_key_t *); extern void hash_destroy_key(pm_hash_key_t *); extern void hash_destroy_serial(pm_hash_serial_t *); extern void hash_serial_set_off(pm_hash_serial_t *, u_int16_t); extern void hash_serial_append(pm_hash_serial_t *, char *, u_int16_t, int); extern pm_hash_key_t *hash_serial_get_key(pm_hash_serial_t *); extern u_int16_t hash_serial_get_off(pm_hash_serial_t *); extern u_int16_t hash_key_get_len(pm_hash_key_t *); extern u_char *hash_key_get_val(pm_hash_key_t *); extern int hash_key_cmp(pm_hash_key_t *, pm_hash_key_t *); extern void dump_writers_init(); extern void dump_writers_count(); extern u_int32_t dump_writers_get_flags(); extern u_int16_t dump_writers_get_active(); extern u_int16_t dump_writers_get_max(); extern int dump_writers_add(pid_t); extern int pm_scandir(const char *, struct dirent ***, int (*select)(const struct dirent *), int (*compar)(const void *, const void *)); extern void pm_scandir_free(struct dirent ***, int); extern int pm_alphasort(const void *, const void *); extern void *pm_tsearch(const void *, void **, int (*compar)(const void *, const void *), size_t); extern void pm_tdestroy(void **, void (*free_node)(void *)); extern int delete_line_from_file(int, char *); extern void generate_random_string(char *, const int); extern void P_broker_timers_set_last_fail(struct p_broker_timers *, time_t); extern void P_broker_timers_set_retry_interval(struct p_broker_timers *, int); extern void P_broker_timers_unset_last_fail(struct p_broker_timers *); extern time_t P_broker_timers_get_last_fail(struct p_broker_timers *); extern int P_broker_timers_get_retry_interval(struct p_broker_timers *); extern time_t P_broker_timers_get_last_fail(struct p_broker_timers *); extern primptrs_func primptrs_funcs[PRIMPTRS_FUNCS_N]; extern void distribute_work(struct pm_dump_runner *, u_int64_t, int, u_int64_t); extern unsigned long pm_djb2_string_hash(unsigned char *str); extern void dynname_tokens_prepare(char *, struct dynname_tokens *, int); extern void dynname_tokens_free(struct dynname_tokens *); extern int dynname_tokens_compose(char *, int, struct dynname_tokens *, void *); extern int dynname_text_token_handler(char *, int, char *, void *); extern int dwi_proc_name_handler(char *, int, char *, void *); extern int dwi_writer_pid_handler(char *, int, char *, void *); extern int dwi_pmacct_build_handler(char *, int, char *, void *); extern int dtdr_writer_id(void *, char *, int); extern int dtdr_unknown(void *, char *, int); extern char *lookup_id_to_string_struct(const struct _id_to_string_struct *, u_int64_t); extern const char *sampling_direction_print(u_int8_t); extern u_int8_t sampling_direction_str2id(char *); #endif //UTIL_H pmacct-1.7.8/src/ip_flow.h0000644000175000017500000001016414354105275014413 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _IP_FLOW_H_ #define _IP_FLOW_H_ /* defines */ #define FLOW_TABLE_HASHSZ 256 #define FLOW_GENERIC_LIFETIME 60 #define FLOW_TCPSYN_LIFETIME 60 #define FLOW_TCPEST_LIFETIME 432000 #define FLOW_TCPFIN_LIFETIME 30 #define FLOW_TCPRST_LIFETIME 10 #define FLOW_TABLE_PRUNE_INTERVAL 3600 #define FLOW_TABLE_EMER_PRUNE_INTERVAL 60 #define DEFAULT_FLOW_BUFFER_SIZE 16384000 /* 16 Mb */ struct context_chain { char *protocol; void *data; struct context_chain *next; }; /* structures */ struct ip_flow_common { /* [0] = forward flow data [1] = reverse flow data */ u_int16_t bucket; struct timeval last[2]; u_int32_t last_tcp_seq; u_int8_t tcp_flags[2]; u_int8_t proto; /* XXX: classifier hooks, move to pm_class2_t */ pm_class_t class[2]; /* conntrack hooks */ void (*conntrack_helper)(time_t, struct packet_ptrs *); }; struct ip_flow { struct ip_flow_common cmn; u_int32_t ip_src; u_int32_t ip_dst; u_int16_t port_src; u_int16_t port_dst; char *bgp_src; /* pointer to bgp_node structure for source prefix, if any */ char *bgp_dst; /* pointer to bgp_node structure for destination prefix, if any */ struct ip_flow *lru_next; struct ip_flow *lru_prev; struct ip_flow *next; struct ip_flow *prev; }; struct flow_lru_l { struct ip_flow *root; struct ip_flow *last; }; struct ip_flow6 { struct ip_flow_common cmn; u_int32_t ip_src[4]; u_int32_t ip_dst[4]; u_int16_t port_src; u_int16_t port_dst; struct ip_flow6 *lru_next; struct ip_flow6 *lru_prev; struct ip_flow6 *next; struct ip_flow6 *prev; }; struct flow_lru_l6 { struct ip_flow6 *root; struct ip_flow6 *last; }; /* prototypes */ extern void init_ip_flow_handler(); /* wrapper */ extern void init_ip4_flow_handler(); extern void ip_flow_handler(struct packet_ptrs *); extern void find_flow(struct timeval *, struct packet_ptrs *); extern void create_flow(struct timeval *, struct ip_flow *, u_int8_t, unsigned int, struct packet_ptrs *, struct pm_iphdr *, struct pm_tlhdr *, unsigned int); extern void prune_old_flows(struct timeval *); extern unsigned int hash_flow(u_int32_t, u_int32_t, u_int16_t, u_int16_t, u_int8_t); extern unsigned int normalize_flow(u_int32_t *, u_int32_t *, u_int16_t *, u_int16_t *); extern unsigned int is_expired(struct timeval *, struct ip_flow_common *); extern unsigned int is_expired_uni(struct timeval *, struct ip_flow_common *, unsigned int); extern void evaluate_tcp_flags(struct timeval *, struct packet_ptrs *, struct ip_flow_common *, unsigned int); extern void clear_tcp_flow_cmn(struct ip_flow_common *, unsigned int); extern void init_ip6_flow_handler(); extern void ip_flow6_handler(struct packet_ptrs *); extern unsigned int hash_flow6(u_int32_t, struct in6_addr *, struct in6_addr *); extern unsigned int normalize_flow6(struct in6_addr *, struct in6_addr *, u_int16_t *, u_int16_t *); extern void find_flow6(struct timeval *, struct packet_ptrs *); extern void create_flow6(struct timeval *, struct ip_flow6 *, u_int8_t, unsigned int, struct packet_ptrs *, struct ip6_hdr *, struct pm_tlhdr *, unsigned int); extern void prune_old_flows6(struct timeval *); /* global vars */ extern struct ip_flow **ip_flow_table; extern struct flow_lru_l flow_lru_list; extern struct ip_flow6 **ip_flow_table6; extern struct flow_lru_l6 flow_lru_list6; #endif /* _IP_FLOW_H_ */ pmacct-1.7.8/src/ip_flow.c0000644000175000017500000005057214354105275014415 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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 no, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* includes */ #include "pmacct.h" #include "pmacct-data.h" #include "plugin_hooks.h" #include "ip_flow.h" #include "jhash.h" /* Global variables */ struct ip_flow **ip_flow_table; struct flow_lru_l flow_lru_list; struct ip_flow6 **ip_flow_table6; struct flow_lru_l6 flow_lru_list6; u_int32_t flt_total_nodes; time_t flt_prune_deadline; time_t flt_emergency_prune; time_t flow_generic_lifetime; time_t flow_tcpest_lifetime; u_int32_t flt_trivial_hash_rnd = 140281; /* ummmh */ u_int32_t flt6_total_nodes; time_t flt6_prune_deadline; time_t flt6_emergency_prune; void init_ip_flow_handler() { init_ip4_flow_handler(); init_ip6_flow_handler(); } void init_ip4_flow_handler() { int size; if (config.flow_bufsz) flt_total_nodes = config.flow_bufsz / sizeof(struct ip_flow); else flt_total_nodes = DEFAULT_FLOW_BUFFER_SIZE / sizeof(struct ip_flow); if (!config.flow_hashsz) config.flow_hashsz = FLOW_TABLE_HASHSZ; size = sizeof(struct ip_flow) * config.flow_hashsz; ip_flow_table = (struct ip_flow **) malloc(size); assert(ip_flow_table); memset(ip_flow_table, 0, size); flow_lru_list.root = (struct ip_flow *) malloc(sizeof(struct ip_flow)); flow_lru_list.last = flow_lru_list.root; memset(flow_lru_list.root, 0, sizeof(struct ip_flow)); flt_prune_deadline = time(NULL)+FLOW_TABLE_PRUNE_INTERVAL; flt_emergency_prune = 0; if (config.flow_lifetime) flow_generic_lifetime = config.flow_lifetime; else flow_generic_lifetime = FLOW_GENERIC_LIFETIME; if (config.flow_tcp_lifetime) flow_tcpest_lifetime = config.flow_tcp_lifetime; else { flow_tcpest_lifetime = flow_generic_lifetime; } } void ip_flow_handler(struct packet_ptrs *pptrs) { struct timeval now; gettimeofday(&now, NULL); if (now.tv_sec > flt_prune_deadline) { prune_old_flows(&now); flt_prune_deadline = now.tv_sec+FLOW_TABLE_PRUNE_INTERVAL; } find_flow(&now, pptrs); } void evaluate_tcp_flags(struct timeval *now, struct packet_ptrs *pptrs, struct ip_flow_common *fp, unsigned int idx) { unsigned int rev = idx ? 0 : 1; if (fp->proto == IPPROTO_TCP) { /* evaluating the transition to the ESTABLISHED state: we need to be as much precise as possible as the lifetime for an established flow is quite high. We check that we have a) SYN flag on a forward direction, b) SYN+ACK on the reverse one and c) that cur_seqno == syn_seqno+1 holds */ if (fp->tcp_flags[idx] & TH_SYN && fp->tcp_flags[rev] & TH_SYN && fp->tcp_flags[rev] & TH_ACK) { if (ntohl(((struct pm_tcphdr *)pptrs->tlh_ptr)->th_seq) == fp->last_tcp_seq+1) { /* The flow successfully entered the ESTABLISHED state: clearing flags */ fp->tcp_flags[idx] = FALSE; fp->tcp_flags[rev] = FALSE; } } if (pptrs->tcp_flags) { if (pptrs->tcp_flags & TH_SYN) { fp->tcp_flags[idx] = TH_SYN; if (pptrs->tcp_flags & TH_ACK) fp->tcp_flags[idx] |= TH_ACK; else fp->last_tcp_seq = ntohl(((struct pm_tcphdr *)pptrs->tlh_ptr)->th_seq); } if (pptrs->tcp_flags & TH_FIN || pptrs->tcp_flags & TH_RST) { fp->tcp_flags[idx] = pptrs->tcp_flags; fp->tcp_flags[rev] = pptrs->tcp_flags; } } } } void clear_tcp_flow_cmn(struct ip_flow_common *fp, unsigned int idx) { fp->last[idx].tv_sec = 0; fp->last[idx].tv_usec = 0; fp->tcp_flags[idx] = 0; fp->class[idx] = 0; } void find_flow(struct timeval *now, struct packet_ptrs *pptrs) { struct pm_iphdr my_iph; struct pm_tcphdr my_tlh; struct pm_iphdr *iphp = &my_iph; struct pm_tlhdr *tlhp = (struct pm_tlhdr *) &my_tlh; struct ip_flow *fp, *candidate = NULL, *last_seen = NULL; unsigned int idx, bucket; memcpy(&my_iph, pptrs->iph_ptr, IP4HdrSz); memcpy(&my_tlh, pptrs->tlh_ptr, MyTCPHdrSz); idx = normalize_flow(&iphp->ip_src.s_addr, &iphp->ip_dst.s_addr, &tlhp->src_port, &tlhp->dst_port); bucket = hash_flow(iphp->ip_src.s_addr, iphp->ip_dst.s_addr, tlhp->src_port, tlhp->dst_port, iphp->ip_p); for (fp = ip_flow_table[bucket]; fp; fp = fp->next) { if (fp->ip_src == iphp->ip_src.s_addr && fp->ip_dst == iphp->ip_dst.s_addr && fp->port_src == tlhp->src_port && fp->port_dst == tlhp->dst_port && fp->cmn.proto == iphp->ip_p) { /* flow found; will check for its lifetime */ if (!is_expired_uni(now, &fp->cmn, idx)) { /* still valid flow */ evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = FALSE; return; } else { /* stale flow: will start a new one */ clear_tcp_flow_cmn(&fp->cmn, idx); evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = TRUE; return; } } if (!candidate && is_expired(now, &fp->cmn)) candidate = fp; last_seen = fp; } if (candidate) create_flow(now, candidate, TRUE, bucket, pptrs, iphp, tlhp, idx); else create_flow(now, last_seen, FALSE, bucket, pptrs, iphp, tlhp, idx); } void create_flow(struct timeval *now, struct ip_flow *fp, u_int8_t is_candidate, unsigned int bucket, struct packet_ptrs *pptrs, struct pm_iphdr *iphp, struct pm_tlhdr *tlhp, unsigned int idx) { struct ip_flow *newf; if (!flt_total_nodes) { if (now->tv_sec > flt_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/4 buffer full. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt_emergency_prune = now->tv_sec; prune_old_flows(now); } pptrs->new_flow = FALSE; return; } if (fp) { /* a 'not candidate' is simply the tail (last node) of the list. We need to allocate a new node */ if (!is_candidate) { newf = (struct ip_flow *) malloc(sizeof(struct ip_flow)); if (!newf) { if (now->tv_sec > flt_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/4 buffer finished memory. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt_emergency_prune = now->tv_sec; prune_old_flows(now); } pptrs->new_flow = FALSE; return; } else flt_total_nodes--; memset(newf, 0, sizeof(struct ip_flow)); fp->next = newf; newf->prev = fp; flow_lru_list.last->lru_next = newf; /* placing new node as LRU tail */ newf->lru_prev = flow_lru_list.last; flow_lru_list.last = newf; fp = newf; } else { if (fp->lru_next) { /* if fp->lru_next==NULL the node is already the tail */ fp->lru_prev->lru_next = fp->lru_next; fp->lru_next->lru_prev = fp->lru_prev; flow_lru_list.last->lru_next = fp; fp->lru_prev = flow_lru_list.last; fp->lru_next = NULL; flow_lru_list.last = fp; } memset(&fp->cmn, 0, sizeof(struct ip_flow_common)); } } else { /* we don't have any pointer to existing flows; this is because the current bucket doesn't contain any node; we'll allocate the first one */ fp = (struct ip_flow *) malloc(sizeof(struct ip_flow)); if (!fp) { if (now->tv_sec > flt_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/4 buffer finished memory. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt_emergency_prune = now->tv_sec; prune_old_flows(now); } pptrs->new_flow = FALSE; return; } else flt_total_nodes--; memset(fp, 0, sizeof(struct ip_flow)); ip_flow_table[bucket] = fp; flow_lru_list.last->lru_next = fp; /* placing new node as LRU tail */ fp->lru_prev = flow_lru_list.last; flow_lru_list.last = fp; } fp->ip_src = iphp->ip_src.s_addr; fp->ip_dst = iphp->ip_dst.s_addr; fp->port_src = tlhp->src_port; fp->port_dst = tlhp->dst_port; fp->cmn.proto = iphp->ip_p; fp->cmn.bucket = bucket; evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = TRUE; } void prune_old_flows(struct timeval *now) { struct ip_flow *fp, *temp, *last_seen = flow_lru_list.root; fp = flow_lru_list.root->lru_next; while (fp) { if (is_expired(now, &fp->cmn)) { /* we found a stale element; we'll prune it */ if (fp->lru_next) temp = fp->lru_next; else temp = NULL; /* rearranging bucket's pointers */ if (fp->prev && fp->next) { fp->prev->next = fp->next; fp->next->prev = fp->prev; } else if (fp->prev) fp->prev->next = NULL; else if (fp->next) { ip_flow_table[fp->cmn.bucket] = fp->next; fp->next->prev = NULL; } else ip_flow_table[fp->cmn.bucket] = NULL; /* rearranging LRU pointers */ if (fp->lru_next) { fp->lru_next->lru_prev = fp->lru_prev; fp->lru_prev->lru_next = fp->lru_next; } else fp->lru_prev->lru_next = NULL; free(fp); flt_total_nodes++; if (temp) fp = temp; else fp = NULL; } else { last_seen = fp; fp = fp->lru_next; } } flow_lru_list.last = last_seen; } unsigned int normalize_flow(u_int32_t *ip_src, u_int32_t *ip_dst, u_int16_t *port_src, u_int16_t *port_dst) { u_int16_t port_tmp; u_int32_t ip_tmp; if (*port_src < *port_dst) { port_tmp = *port_src; *port_src = *port_dst; *port_dst = port_tmp; ip_tmp = *ip_src; *ip_src = *ip_dst; *ip_dst = ip_tmp; return TRUE; /* reverse flow */ } if (*port_src == *port_dst) { if (*ip_src < *ip_dst) { ip_tmp = *ip_src; *ip_src = *ip_dst; *ip_dst = ip_tmp; return TRUE; /* reverse flow */ } } return FALSE; /* forward flow */ } /* hash_flow() is taken (it has another name there) from Linux kernel 2.4; see full credits contained in jhash.h */ unsigned int hash_flow(u_int32_t ip_src, u_int32_t ip_dst, u_int16_t port_src, u_int16_t port_dst, u_int8_t proto) { return jhash_3words((u_int32_t)(port_src ^ port_dst) << 16 | proto, ip_src, ip_dst, flt_trivial_hash_rnd) & (config.flow_hashsz-1); } /* is_expired() checks for the expiration of the bi-directional flow; returns: TRUE if a) the TCP flow is expired or, b) the non-TCP flow scores 2 points; FALSE in any other case. This function will also contain any further semi-stateful evaluation of specific protocols */ unsigned int is_expired(struct timeval *now, struct ip_flow_common *fp) { int forward = 0, reverse = 0; forward = is_expired_uni(now, fp, 0); reverse = is_expired_uni(now, fp, 1); if (forward && reverse) return TRUE; else return FALSE; } /* is_expired_uni() checks for the expiration of the uni-directional flow; returns: TRUE if the flow has expired; FALSE in any other case. */ unsigned int is_expired_uni(struct timeval *now, struct ip_flow_common *fp, unsigned int idx) { if (fp->proto == IPPROTO_TCP) { /* tcp_flags == 0 ==> the TCP flow is in ESTABLISHED mode */ if (!fp->tcp_flags[idx]) { if (now->tv_sec > fp->last[idx].tv_sec+flow_tcpest_lifetime) return TRUE; } else { if (fp->tcp_flags[idx] & TH_SYN && now->tv_sec > fp->last[idx].tv_sec+FLOW_TCPSYN_LIFETIME) return TRUE; if (fp->tcp_flags[idx] & TH_FIN && now->tv_sec > fp->last[idx].tv_sec+FLOW_TCPFIN_LIFETIME) return TRUE; if (fp->tcp_flags[idx] & TH_RST && now->tv_sec > fp->last[idx].tv_sec+FLOW_TCPRST_LIFETIME) return TRUE; } } else { if (now->tv_sec > fp->last[idx].tv_sec+flow_generic_lifetime) return TRUE; } return FALSE; } void init_ip6_flow_handler() { int size; if (config.flow_bufsz) flt6_total_nodes = config.flow_bufsz / sizeof(struct ip_flow6); else flt6_total_nodes = DEFAULT_FLOW_BUFFER_SIZE / sizeof(struct ip_flow6); if (!config.flow_hashsz) config.flow_hashsz = FLOW_TABLE_HASHSZ; size = sizeof(struct ip_flow6) * config.flow_hashsz; ip_flow_table6 = (struct ip_flow6 **) malloc(size); memset(ip_flow_table6, 0, size); flow_lru_list6.root = (struct ip_flow6 *) malloc(sizeof(struct ip_flow6)); flow_lru_list6.last = flow_lru_list6.root; memset(flow_lru_list6.root, 0, sizeof(struct ip_flow6)); flt6_prune_deadline = time(NULL)+FLOW_TABLE_PRUNE_INTERVAL; flt6_emergency_prune = 0; if (config.flow_lifetime) flow_generic_lifetime = config.flow_lifetime; else flow_generic_lifetime = FLOW_GENERIC_LIFETIME; if (config.flow_tcp_lifetime) flow_tcpest_lifetime = config.flow_tcp_lifetime; else { flow_tcpest_lifetime = flow_generic_lifetime; } } void ip_flow6_handler(struct packet_ptrs *pptrs) { struct timeval now; gettimeofday(&now, NULL); if (now.tv_sec > flt6_prune_deadline) { prune_old_flows6(&now); flt6_prune_deadline = now.tv_sec+FLOW_TABLE_PRUNE_INTERVAL; } find_flow6(&now, pptrs); } unsigned int hash_flow6(u_int32_t id, struct in6_addr *saddr, struct in6_addr *daddr) { u_int32_t a, b, c; u_int32_t *src = (u_int32_t *)saddr, *dst = (u_int32_t *)daddr; a = src[0]; b = src[1]; c = src[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += flt_trivial_hash_rnd; __jhash_mix(a, b, c); a += src[3]; b += dst[0]; c += dst[1]; __jhash_mix(a, b, c); a += dst[2]; b += dst[3]; c += id; __jhash_mix(a, b, c); return c & (config.flow_hashsz - 1); } unsigned int normalize_flow6(struct in6_addr *saddr, struct in6_addr *daddr, u_int16_t *port_src, u_int16_t *port_dst) { struct in6_addr taddr; u_int16_t port_tmp; if (*port_src < *port_dst) { port_tmp = *port_src; *port_src = *port_dst; *port_dst = port_tmp; ip6_addr_cpy(&taddr, saddr); ip6_addr_cpy(saddr, daddr); ip6_addr_cpy(daddr, &taddr); return TRUE; /* reverse flow */ } if (*port_src == *port_dst) { if (ip6_addr_cmp(saddr, daddr) < 0) { ip6_addr_cpy(&taddr, saddr); ip6_addr_cpy(saddr, daddr); ip6_addr_cpy(daddr, &taddr); return TRUE; /* reverse flow */ } } return FALSE; /* forward flow */ } void find_flow6(struct timeval *now, struct packet_ptrs *pptrs) { struct ip6_hdr my_iph; struct pm_tcphdr my_tlh; struct ip6_hdr *iphp = &my_iph; struct pm_tlhdr *tlhp = (struct pm_tlhdr *) &my_tlh; struct ip_flow6 *fp, *candidate = NULL, *last_seen = NULL; unsigned int idx, bucket; memcpy(&my_iph, pptrs->iph_ptr, IP6HdrSz); memcpy(&my_tlh, pptrs->tlh_ptr, MyTCPHdrSz); idx = normalize_flow6(&iphp->ip6_src, &iphp->ip6_dst, &tlhp->src_port, &tlhp->dst_port); bucket = hash_flow6((tlhp->src_port << 16) | tlhp->dst_port, &iphp->ip6_src, &iphp->ip6_dst); for (fp = ip_flow_table6[bucket]; fp; fp = fp->next) { if (!ip6_addr_cmp(&fp->ip_src, &iphp->ip6_src) && !ip6_addr_cmp(&fp->ip_dst, &iphp->ip6_dst) && fp->port_src == tlhp->src_port && fp->port_dst == tlhp->dst_port && fp->cmn.proto == pptrs->l4_proto) { /* flow found; will check for its lifetime */ if (!is_expired_uni(now, &fp->cmn, idx)) { /* still valid flow */ evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = FALSE; return; } else { /* stale flow: will start a new one */ clear_tcp_flow_cmn(&fp->cmn, idx); evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = TRUE; return; } } if (!candidate && is_expired(now, &fp->cmn)) candidate = fp; last_seen = fp; } if (candidate) create_flow6(now, candidate, TRUE, bucket, pptrs, iphp, tlhp, idx); else create_flow6(now, last_seen, FALSE, bucket, pptrs, iphp, tlhp, idx); } void create_flow6(struct timeval *now, struct ip_flow6 *fp, u_int8_t is_candidate, unsigned int bucket, struct packet_ptrs *pptrs, struct ip6_hdr *iphp, struct pm_tlhdr *tlhp, unsigned int idx) { struct ip_flow6 *newf; if (!flt6_total_nodes) { if (now->tv_sec > flt6_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/6 buffer full. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt6_emergency_prune = now->tv_sec; prune_old_flows6(now); } pptrs->new_flow = FALSE; return; } if (fp) { /* a 'not candidate' is simply the tail (last node) of the list. We need to allocate a new node */ if (!is_candidate) { newf = (struct ip_flow6 *) malloc(sizeof(struct ip_flow6)); if (!newf) { if (now->tv_sec > flt6_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/6 buffer full. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt6_emergency_prune = now->tv_sec; prune_old_flows6(now); } pptrs->new_flow = FALSE; return; } else flt6_total_nodes--; memset(newf, 0, sizeof(struct ip_flow6)); fp->next = newf; newf->prev = fp; flow_lru_list6.last->lru_next = newf; /* placing new node as LRU tail */ newf->lru_prev = flow_lru_list6.last; flow_lru_list6.last = newf; fp = newf; } else { if (fp->lru_next) { /* if fp->lru_next==NULL the node is already the tail */ fp->lru_prev->lru_next = fp->lru_next; fp->lru_next->lru_prev = fp->lru_prev; flow_lru_list6.last->lru_next = fp; fp->lru_prev = flow_lru_list6.last; fp->lru_next = NULL; flow_lru_list6.last = fp; } memset(&fp->cmn, 0, sizeof(struct ip_flow_common)); } } else { /* we don't have any fragment pointer; this is because current bucket doesn't contain any node; we'll allocate first one */ fp = (struct ip_flow6 *) malloc(sizeof(struct ip_flow6)); if (!fp) { if (now->tv_sec > flt6_emergency_prune+FLOW_TABLE_EMER_PRUNE_INTERVAL) { Log(LOG_INFO, "INFO ( %s/core ): Flow/6 buffer full. Skipping flows. Increase %s_flow_buffer_size\n", config.name, config.progname); flt6_emergency_prune = now->tv_sec; prune_old_flows6(now); } pptrs->new_flow = FALSE; return; } else flt6_total_nodes--; memset(fp, 0, sizeof(struct ip_flow6)); ip_flow_table6[bucket] = fp; flow_lru_list6.last->lru_next = fp; /* placing new node as LRU tail */ fp->lru_prev = flow_lru_list6.last; flow_lru_list6.last = fp; } ip6_addr_cpy(&fp->ip_src, &iphp->ip6_src); ip6_addr_cpy(&fp->ip_dst, &iphp->ip6_dst); fp->port_src = tlhp->src_port; fp->port_dst = tlhp->dst_port; fp->cmn.proto = pptrs->l4_proto; fp->cmn.bucket = bucket; evaluate_tcp_flags(now, pptrs, &fp->cmn, idx); fp->cmn.last[idx].tv_sec = now->tv_sec; fp->cmn.last[idx].tv_usec = now->tv_usec; pptrs->new_flow = TRUE; } void prune_old_flows6(struct timeval *now) { struct ip_flow6 *fp, *temp, *last_seen = flow_lru_list6.root; fp = flow_lru_list6.root->lru_next; while (fp) { if (is_expired(now, &fp->cmn)) { /* we found a stale element; we'll prune it */ if (fp->lru_next) temp = fp->lru_next; else temp = NULL; /* rearranging bucket's pointers */ if (fp->prev && fp->next) { fp->prev->next = fp->next; fp->next->prev = fp->prev; } else if (fp->prev) fp->prev->next = NULL; else if (fp->next) { ip_flow_table6[fp->cmn.bucket] = fp->next; fp->next->prev = NULL; } else ip_flow_table6[fp->cmn.bucket] = NULL; /* rearranging LRU pointers */ if (fp->lru_next) { fp->lru_next->lru_prev = fp->lru_prev; fp->lru_prev->lru_next = fp->lru_next; } else fp->lru_prev->lru_next = NULL; free(fp); flt6_total_nodes++; if (temp) fp = temp; else fp = NULL; } else { last_seen = fp; fp = fp->lru_next; } } flow_lru_list6.last = last_seen; } pmacct-1.7.8/src/pmbgpd.h0000644000175000017500000000426414354105275014231 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2020 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PMBGPD_H #define PMBGPD_H /* includes */ /* defines */ #define BGP_LG_DEFAULT_TCP_PORT 17900 #define BGP_LG_DEFAULT_THREADS 8 #define BGP_LG_QT_UNKNOWN 0 #define BGP_LG_QT_IP_LOOKUP 1 #define BGP_LG_QT_GET_PEERS 2 /* structures */ /* prototypes */ extern void usage_daemon(char *); extern void compute_once(); /* Looking Glass */ #if defined WITH_ZMQ extern void bgp_lg_wrapper(); extern int bgp_lg_daemon(); #if defined WITH_JANSSON extern void bgp_lg_daemon_worker_json(void *, void *); extern int bgp_lg_daemon_decode_query_header_json(struct p_zmq_sock *, struct bgp_lg_req *); extern int bgp_lg_daemon_decode_query_ip_lookup_json(struct p_zmq_sock *, struct bgp_lg_req_ipl_data *); extern void bgp_lg_daemon_encode_reply_results_json(struct p_zmq_sock *, struct bgp_lg_rep *, int, int); extern void bgp_lg_daemon_encode_reply_ip_lookup_json(struct p_zmq_sock *, struct bgp_lg_rep *, int); extern char *bgp_lg_daemon_encode_reply_ip_lookup_data_json(struct bgp_lg_rep_ipl_data *); extern void bgp_lg_daemon_encode_reply_get_peers_json(struct p_zmq_sock *, struct bgp_lg_rep *, int); extern char *bgp_lg_daemon_encode_reply_get_peers_data_json(struct bgp_lg_rep_gp_data *); extern void bgp_lg_daemon_encode_reply_unknown_json(struct p_zmq_sock *); #endif //WITH_JANSSON #endif //WITH_ZMQ /* global variables */ extern char bgp_lg_default_ip[]; #endif //PMBGPD_H pmacct-1.7.8/src/pretag.h0000644000175000017500000002506214354105275014241 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PRETAG_H #define PRETAG_H /* Pre-Tag map stuff */ #define N_MAP_HANDLERS 8 #define N_MAP_SET_HANDLERS 4 #define MAX_LABEL_LEN 32 #define MAX_BITMAP_ENTRIES 64 /* pt_bitmap_t -> u_int64_t */ #define MAX_PRETAG_MAP_ENTRIES 384 #define PRETAG_LABEL_KV_SEP "%" #define PRETAG_LABEL_KV_SEP_INT '%' #define MAX_ID_TABLE_INDEXES 8 #define ID_TABLE_INDEX_RESULTS (MAX_ID_TABLE_INDEXES * 8) #define PRETAG_IN_IFACE 0x0000000000000001ULL #define PRETAG_OUT_IFACE 0x0000000000000002ULL #define PRETAG_NEXTHOP 0x0000000000000004ULL #define PRETAG_BGP_NEXTHOP 0x0000000000000008ULL #define PRETAG_ENGINE_TYPE 0x0000000000000010ULL #define PRETAG_ENGINE_ID 0x0000000000000020ULL #define PRETAG_FILTER 0x0000000000000040ULL #define PRETAG_NAT_EVENT 0x0000000000000080ULL #define PRETAG_SF_AGENTID 0x0000000000000100ULL #define PRETAG_SAMPLING_RATE 0x0000000000000200ULL #define PRETAG_DIRECTION 0x0000000000000400ULL #define PRETAG_SRC_AS 0x0000000000000800ULL #define PRETAG_DST_AS 0x0000000000001000ULL #define PRETAG_PEER_SRC_AS 0x0000000000002000ULL #define PRETAG_PEER_DST_AS 0x0000000000004000ULL #define PRETAG_SRC_LOCAL_PREF 0x0000000000008000ULL #define PRETAG_LOCAL_PREF 0x0000000000010000ULL #define PRETAG_SRC_STD_COMM 0x0000000000020000ULL #define PRETAG_STD_COMM 0x0000000000040000ULL #define PRETAG_MPLS_VPN_RD 0x0000000000080000ULL #define PRETAG_SAMPLE_TYPE 0x0000000000100000ULL #define PRETAG_SET_TOS 0x0000000000200000ULL #define PRETAG_LOOKUP_BGP_PORT 0x0000000000400000ULL #define PRETAG_SET_TAG 0x0000000000800000ULL #define PRETAG_SET_TAG2 0x0000000001000000ULL #define PRETAG_MPLS_LABEL_BOTTOM 0x0000000002000000ULL #define PRETAG_FLOWSET_ID 0x0000000004000000ULL #define PRETAG_SRC_MAC 0x0000000008000000ULL #define PRETAG_DST_MAC 0x0000000010000000ULL #define PRETAG_VLAN_ID 0x0000000020000000ULL #define PRETAG_IP 0x0000000040000000ULL #define PRETAG_SET_LABEL 0x0000000080000000ULL #define PRETAG_CVLAN_ID 0x0000000100000000ULL #define PRETAG_MPLS_VPN_ID 0x0000000200000000ULL #define PRETAG_FWDSTATUS_ID 0x0000000400000000ULL #define PRETAG_SRC_NET 0x0000000800000000ULL #define PRETAG_DST_NET 0x0000001000000000ULL #define PRETAG_MPLS_PW_ID 0x0000002000000000ULL #define PRETAG_SRC_ROA 0x0000004000000000ULL #define PRETAG_DST_ROA 0x0000008000000000ULL #define PRETAG_IS_BI_FLOW 0x0000010000000000ULL #define PRETAG_IS_MULTICAST 0x0000020000000000ULL #define PRETAG_IS_NSEL 0x0000040000000000ULL #define PRETAG_IS_NEL 0x0000080000000000ULL /* ... */ #define PRETAG_NULL 0x8000000000000000ULL #define PRETAG_MAP_RCODE_ID 0x00000100 #define PRETAG_MAP_RCODE_ID2 0x00000200 #define PRETAG_MAP_RCODE_SET_TOS 0x00000400 #define PRETAG_MAP_RCODE_JEQ 0x00000800 #define BTA_MAP_RCODE_ID_ID2 0x00001000 #define BTA_MAP_RCODE_LOOKUP_BGP_PORT 0x00002000 #define BPAS_MAP_RCODE_BGP 0x00004000 #define PRETAG_MAP_RCODE_LABEL 0x00008000 #define PRETAG_FLAG_NEG 0x00000001 #define PRETAG_FLAG_JEQ 0x00000002 #define PRETAG_IDX_ERR_NONE 0x00000000 #define PRETAG_IDX_ERR_FATAL 0x00000001 #define PRETAG_IDX_ERR_WARN 0x00000002 typedef int (*pretag_handler) (struct packet_ptrs *, void *, void *); typedef pm_id_t (*pretag_stack_handler) (pm_id_t, pm_id_t); typedef u_int64_t pt_bitmap_t; typedef struct { u_int8_t neg; u_int8_t n; } pt_uint8_t; typedef struct { u_int8_t neg; u_int16_t n; } pt_uint16_t; typedef struct { u_int8_t neg; u_int32_t n; } pt_uint32_t; typedef struct { u_int8_t neg; struct host_addr a; } pt_hostaddr_t; typedef struct host_mask pt_hostmask_t; typedef struct { u_int8_t neg; struct host_addr a; struct host_mask m; } pt_netaddr_t; typedef struct { u_int8_t neg; u_char a[ETH_ADDR_LEN]; } pt_etheraddr_t; typedef struct { u_int8_t neg; rd_t rd; } pt_rd_t; typedef struct { char *label; struct id_entry *ptr; } pt_jeq_t; typedef struct { pretag_stack_handler func; } pt_stack_t; /* Pre-Tag table (ptt) element definition */ typedef struct { u_int8_t neg; pm_id_t n; pm_id_t r; } ptt_t; /* Pre-Tag label table (ptlt) element definition */ typedef struct { u_int8_t neg; u_int32_t len; char *v; } ptlt_t; struct id_entry_key { pt_hostaddr_t agent_ip; pt_hostmask_t agent_mask; pt_hostaddr_t nexthop; pt_hostaddr_t bgp_nexthop; pt_uint32_t input; /* input interface index */ pt_uint32_t output; /* output interface index */ pt_uint8_t engine_type; pt_uint32_t engine_id; pt_uint16_t flowset_id; /* applies to NetFlow v9/IPFIX flowset ID */ pt_uint32_t agent_id; /* applies to sFlow agentSubId */ pt_uint32_t sampling_rate; /* applies to sFlow sampling rate */ pt_uint32_t sample_type; /* applies to NetFlow/IPFIX (inferred) & sFlow sample type */ pt_uint8_t is_bi_flow; pt_uint8_t is_nsel; pt_uint8_t is_nel; pt_uint8_t direction; pt_uint8_t nat_event; pt_uint32_t src_as; pt_uint32_t dst_as; pt_uint32_t peer_src_as; pt_uint32_t peer_dst_as; pt_uint32_t src_local_pref; pt_uint32_t local_pref; pt_uint8_t src_roa; pt_uint8_t dst_roa; pt_uint32_t mpls_label_bottom; pt_etheraddr_t src_mac; pt_etheraddr_t dst_mac; pt_uint16_t vlan_id; pt_uint16_t cvlan_id; pt_netaddr_t src_net; pt_netaddr_t dst_net; pt_uint8_t is_multicast; s_uint16_t lookup_bgp_port; char *src_comms[16]; /* XXX: MAX_BGP_COMM_PATTERNS = 16 */ char *comms[16]; /* XXX: MAX_BGP_COMM_PATTERNS = 16 */ pt_uint32_t mpls_vpn_id; pt_rd_t mpls_vpn_rd; pt_uint32_t mpls_pw_id; pt_uint8_t fwd_status; struct bpf_program filter; pt_uint8_t null; }; struct id_entry { pm_id_t id; pm_id_t id2; pt_label_t label; pm_id_t flags; pm_id_t pos; s_uint8_t set_tos; struct id_entry_key key; pretag_handler func[N_MAP_HANDLERS]; pt_bitmap_t func_type[N_MAP_HANDLERS]; pretag_handler set_func[N_MAP_SET_HANDLERS]; pt_bitmap_t set_func_type[N_MAP_SET_HANDLERS]; char *entry_label; pt_jeq_t jeq; u_int8_t ret; pt_stack_t stack; pt_bitmap_t last_matched; u_int8_t id_inc; u_int8_t id2_inc; }; struct id_table_index; /* just to make the compiler swallow the next typedef */ typedef int (*pretag_prep)(struct id_table_index *, int, pm_hash_serial_t *, void *); typedef int (*pretag_copier)(struct id_table_index *, int, int, struct id_entry *, pm_hash_serial_t *, void *); struct id_table_index_netmask_list { cdada_list_t *list; int size; }; struct id_table_index_netmask { struct id_table_index_netmask_list v4; struct id_table_index_netmask_list v6; int hdlr_no; }; struct id_table_index { pt_bitmap_t bitmap; u_int32_t entries; pretag_prep idt_handler[MAX_BITMAP_ENTRIES]; pretag_copier fdata_handler[MAX_BITMAP_ENTRIES]; struct id_table_index_netmask netmask; pm_hash_serial_t hash_serializer; cdada_map_t *idx_map; }; struct id_table { char *filename; int type; unsigned int num; struct id_entry *ipv4_base; unsigned int ipv4_num; struct id_entry *ipv6_base; unsigned int ipv6_num; struct id_entry *e; struct id_table_index index[MAX_ID_TABLE_INDEXES]; unsigned int index_num; time_t timestamp; u_int32_t flags; cdada_map_t *label_map_v4; cdada_map_t *label_map_v6; }; struct _map_dictionary_line { char key[SRVBUFLEN]; int (*func)(char *, struct id_entry *, char *, struct plugin_requests *, int); }; struct _map_index_internal_dictionary_line { pt_bitmap_t key; pretag_prep func; }; struct _map_index_dictionary_line { pt_bitmap_t key; pretag_copier func; }; struct _map_index_size_dictionary_line { pt_bitmap_t key; ssize_t size; }; struct pretag_filter { u_int16_t num; ptt_t table[MAX_PRETAG_MAP_ENTRIES/4]; }; struct pretag_label_filter { u_int16_t num; ptlt_t table[MAX_PRETAG_MAP_ENTRIES/4]; }; /* prototypes */ extern void load_id_file(int, char *, struct id_table *, struct plugin_requests *, int *); extern void load_pre_tag_map(int, char *, struct id_table *, struct plugin_requests *, int *, int, int); extern u_int8_t pt_check_neg(char **, u_int32_t *); extern void pt_set_jeq(u_int32_t *); extern char * pt_check_range(char *); extern void pretag_init_vars(struct packet_ptrs *, struct id_table *); extern void pretag_init_label(pt_label_t *); extern int pretag_malloc_label(pt_label_t *, int); extern int pretag_realloc_label(pt_label_t *, int, int); extern int pretag_copy_label(pt_label_t *, pt_label_t *); extern int pretag_move_label(pt_label_t *, pt_label_t *); extern int pretag_append_label(pt_label_t *, pt_label_t *); extern void pretag_free_label(pt_label_t *); extern int pretag_entry_process(struct id_entry *, struct packet_ptrs *, pm_id_t *, pm_id_t *); extern pt_bitmap_t pretag_index_build_bitmap(struct id_entry *, int); extern int pretag_index_insert_bitmap(struct id_table *, pt_bitmap_t); extern int pretag_index_set_handlers(struct id_table *); extern int pretag_index_allocate(struct id_table *); extern int pretag_index_fill(struct id_table *, pt_bitmap_t, struct id_entry *, int); extern int pretag_index_validate_dedup_netmask_lists(struct id_table *); extern void pretag_index_print_key(const cdada_map_t *, const void *, void *, void *); extern void pretag_index_report(struct id_table *); extern void pretag_index_destroy(struct id_table *); extern u_int32_t pretag_index_lookup(struct id_table *, struct packet_ptrs *, struct id_entry **, int); extern void pretag_index_results_sort(struct id_entry **, int); extern void pretag_index_results_compress_jeqs(struct id_entry **, int); extern int pretag_index_have_one(struct id_table *); extern int bpas_map_allocated; extern int blp_map_allocated; extern int bmed_map_allocated; extern int biss_map_allocated; extern int bta_map_allocated; extern int bitr_map_allocated; extern int sampling_map_allocated; extern int custom_primitives_allocated; extern int bta_map_caching; extern int sampling_map_caching; extern int (*find_id_func)(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *); #endif //PRETAG_H pmacct-1.7.8/src/kafka_common.h0000644000175000017500000001147614354105275015410 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KAFKA_COMMON_H #define KAFKA_COMMON_H /* includes */ #include #include "plugin_common.h" #ifdef WITH_SERDES #include #endif /* defines */ #define PM_KAFKA_ERRSTR_LEN 512 #define PM_KAFKA_DEFAULT_RETRY 60 #define PM_KAFKA_LONGLONG_RETRY INT_MAX #define PM_KAFKA_OUTQ_LEN_RETRIES 3 #define PM_KAFKA_CNT_TYPE_STR 1 #define PM_KAFKA_CNT_TYPE_BIN 2 /* structures */ struct p_kafka_host { char broker[SRVBUFLEN]; char errstr[PM_KAFKA_ERRSTR_LEN]; u_int8_t content_type; rd_kafka_t *rk; rd_kafka_conf_t *cfg; rd_kafka_topic_t *topic; rd_kafka_topic_conf_t *topic_cfg; char *config_file; int partition; char *key; int key_len; struct p_table_rr topic_rr; #ifdef WITH_SERDES serdes_schema_t *sd_schema[MAX_AVRO_SCHEMA]; struct p_broker_timers sd_schema_timers; #endif struct p_broker_timers btimers; }; /* prototypes */ extern void p_kafka_init_host(struct p_kafka_host *, char *); extern void p_kafka_init_host_struct(struct p_kafka_host *); extern void p_kafka_init_host_conf(struct p_kafka_host *, char *); extern void p_kafka_init_topic_rr(struct p_kafka_host *); extern void p_kafka_set_broker(struct p_kafka_host *, char *, int); extern void p_kafka_set_topic(struct p_kafka_host *, char *); extern void p_kafka_set_topic_rr(struct p_kafka_host *, int); extern void p_kafka_set_content_type(struct p_kafka_host *, int); extern void p_kafka_set_partition(struct p_kafka_host *, int); extern void p_kafka_set_key(struct p_kafka_host *, char *, int); extern void p_kafka_set_config_file(struct p_kafka_host *, char *); extern rd_kafka_t *p_kafka_get_handler(struct p_kafka_host *); extern char *p_kafka_get_broker(struct p_kafka_host *); extern char *p_kafka_get_topic(struct p_kafka_host *); extern int p_kafka_get_topic_rr(struct p_kafka_host *); extern int p_kafka_get_content_type(struct p_kafka_host *); extern int p_kafka_get_partition(struct p_kafka_host *); extern void p_kafka_set_dynamic_partitioner(struct p_kafka_host *); extern char *p_kafka_get_key(struct p_kafka_host *); extern void p_kafka_get_version(); extern void p_kafka_unset_topic(struct p_kafka_host *); extern int p_kafka_parse_config_entry(char *, char *, char **, char **); extern void p_kafka_apply_global_config(struct p_kafka_host *); extern void p_kafka_apply_topic_config(struct p_kafka_host *); extern void p_kafka_logger(const rd_kafka_t *, int, const char *, const char *); extern void p_kafka_msg_delivered(rd_kafka_t *, const rd_kafka_message_t *, void *); extern void p_kafka_msg_error(rd_kafka_t *, int, const char *, void *); extern int p_kafka_stats(rd_kafka_t *, char *, size_t, void *); extern int p_kafka_connect_to_produce(struct p_kafka_host *); extern int p_kafka_produce_data(struct p_kafka_host *, void *, size_t); extern int p_kafka_produce_data_and_free(struct p_kafka_host *, void *, size_t); extern int p_kafka_produce_data_to_part(struct p_kafka_host *, void *, size_t, int, int); extern int p_kafka_connect_to_consume(struct p_kafka_host *); extern int p_kafka_manage_consumer(struct p_kafka_host *, int); extern int p_kafka_consume_poller(struct p_kafka_host *, void **, int); extern int p_kafka_consume_data(struct p_kafka_host *, void *, u_char *, size_t); extern void p_kafka_close(struct p_kafka_host *, int); extern int p_kafka_check_outq_len(struct p_kafka_host *); extern int write_and_free_json_kafka(void *, void *); extern int write_binary_kafka(void *, void *, size_t); /* global vars */ extern struct p_kafka_host kafkap_kafka_host; extern struct p_kafka_host bgp_daemon_msglog_kafka_host; extern struct p_kafka_host bmp_daemon_msglog_kafka_host; extern struct p_kafka_host sfacctd_counter_kafka_host; extern struct p_kafka_host telemetry_kafka_host; extern struct p_kafka_host telemetry_daemon_msglog_kafka_host; extern struct p_kafka_host nfacctd_kafka_host; extern int kafkap_ret_err_cb; extern int dyn_partition_key; extern char default_kafka_broker_host[]; extern int default_kafka_broker_port; extern char default_kafka_topic[]; #endif //KAFKA_COMMON_H pmacct-1.7.8/src/classifier.h0000644000175000017500000000360514354105275015102 0ustar paolopaolo/* pmacct (Promiscuous mode IP Accounting package) pmacct is Copyright (C) 2003-2022 by Paolo Lucente */ /* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CLASSIFIER_H #define CLASSIFIER_H #include "conntrack.h" /* defines */ #define MAX_FN_LEN 256 #define MAX_SUBDIRS 128 #define MAX_CLASSIFIERS 512 #define MAX_PATTERN_LEN 2048 #define DEFAULT_TENTATIVES 5 /* data structures */ struct pkt_classifier { pm_class_t id; char protocol[MAX_PROTOCOL_LEN]; #if defined (WITH_NDPI) ndpi_protocol_category_t category; #endif conntrack_helper ct_helper; }; /* All but __CLASSIFIER_C are dummy entries. They are required to export locally the 'class' array. This is in order to avoid to link extra C files into nfacctd and sfacctd */ /* prototypes */ extern void init_classifiers(); extern pm_class_t pmct_register(struct pkt_classifier *); extern pm_class_t pmct_ndpi_register(struct pkt_classifier *); extern void pmct_unregister(pm_class_t); extern pm_class_t pmct_find_first_free(); extern pm_class_t pmct_find_last_free(); extern int pmct_isfree(pm_class_t); extern int pmct_get(pm_class_t, struct pkt_classifier *); extern int pmct_get_num_entries(); extern struct pkt_classifier *class; #endif //CLASSIFIER_H